@alepha/ui 0.18.1 → 0.18.3

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 (280) hide show
  1. package/dist/admin/{AdminApiKeys-C-6_Q-lH.js → AdminApiKeys-Dy_k-4Vd.js} +17 -38
  2. package/dist/admin/AdminApiKeys-Dy_k-4Vd.js.map +1 -0
  3. package/dist/admin/{AdminAudits-Bgbf04hO.js → AdminAudits-CKiFMSSU.js} +23 -19
  4. package/dist/admin/AdminAudits-CKiFMSSU.js.map +1 -0
  5. package/dist/admin/AdminDashboard-PhC_dZqo.js +67 -0
  6. package/dist/admin/AdminDashboard-PhC_dZqo.js.map +1 -0
  7. package/dist/admin/{AdminFiles-B9a7G3cY.js → AdminFiles-DFTjijGp.js} +3 -7
  8. package/dist/admin/AdminFiles-DFTjijGp.js.map +1 -0
  9. package/dist/admin/{AdminJobDashboard-DaTwf5OY.js → AdminJobDashboard-BL8gGPDp.js} +2 -2
  10. package/dist/admin/{AdminJobDashboard-DaTwf5OY.js.map → AdminJobDashboard-BL8gGPDp.js.map} +1 -1
  11. package/dist/admin/{AdminJobExecutions-B9cek5dl.js → AdminJobExecutions-D9E-CS-U.js} +24 -36
  12. package/dist/admin/AdminJobExecutions-D9E-CS-U.js.map +1 -0
  13. package/dist/admin/{AdminJobRegistry-DFgV3oqx.js → AdminJobRegistry-Ci9ue1zC.js} +10 -18
  14. package/dist/admin/AdminJobRegistry-Ci9ue1zC.js.map +1 -0
  15. package/dist/admin/AdminLayout-I6TlUMPc.js +61 -0
  16. package/dist/admin/AdminLayout-I6TlUMPc.js.map +1 -0
  17. package/dist/admin/AdminNotifications-ZPHCYrv7.js +542 -0
  18. package/dist/admin/AdminNotifications-ZPHCYrv7.js.map +1 -0
  19. package/dist/admin/{AdminParameters-DHw9ATgl.js → AdminParameters-CqgvhRsb.js} +120 -105
  20. package/dist/admin/AdminParameters-CqgvhRsb.js.map +1 -0
  21. package/dist/admin/{AdminSessions-BhGJPI3z.js → AdminSessions-Bz5NRuoW.js} +48 -53
  22. package/dist/admin/AdminSessions-Bz5NRuoW.js.map +1 -0
  23. package/dist/admin/{AdminUserLayout-BdC4Te8m.js → AdminUserLayout-lXT6I0Qq.js} +14 -8
  24. package/dist/admin/AdminUserLayout-lXT6I0Qq.js.map +1 -0
  25. package/dist/admin/{AdminUserProfile-DAt23fqY.js → AdminUserProfile-vFBLoJ3h.js} +3 -3
  26. package/dist/admin/{AdminUserProfile-DAt23fqY.js.map → AdminUserProfile-vFBLoJ3h.js.map} +1 -1
  27. package/dist/admin/{AdminUserSessions-1uzcx02z.js → AdminUserSessions-CT_YDim0.js} +33 -35
  28. package/dist/admin/AdminUserSessions-CT_YDim0.js.map +1 -0
  29. package/dist/admin/AdminUsers-D1UfGya9.js +206 -0
  30. package/dist/admin/AdminUsers-D1UfGya9.js.map +1 -0
  31. package/dist/admin/{AuthLayout-DFJvCvzw.js → AuthLayout-_frhdgOO.js} +2 -2
  32. package/dist/admin/{AuthLayout-DFJvCvzw.js.map → AuthLayout-_frhdgOO.js.map} +1 -1
  33. package/dist/admin/{IconGoogle-CSQLPYwX.js → IconGoogle-Ch1m3Uzl.js} +1 -1
  34. package/dist/admin/{IconGoogle-CSQLPYwX.js.map → IconGoogle-Ch1m3Uzl.js.map} +1 -1
  35. package/dist/admin/Login-xtNmQtGh.js +275 -0
  36. package/dist/admin/Login-xtNmQtGh.js.map +1 -0
  37. package/dist/{auth/Profile-BMX_Ar_s.js → admin/Profile-_AtPUwAP.js} +31 -27
  38. package/dist/admin/Profile-_AtPUwAP.js.map +1 -0
  39. package/dist/admin/{Register-Cs10l8vX.js → Register-JcCjHUUn.js} +199 -143
  40. package/dist/admin/Register-JcCjHUUn.js.map +1 -0
  41. package/dist/admin/{ResetPassword-BwDdfkGH.js → ResetPassword-CwGBPLJO.js} +7 -7
  42. package/dist/admin/ResetPassword-CwGBPLJO.js.map +1 -0
  43. package/dist/admin/{VerifyEmail-DfXHAiQl.js → VerifyEmail-hNxWejWf.js} +23 -8
  44. package/dist/admin/VerifyEmail-hNxWejWf.js.map +1 -0
  45. package/dist/admin/{core-2xoLiT0o.js → core-CYaRQ8O-.js} +2082 -688
  46. package/dist/admin/core-CYaRQ8O-.js.map +1 -0
  47. package/dist/admin/index.d.ts +112 -48
  48. package/dist/admin/index.d.ts.map +1 -1
  49. package/dist/admin/index.js +467 -69
  50. package/dist/admin/index.js.map +1 -1
  51. package/dist/auth/{AuthLayout-CAE1pX9s.js → AuthLayout-AvLlcLjS.js} +2 -2
  52. package/dist/auth/{AuthLayout-CAE1pX9s.js.map → AuthLayout-AvLlcLjS.js.map} +1 -1
  53. package/dist/auth/Login-BA1E8IZl.js +275 -0
  54. package/dist/auth/Login-BA1E8IZl.js.map +1 -0
  55. package/dist/{admin/Profile-B-c9pCPf.js → auth/Profile-YcWdeuFz.js} +31 -27
  56. package/dist/auth/Profile-YcWdeuFz.js.map +1 -0
  57. package/dist/auth/{Register-6hi_cpfF.js → Register-CPhEO5MG.js} +198 -142
  58. package/dist/auth/Register-CPhEO5MG.js.map +1 -0
  59. package/dist/{demo/ResetPassword-DWN0lzr5.js → auth/ResetPassword-DCtGcneA.js} +7 -7
  60. package/dist/auth/ResetPassword-DCtGcneA.js.map +1 -0
  61. package/dist/{demo/VerifyEmail-DZWL72K4.js → auth/VerifyEmail-DkH7NBfn.js} +23 -8
  62. package/dist/auth/VerifyEmail-DkH7NBfn.js.map +1 -0
  63. package/dist/auth/{core-niW0sFLv.js → core-D5jIAVF2.js} +1385 -329
  64. package/dist/auth/core-D5jIAVF2.js.map +1 -0
  65. package/dist/auth/index.d.ts +105 -49
  66. package/dist/auth/index.d.ts.map +1 -1
  67. package/dist/auth/index.js +29 -26
  68. package/dist/auth/index.js.map +1 -1
  69. package/dist/core/index.d.ts +210 -74
  70. package/dist/core/index.d.ts.map +1 -1
  71. package/dist/core/index.js +2247 -834
  72. package/dist/core/index.js.map +1 -1
  73. package/dist/demo/{AuthLayout-jLa0aKsI.js → AuthLayout-Brri4A-L.js} +2 -2
  74. package/dist/demo/{AuthLayout-jLa0aKsI.js.map → AuthLayout-Brri4A-L.js.map} +1 -1
  75. package/dist/demo/DemoButton-wiCxZZ_L.js +182 -0
  76. package/dist/demo/DemoButton-wiCxZZ_L.js.map +1 -0
  77. package/dist/demo/DemoControlSelect-D7ILObVg.js +305 -0
  78. package/dist/demo/DemoControlSelect-D7ILObVg.js.map +1 -0
  79. package/dist/demo/DemoDataTable-DZ5Y8pFX.js +362 -0
  80. package/dist/demo/DemoDataTable-DZ5Y8pFX.js.map +1 -0
  81. package/dist/demo/{DemoDialog-4ItHLf9t.js → DemoDialog-CUWdLHim.js} +2 -2
  82. package/dist/demo/{DemoDialog-4ItHLf9t.js.map → DemoDialog-CUWdLHim.js.map} +1 -1
  83. package/dist/demo/{DemoFlex-EtVq8QfX.js → DemoFlex-a8OhMMvq.js} +3 -3
  84. package/dist/demo/{DemoFlex-EtVq8QfX.js.map → DemoFlex-a8OhMMvq.js.map} +1 -1
  85. package/dist/demo/{DemoHeading-BS-vGfkI.js → DemoHeading-C13OVDfS.js} +3 -3
  86. package/dist/demo/{DemoHeading-BS-vGfkI.js.map → DemoHeading-C13OVDfS.js.map} +1 -1
  87. package/dist/demo/{DemoHome-Clbn8AmS.js → DemoHome-D_De3UiT.js} +2 -2
  88. package/dist/demo/{DemoHome-Clbn8AmS.js.map → DemoHome-D_De3UiT.js.map} +1 -1
  89. package/dist/demo/{DemoJsonViewer-DkIX_ky2.js → DemoJsonViewer-B50s9aGM.js} +3 -3
  90. package/dist/demo/{DemoJsonViewer-DkIX_ky2.js.map → DemoJsonViewer-B50s9aGM.js.map} +1 -1
  91. package/dist/demo/{DemoLayout-C56xb5EE.js → DemoLayout-CHU8WTwO.js} +14 -5
  92. package/dist/demo/DemoLayout-CHU8WTwO.js.map +1 -0
  93. package/dist/demo/{DemoLogin-BZwpicOS.js → DemoLogin-BBlrWpml.js} +49 -32
  94. package/dist/demo/DemoLogin-BBlrWpml.js.map +1 -0
  95. package/dist/demo/{DemoRegister-C7_qc4MJ.js → DemoRegister-BuNE3_-f.js} +49 -50
  96. package/dist/demo/DemoRegister-BuNE3_-f.js.map +1 -0
  97. package/dist/demo/{DemoResetPassword-BI1Ct4Dw.js → DemoResetPassword-D_IjjjOJ.js} +12 -16
  98. package/dist/demo/DemoResetPassword-D_IjjjOJ.js.map +1 -0
  99. package/dist/demo/{DemoSidebar-CcBo4ltC.js → DemoSidebar-Giy2HRBD.js} +3 -3
  100. package/dist/demo/{DemoSidebar-CcBo4ltC.js.map → DemoSidebar-Giy2HRBD.js.map} +1 -1
  101. package/dist/demo/{DemoText-CzXuUn3g.js → DemoText-ubcw-vog.js} +3 -3
  102. package/dist/demo/{DemoText-CzXuUn3g.js.map → DemoText-ubcw-vog.js.map} +1 -1
  103. package/dist/demo/{DemoToast-BgHDhWrX.js → DemoToast-9die_dYT.js} +2 -2
  104. package/dist/demo/{DemoToast-BgHDhWrX.js.map → DemoToast-9die_dYT.js.map} +1 -1
  105. package/dist/demo/{DemoTypeForm-DDzWoMSV.js → DemoTypeForm-D_d6OVKL.js} +8 -4
  106. package/dist/demo/DemoTypeForm-D_d6OVKL.js.map +1 -0
  107. package/dist/demo/DemoVerifyEmail-B43KlF4F.js +34 -0
  108. package/dist/demo/DemoVerifyEmail-B43KlF4F.js.map +1 -0
  109. package/dist/demo/Login-C12N4oGs.js +275 -0
  110. package/dist/demo/Login-C12N4oGs.js.map +1 -0
  111. package/dist/demo/{Profile-CWqti7FB.js → Profile-DS5q4vOh.js} +31 -27
  112. package/dist/demo/Profile-DS5q4vOh.js.map +1 -0
  113. package/dist/demo/{Register-a70LPgs2.js → Register-B4hLBeEv.js} +198 -142
  114. package/dist/demo/Register-B4hLBeEv.js.map +1 -0
  115. package/dist/{auth/ResetPassword-CqfTk1FI.js → demo/ResetPassword-D8g9ha1N.js} +7 -7
  116. package/dist/demo/ResetPassword-D8g9ha1N.js.map +1 -0
  117. package/dist/demo/{Showcase-Dq3MISpd.js → Showcase-D6Fxt4X4.js} +64 -65
  118. package/dist/demo/Showcase-D6Fxt4X4.js.map +1 -0
  119. package/dist/{auth/VerifyEmail-nWiSTMjF.js → demo/VerifyEmail-BjDo0cZA.js} +23 -8
  120. package/dist/demo/VerifyEmail-BjDo0cZA.js.map +1 -0
  121. package/dist/demo/{auth-d6n3xbug.js → auth-ByVTreDl.js} +8 -8
  122. package/dist/demo/{auth-d6n3xbug.js.map → auth-ByVTreDl.js.map} +1 -1
  123. package/dist/demo/{core-RCUw1Q-a.js → core-DFgB3yU4.js} +2182 -756
  124. package/dist/demo/core-DFgB3yU4.js.map +1 -0
  125. package/dist/demo/index.d.ts +1 -0
  126. package/dist/demo/index.d.ts.map +1 -1
  127. package/dist/demo/index.js +24 -18
  128. package/dist/demo/index.js.map +1 -1
  129. package/package.json +7 -7
  130. package/src/admin/{AdminRouter.ts → AdminRouter.tsx} +150 -18
  131. package/src/admin/components/AdminDashboard.tsx +52 -0
  132. package/src/admin/components/AdminLayout.tsx +32 -40
  133. package/src/admin/components/audits/AdminAudits.tsx +22 -16
  134. package/src/admin/components/files/AdminFiles.tsx +1 -6
  135. package/src/admin/components/jobs/AdminJobExecutions.tsx +33 -39
  136. package/src/admin/components/jobs/AdminJobRegistry.tsx +9 -18
  137. package/src/admin/components/keys/AdminApiKeys.tsx +23 -41
  138. package/src/admin/components/notifications/AdminNotifications.tsx +519 -0
  139. package/src/admin/components/parameters/ParameterDetails.tsx +12 -270
  140. package/src/admin/components/parameters/ParameterDetailsConfigForm.tsx +238 -0
  141. package/src/admin/components/parameters/ParameterDetailsLoading.tsx +24 -0
  142. package/src/admin/components/parameters/ParameterHistory.tsx +10 -11
  143. package/src/admin/components/parameters/ParameterTree.tsx +28 -184
  144. package/src/admin/components/parameters/ParameterTreeNode.tsx +151 -0
  145. package/src/admin/components/sessions/AdminSessions.tsx +71 -71
  146. package/src/admin/components/shared/AdminResourceHeader.tsx +2 -25
  147. package/src/admin/components/shared/AdminResourceHeaderMenuItem.tsx +37 -0
  148. package/src/admin/components/shared/AdminResourceTabs.tsx +2 -26
  149. package/src/admin/components/shared/AdminResourceTabsItem.tsx +36 -0
  150. package/src/admin/components/users/AdminUserSessions.tsx +33 -31
  151. package/src/admin/components/users/AdminUsers.tsx +184 -72
  152. package/src/admin/index.ts +2 -2
  153. package/src/admin/primitives/$uiAdmin.ts +1 -1
  154. package/src/auth/components/Login.tsx +188 -121
  155. package/src/auth/components/Profile.tsx +1 -22
  156. package/src/auth/components/ProfileField.tsx +39 -0
  157. package/src/auth/components/Register.tsx +215 -158
  158. package/src/auth/components/ResetPassword.tsx +7 -11
  159. package/src/auth/components/VerifyEmail.tsx +35 -10
  160. package/src/auth/components/buttons/UserButton.tsx +20 -24
  161. package/src/auth/index.ts +1 -0
  162. package/src/core/atoms/alephaSidebarAtom.ts +1 -1
  163. package/src/core/atoms/alephaThemeListAtom.ts +14 -1
  164. package/src/core/atoms/alephaThemeOverridesAtom.ts +17 -0
  165. package/src/core/atoms/themes/editorial.ts +184 -0
  166. package/src/core/atoms/themes/monochrome.ts +197 -0
  167. package/src/core/atoms/themes/rosePine.ts +208 -0
  168. package/src/core/atoms/themes/softBrutalism.ts +221 -0
  169. package/src/core/atoms/themes/terminal.ts +186 -0
  170. package/src/core/components/Flex.tsx +101 -1
  171. package/src/core/components/Text.tsx +1 -1
  172. package/src/core/components/buttons/ActionButton.tsx +109 -87
  173. package/src/core/components/buttons/DarkModeButton.tsx +3 -3
  174. package/src/core/components/buttons/LanguageButton.tsx +1 -1
  175. package/src/core/components/buttons/OmnibarButton.tsx +1 -2
  176. package/src/core/components/buttons/ThemeButton.tsx +40 -11
  177. package/src/core/components/buttons/ThemeExpertModal.tsx +184 -0
  178. package/src/core/components/buttons/ToggleSidebarButton.tsx +1 -2
  179. package/src/core/components/data/DetailDrawer.tsx +102 -96
  180. package/src/core/components/data/DetailList.tsx +2 -1
  181. package/src/core/components/layout/AppBar.tsx +10 -0
  182. package/src/core/components/layout/Breadcrumb.tsx +3 -6
  183. package/src/core/components/layout/DashboardShell.tsx +28 -11
  184. package/src/core/components/layout/Sidebar.tsx +18 -235
  185. package/src/core/components/layout/SidebarCollapsedItem.tsx +91 -0
  186. package/src/core/components/layout/SidebarItem.tsx +146 -0
  187. package/src/core/components/layout/index.ts +3 -1
  188. package/src/core/constants/ui.ts +5 -5
  189. package/src/core/form/components/Control.tsx +31 -29
  190. package/src/core/form/components/ControlArray.tsx +13 -39
  191. package/src/core/form/components/ControlDate.tsx +10 -21
  192. package/src/core/form/components/ControlNumber.tsx +4 -33
  193. package/src/core/form/components/ControlQueryBuilder.tsx +12 -175
  194. package/src/core/form/components/ControlQueryBuilderHelp.tsx +165 -0
  195. package/src/core/form/components/ControlSelect.browser.spec.tsx +343 -0
  196. package/src/core/form/components/ControlSelect.tsx +294 -92
  197. package/src/core/form/components/TypeForm.browser.spec.tsx +3 -3
  198. package/src/core/form/components/TypeForm.tsx +5 -2
  199. package/src/core/form/index.ts +8 -1
  200. package/src/core/form/utils/parseInput.ts +7 -3
  201. package/src/core/hooks/useTheme.ts +26 -3
  202. package/src/core/index.ts +9 -2
  203. package/src/core/interfaces/AlephaTheme.ts +2 -0
  204. package/src/core/json/components/JsonViewer.tsx +103 -319
  205. package/src/core/json/components/JsonViewerCopyButton.tsx +46 -0
  206. package/src/core/json/components/JsonViewerRowNode.tsx +120 -0
  207. package/src/core/json/components/JsonViewerShared.ts +76 -0
  208. package/src/core/providers/ThemeProvider.ts +108 -8
  209. package/src/core/services/DialogService.tsx +24 -3
  210. package/src/core/styles.css +33 -20
  211. package/src/core/table/components/ColumnPicker.tsx +3 -3
  212. package/src/core/table/components/DataTable.tsx +233 -143
  213. package/src/core/table/components/DataTableFilters.tsx +6 -16
  214. package/src/core/table/components/DataTablePagination.tsx +58 -29
  215. package/src/core/table/components/DataTableToolbar.tsx +16 -7
  216. package/src/core/table/components/FilterPicker.tsx +3 -3
  217. package/src/core/table/index.ts +1 -0
  218. package/src/core/table/interfaces/types.ts +42 -9
  219. package/src/core/utils/icons.tsx +2 -2
  220. package/src/demo/DemoRouter.ts +8 -1
  221. package/src/demo/components/DemoLayout.tsx +12 -2
  222. package/src/demo/components/auth/DemoLogin.tsx +35 -28
  223. package/src/demo/components/auth/DemoRegister.tsx +35 -49
  224. package/src/demo/components/auth/DemoResetPassword.tsx +5 -9
  225. package/src/demo/components/auth/DemoVerifyEmail.tsx +7 -6
  226. package/src/demo/components/core/DemoButton.tsx +123 -103
  227. package/src/demo/components/core/DemoControlSelect.tsx +325 -0
  228. package/src/demo/components/core/DemoDataTable.tsx +255 -241
  229. package/src/demo/components/core/DemoTypeForm.tsx +7 -2
  230. package/src/demo/components/shared/MacWindow.tsx +5 -11
  231. package/src/demo/components/shared/Showcase.tsx +28 -42
  232. package/dist/admin/AdminApiKeys-C-6_Q-lH.js.map +0 -1
  233. package/dist/admin/AdminAudits-Bgbf04hO.js.map +0 -1
  234. package/dist/admin/AdminFiles-B9a7G3cY.js.map +0 -1
  235. package/dist/admin/AdminJobExecutions-B9cek5dl.js.map +0 -1
  236. package/dist/admin/AdminJobRegistry-DFgV3oqx.js.map +0 -1
  237. package/dist/admin/AdminLayout-DHsvWxVB.js +0 -70
  238. package/dist/admin/AdminLayout-DHsvWxVB.js.map +0 -1
  239. package/dist/admin/AdminParameters-DHw9ATgl.js.map +0 -1
  240. package/dist/admin/AdminSessions-BhGJPI3z.js.map +0 -1
  241. package/dist/admin/AdminUserLayout-BdC4Te8m.js.map +0 -1
  242. package/dist/admin/AdminUserSessions-1uzcx02z.js.map +0 -1
  243. package/dist/admin/AdminUsers-C85c3eiQ.js +0 -121
  244. package/dist/admin/AdminUsers-C85c3eiQ.js.map +0 -1
  245. package/dist/admin/Login-BGheURrg.js +0 -219
  246. package/dist/admin/Login-BGheURrg.js.map +0 -1
  247. package/dist/admin/Profile-B-c9pCPf.js.map +0 -1
  248. package/dist/admin/Register-Cs10l8vX.js.map +0 -1
  249. package/dist/admin/ResetPassword-BwDdfkGH.js.map +0 -1
  250. package/dist/admin/VerifyEmail-DfXHAiQl.js.map +0 -1
  251. package/dist/admin/auth-Dr0Cf8I7.js +0 -319
  252. package/dist/admin/auth-Dr0Cf8I7.js.map +0 -1
  253. package/dist/admin/core-2xoLiT0o.js.map +0 -1
  254. package/dist/auth/Login-Denw_UGy.js +0 -219
  255. package/dist/auth/Login-Denw_UGy.js.map +0 -1
  256. package/dist/auth/Profile-BMX_Ar_s.js.map +0 -1
  257. package/dist/auth/Register-6hi_cpfF.js.map +0 -1
  258. package/dist/auth/ResetPassword-CqfTk1FI.js.map +0 -1
  259. package/dist/auth/VerifyEmail-nWiSTMjF.js.map +0 -1
  260. package/dist/auth/core-niW0sFLv.js.map +0 -1
  261. package/dist/demo/DemoButton-BmaWZVwf.js +0 -178
  262. package/dist/demo/DemoButton-BmaWZVwf.js.map +0 -1
  263. package/dist/demo/DemoDataTable-Z9xyV221.js +0 -362
  264. package/dist/demo/DemoDataTable-Z9xyV221.js.map +0 -1
  265. package/dist/demo/DemoLayout-C56xb5EE.js.map +0 -1
  266. package/dist/demo/DemoLogin-BZwpicOS.js.map +0 -1
  267. package/dist/demo/DemoRegister-C7_qc4MJ.js.map +0 -1
  268. package/dist/demo/DemoResetPassword-BI1Ct4Dw.js.map +0 -1
  269. package/dist/demo/DemoTypeForm-DDzWoMSV.js.map +0 -1
  270. package/dist/demo/DemoVerifyEmail-C_Irdnov.js +0 -30
  271. package/dist/demo/DemoVerifyEmail-C_Irdnov.js.map +0 -1
  272. package/dist/demo/Login-hSOU3jZc.js +0 -219
  273. package/dist/demo/Login-hSOU3jZc.js.map +0 -1
  274. package/dist/demo/Profile-CWqti7FB.js.map +0 -1
  275. package/dist/demo/Register-a70LPgs2.js.map +0 -1
  276. package/dist/demo/ResetPassword-DWN0lzr5.js.map +0 -1
  277. package/dist/demo/Showcase-Dq3MISpd.js.map +0 -1
  278. package/dist/demo/VerifyEmail-DZWL72K4.js.map +0 -1
  279. package/dist/demo/core-RCUw1Q-a.js.map +0 -1
  280. package/src/demo/styles.css +0 -0
@@ -1,14 +1,14 @@
1
1
  import { $atom, $context, $inject, $module, Alepha, AlephaError, TypeBoxError, t } from "alepha";
2
- import { AlephaReactForm, FormValidationError, useForm, useFormState } from "alepha/react/form";
3
- import { $head, AlephaReactHead } from "alepha/react/head";
2
+ import { AlephaReactForm, FormValidationError, useFieldValue, useForm, useFormState } from "alepha/react/form";
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";
6
+ import { ActionIcon, Anchor, AppShell, Autocomplete, Badge, Burger, Button, Card, Checkbox, ColorInput, ColorSchemeScript, ColorSwatch, Container, Divider, Drawer, Fieldset, FileInput, Flex, Grid, Image, Input, Kbd, Loader, MantineProvider, Menu, MultiSelect, NumberInput, Pagination, Paper, PasswordInput, Popover, ScrollArea, SegmentedControl, Select, SimpleGrid, Slider, Switch, Table, TagsInput, Text, TextInput, Textarea, Tooltip, Tree, UnstyledButton, getTreeExpandedState, useMantineColorScheme, useMantineTheme, useTree } from "@mantine/core";
6
7
  import { ModalsProvider, modals } from "@mantine/modals";
7
- import { ActionIcon, Anchor, AppShell, Autocomplete, Badge, Burger, Button, Card, Checkbox, ColorInput, ColorSchemeScript, Container, Divider, Drawer, Fieldset, FileInput, Flex, Grid, Image, Input, Kbd, Loader, MantineProvider, Menu, MultiSelect, NumberInput, Pagination, Paper, PasswordInput, Popover, ScrollArea, SegmentedControl, Select, Slider, Switch, Table, TagsInput, Text, TextInput, Textarea, ThemeIcon, Tooltip, Tree, UnstyledButton, getTreeExpandedState, useMantineColorScheme, useMantineTheme, useTree } from "@mantine/core";
8
8
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
9
  import { Children, Fragment as Fragment$1, createElement, forwardRef, isValidElement, useCallback, useEffect, useMemo, useRef, useState } from "react";
10
10
  import { Notifications, notifications } from "@mantine/notifications";
11
- import { IconAlertTriangle, IconArrowDown, IconArrowLeft, IconArrowUp, IconArrowsSort, IconAt, IconCalendar, IconCheck, IconChevronDown, IconChevronRight, IconClipboard, IconClock, IconColorPicker, IconColumns, IconCopy, IconDownload, IconFile, IconFilter, IconGripVertical, IconHash, IconInfoCircle, IconInfoTriangle, IconKey, IconLanguage, IconLayoutSidebarLeftCollapse, IconLayoutSidebarRightCollapse, IconLetterCase, IconLink, IconList, IconMail, IconMoon, IconPalette, IconPhone, IconPlus, IconRefresh, IconSearch, IconSelector, IconSquareRounded, IconSun, IconToggleLeft, IconTrash, IconX } from "@tabler/icons-react";
11
+ import { IconAlertTriangle, IconArrowDown, IconArrowLeft, IconArrowUp, IconArrowsSort, IconAt, IconCalendar, IconCheck, IconChevronDown, IconChevronRight, IconClipboard, IconClock, IconColorPicker, IconColumns, IconCopy, IconDotsVertical, IconDownload, IconFile, IconFilter, IconGripVertical, IconHash, IconInfoCircle, IconInfoTriangle, IconKey, IconLanguage, IconLayoutSidebarLeftCollapse, IconLayoutSidebarRightCollapse, IconLetterCase, IconLink, IconList, IconMail, IconMoon, IconPalette, IconPhone, IconPlus, IconRefresh, IconSearch, IconSelector, IconSquareRounded, IconSun, IconToggleLeft, IconTrash, IconX } from "@tabler/icons-react";
12
12
  import { $page, Link, NestedView, useActive, useRouter, useRouterState } from "alepha/react/router";
13
13
  import { NavigationProgress, nprogress } from "@mantine/nprogress";
14
14
  import { ClientOnly, useAction, useAlepha, useEvents, useInject, useStore } from "alepha/react";
@@ -32,7 +32,7 @@ const alephaSidebarAtom = $atom({
32
32
  closed: true,
33
33
  collapsed: false,
34
34
  expandedWidth: 300,
35
- collapsedWidth: 78
35
+ collapsedWidth: 72
36
36
  }
37
37
  });
38
38
 
@@ -44,6 +44,20 @@ const alephaThemeAtom = $atom({
44
44
  default: { index: 0 }
45
45
  });
46
46
 
47
+ //#endregion
48
+ //#region ../../src/core/atoms/alephaThemeOverridesAtom.ts
49
+ const alephaThemeOverridesAtom = $atom({
50
+ name: "alepha.ui.themeOverrides",
51
+ schema: t.object({
52
+ primaryColor: t.optional(t.text()),
53
+ radius: t.optional(t.text()),
54
+ fontFamily: t.optional(t.text()),
55
+ fontSize: t.optional(t.text()),
56
+ scale: t.optional(t.text())
57
+ }),
58
+ default: {}
59
+ });
60
+
47
61
  //#endregion
48
62
  //#region ../../src/core/atoms/themes/default.ts
49
63
  const defaultTheme = {
@@ -51,6 +65,161 @@ const defaultTheme = {
51
65
  description: "Default Alepha Theme"
52
66
  };
53
67
 
68
+ //#endregion
69
+ //#region ../../src/core/atoms/themes/editorial.ts
70
+ /**
71
+ * Editorial theme.
72
+ *
73
+ * Serif typography, high contrast black and white, thin borders, generous whitespace.
74
+ * Newspaper/magazine aesthetic — elegant restraint.
75
+ */
76
+ const editorialTheme = {
77
+ name: "Editorial",
78
+ description: "Serif typography with newspaper elegance",
79
+ defaultColorScheme: "light",
80
+ head: { link: [
81
+ {
82
+ rel: "preconnect",
83
+ href: "https://fonts.googleapis.com"
84
+ },
85
+ {
86
+ rel: "preconnect",
87
+ href: "https://fonts.gstatic.com",
88
+ crossorigin: ""
89
+ },
90
+ {
91
+ rel: "stylesheet",
92
+ href: "https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;600;700;800&family=Source+Serif+4:ital,wght@0,300;0,400;0,600;1,300;1,400&display=swap"
93
+ }
94
+ ] },
95
+ primaryColor: "ink",
96
+ primaryShade: {
97
+ light: 7,
98
+ dark: 3
99
+ },
100
+ autoContrast: true,
101
+ fontFamily: "\"Source Serif 4\", \"Georgia\", \"Times New Roman\", serif",
102
+ fontFamilyMonospace: "ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, \"Liberation Mono\", monospace",
103
+ headings: {
104
+ fontFamily: "\"Playfair Display\", \"Georgia\", \"Times New Roman\", serif",
105
+ fontWeight: "700",
106
+ textWrap: "wrap",
107
+ sizes: {
108
+ h1: {
109
+ fontSize: "2.5rem",
110
+ lineHeight: "1.15"
111
+ },
112
+ h2: {
113
+ fontSize: "1.75rem",
114
+ lineHeight: "1.2"
115
+ },
116
+ h3: {
117
+ fontSize: "1.375rem",
118
+ lineHeight: "1.3"
119
+ },
120
+ h4: {
121
+ fontSize: "1.125rem",
122
+ lineHeight: "1.4"
123
+ },
124
+ h5: {
125
+ fontSize: "1rem",
126
+ lineHeight: "1.5"
127
+ },
128
+ h6: {
129
+ fontSize: "0.875rem",
130
+ lineHeight: "1.5"
131
+ }
132
+ }
133
+ },
134
+ defaultRadius: "sm",
135
+ radius: {
136
+ xs: "2px",
137
+ sm: "3px",
138
+ md: "4px",
139
+ lg: "6px",
140
+ xl: "8px"
141
+ },
142
+ shadows: {
143
+ xs: "0 1px 2px rgba(0, 0, 0, 0.06)",
144
+ sm: "0 1px 3px rgba(0, 0, 0, 0.08)",
145
+ md: "0 2px 6px rgba(0, 0, 0, 0.08)",
146
+ lg: "0 4px 12px rgba(0, 0, 0, 0.1)",
147
+ xl: "0 8px 24px rgba(0, 0, 0, 0.1)"
148
+ },
149
+ colors: {
150
+ ink: [
151
+ "#f5f3f0",
152
+ "#e8e4de",
153
+ "#d4cec5",
154
+ "#b5ad9f",
155
+ "#8c8272",
156
+ "#6b6050",
157
+ "#4a4035",
158
+ "#332b22",
159
+ "#1f1812",
160
+ "#0d0a07"
161
+ ],
162
+ burgundy: [
163
+ "#faf0f0",
164
+ "#f0d4d4",
165
+ "#e0adad",
166
+ "#cc8585",
167
+ "#b35e5e",
168
+ "#944545",
169
+ "#763636",
170
+ "#5a2828",
171
+ "#3d1b1b",
172
+ "#220f0f"
173
+ ],
174
+ gray: [
175
+ "#faf9f7",
176
+ "#f0eee9",
177
+ "#e0dcd5",
178
+ "#c8c2b8",
179
+ "#a8a194",
180
+ "#8a8273",
181
+ "#6b6456",
182
+ "#504a3f",
183
+ "#36322b",
184
+ "#1e1b17"
185
+ ],
186
+ dark: [
187
+ "#d5d2cd",
188
+ "#aba59c",
189
+ "#817a6e",
190
+ "#5e584e",
191
+ "#46413a",
192
+ "#36322c",
193
+ "#2a2721",
194
+ "#201d19",
195
+ "#171411",
196
+ "#0d0b09"
197
+ ]
198
+ },
199
+ components: {
200
+ Button: Button.extend({
201
+ defaultProps: { fw: 600 },
202
+ styles: { root: { letterSpacing: "0.02em" } }
203
+ }),
204
+ ActionIcon: ActionIcon.extend({ styles: { root: { border: "1px solid var(--mantine-color-default-border)" } } }),
205
+ Paper: Paper.extend({ styles: { root: { border: "1px solid var(--mantine-color-default-border)" } } }),
206
+ Card: Card.extend({ styles: { root: { border: "1px solid var(--mantine-color-default-border)" } } }),
207
+ TextInput: TextInput.extend({ styles: { input: { border: "1px solid var(--mantine-color-default-border)" } } }),
208
+ Badge: Badge.extend({
209
+ defaultProps: {
210
+ fw: 600,
211
+ variant: "outline"
212
+ },
213
+ styles: { root: {
214
+ fontFamily: "-apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif",
215
+ letterSpacing: "0.04em",
216
+ textTransform: "uppercase",
217
+ fontSize: "0.65rem"
218
+ } }
219
+ })
220
+ }
221
+ };
222
+
54
223
  //#endregion
55
224
  //#region ../../src/core/atoms/themes/midnight.ts
56
225
  const midnightTheme = {
@@ -166,41 +335,793 @@ const midnightTheme = {
166
335
  }
167
336
  };
168
337
 
338
+ //#endregion
339
+ //#region ../../src/core/atoms/themes/monochrome.ts
340
+ /**
341
+ * Monochrome theme.
342
+ *
343
+ * Pure black and white. No color. Bold typography does all the heavy lifting.
344
+ * A design-school statement piece — minimalist color, maximalist type.
345
+ */
346
+ const monochromeTheme = {
347
+ name: "Monochrome",
348
+ description: "Pure black and white — zero color, maximum typography",
349
+ primaryColor: "mono",
350
+ primaryShade: {
351
+ light: 8,
352
+ dark: 1
353
+ },
354
+ autoContrast: true,
355
+ fontFamily: "-apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Noto Sans\", Helvetica, Arial, sans-serif",
356
+ fontFamilyMonospace: "ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, \"Liberation Mono\", monospace",
357
+ headings: {
358
+ fontFamily: "-apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Noto Sans\", Helvetica, Arial, sans-serif",
359
+ fontWeight: "800",
360
+ textWrap: "wrap",
361
+ sizes: {
362
+ h1: {
363
+ fontSize: "2.25rem",
364
+ lineHeight: "1.15"
365
+ },
366
+ h2: {
367
+ fontSize: "1.625rem",
368
+ lineHeight: "1.25"
369
+ },
370
+ h3: {
371
+ fontSize: "1.25rem",
372
+ lineHeight: "1.35"
373
+ },
374
+ h4: {
375
+ fontSize: "1.0625rem",
376
+ lineHeight: "1.45"
377
+ },
378
+ h5: {
379
+ fontSize: "0.9375rem",
380
+ lineHeight: "1.5"
381
+ },
382
+ h6: {
383
+ fontSize: "0.8125rem",
384
+ lineHeight: "1.5"
385
+ }
386
+ }
387
+ },
388
+ defaultRadius: "0",
389
+ radius: {
390
+ xs: "0",
391
+ sm: "0",
392
+ md: "0",
393
+ lg: "0",
394
+ xl: "2px"
395
+ },
396
+ shadows: {
397
+ xs: "0 1px 2px rgba(0, 0, 0, 0.08)",
398
+ sm: "0 1px 4px rgba(0, 0, 0, 0.1)",
399
+ md: "0 2px 8px rgba(0, 0, 0, 0.12)",
400
+ lg: "0 4px 16px rgba(0, 0, 0, 0.14)",
401
+ xl: "0 8px 32px rgba(0, 0, 0, 0.16)"
402
+ },
403
+ colors: {
404
+ mono: [
405
+ "#f5f5f5",
406
+ "#e0e0e0",
407
+ "#c0c0c0",
408
+ "#a0a0a0",
409
+ "#808080",
410
+ "#606060",
411
+ "#404040",
412
+ "#282828",
413
+ "#141414",
414
+ "#000000"
415
+ ],
416
+ gray: [
417
+ "#f5f5f5",
418
+ "#e5e5e5",
419
+ "#cccccc",
420
+ "#b0b0b0",
421
+ "#909090",
422
+ "#707070",
423
+ "#555555",
424
+ "#3a3a3a",
425
+ "#252525",
426
+ "#121212"
427
+ ],
428
+ blue: [
429
+ "#f5f5f5",
430
+ "#e0e0e0",
431
+ "#c0c0c0",
432
+ "#a0a0a0",
433
+ "#808080",
434
+ "#606060",
435
+ "#404040",
436
+ "#282828",
437
+ "#141414",
438
+ "#000000"
439
+ ],
440
+ green: [
441
+ "#f5f5f5",
442
+ "#e0e0e0",
443
+ "#c0c0c0",
444
+ "#a0a0a0",
445
+ "#808080",
446
+ "#606060",
447
+ "#404040",
448
+ "#282828",
449
+ "#141414",
450
+ "#000000"
451
+ ],
452
+ red: [
453
+ "#f5f5f5",
454
+ "#e0e0e0",
455
+ "#c0c0c0",
456
+ "#a0a0a0",
457
+ "#808080",
458
+ "#606060",
459
+ "#404040",
460
+ "#282828",
461
+ "#141414",
462
+ "#000000"
463
+ ],
464
+ dark: [
465
+ "#d0d0d0",
466
+ "#a0a0a0",
467
+ "#707070",
468
+ "#505050",
469
+ "#383838",
470
+ "#282828",
471
+ "#1c1c1c",
472
+ "#141414",
473
+ "#0a0a0a",
474
+ "#000000"
475
+ ]
476
+ },
477
+ components: {
478
+ Button: Button.extend({
479
+ defaultProps: { fw: 700 },
480
+ styles: { root: {
481
+ border: "2px solid currentColor",
482
+ letterSpacing: "0.03em",
483
+ textTransform: "uppercase",
484
+ fontSize: "0.8125rem"
485
+ } }
486
+ }),
487
+ ActionIcon: ActionIcon.extend({ styles: { root: { border: "2px solid currentColor" } } }),
488
+ Paper: Paper.extend({ styles: { root: { border: "2px solid var(--mantine-color-default-border)" } } }),
489
+ Card: Card.extend({ styles: { root: { border: "2px solid var(--mantine-color-default-border)" } } }),
490
+ TextInput: TextInput.extend({ styles: { input: { border: "2px solid var(--mantine-color-default-border)" } } }),
491
+ Badge: Badge.extend({
492
+ defaultProps: {
493
+ fw: 700,
494
+ variant: "outline"
495
+ },
496
+ styles: { root: {
497
+ textTransform: "uppercase",
498
+ letterSpacing: "0.06em",
499
+ fontSize: "0.65rem",
500
+ border: "2px solid currentColor"
501
+ } }
502
+ })
503
+ }
504
+ };
505
+
506
+ //#endregion
507
+ //#region ../../src/core/atoms/themes/rosePine.ts
508
+ /**
509
+ * Rosé Pine theme.
510
+ *
511
+ * Muted pinks, golds, and subtle greens on warm dark backgrounds.
512
+ * Cozy, low-contrast, easy on the eyes.
513
+ * Based on the Rosé Pine color philosophy.
514
+ */
515
+ const rosePineTheme = {
516
+ name: "Rosé Pine",
517
+ description: "Muted pinks and golds on warm dark backgrounds",
518
+ defaultColorScheme: "dark",
519
+ primaryColor: "rose",
520
+ primaryShade: {
521
+ light: 5,
522
+ dark: 4
523
+ },
524
+ autoContrast: true,
525
+ fontFamily: "-apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Noto Sans\", Helvetica, Arial, sans-serif",
526
+ fontFamilyMonospace: "ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, \"Liberation Mono\", monospace",
527
+ headings: {
528
+ fontFamily: "-apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Noto Sans\", Helvetica, Arial, sans-serif",
529
+ fontWeight: "600",
530
+ textWrap: "wrap",
531
+ sizes: {
532
+ h1: {
533
+ fontSize: "2rem",
534
+ lineHeight: "1.25"
535
+ },
536
+ h2: {
537
+ fontSize: "1.5rem",
538
+ lineHeight: "1.3"
539
+ },
540
+ h3: {
541
+ fontSize: "1.25rem",
542
+ lineHeight: "1.4"
543
+ },
544
+ h4: {
545
+ fontSize: "1rem",
546
+ lineHeight: "1.5"
547
+ },
548
+ h5: {
549
+ fontSize: "0.875rem",
550
+ lineHeight: "1.5"
551
+ },
552
+ h6: {
553
+ fontSize: "0.75rem",
554
+ lineHeight: "1.5"
555
+ }
556
+ }
557
+ },
558
+ defaultRadius: "md",
559
+ radius: {
560
+ xs: "4px",
561
+ sm: "6px",
562
+ md: "8px",
563
+ lg: "12px",
564
+ xl: "16px"
565
+ },
566
+ shadows: {
567
+ xs: "0 1px 3px rgba(0, 0, 0, 0.2)",
568
+ sm: "0 2px 6px rgba(0, 0, 0, 0.2)",
569
+ md: "0 4px 12px rgba(0, 0, 0, 0.25)",
570
+ lg: "0 8px 24px rgba(0, 0, 0, 0.3)",
571
+ xl: "0 12px 36px rgba(0, 0, 0, 0.35)"
572
+ },
573
+ colors: {
574
+ rose: [
575
+ "#faf0f4",
576
+ "#f2d8e3",
577
+ "#eabdd0",
578
+ "#e0a0bb",
579
+ "#d4849f",
580
+ "#c4748f",
581
+ "#b06282",
582
+ "#9a5275",
583
+ "#7a3f5e",
584
+ "#5c2e47"
585
+ ],
586
+ gold: [
587
+ "#fdf8ec",
588
+ "#f8ecc8",
589
+ "#f2dda0",
590
+ "#eacb72",
591
+ "#e0b94d",
592
+ "#c9a33e",
593
+ "#a98830",
594
+ "#866b24",
595
+ "#634f1a",
596
+ "#403310"
597
+ ],
598
+ pine: [
599
+ "#ecf5f0",
600
+ "#d0e6da",
601
+ "#add4be",
602
+ "#86c0a0",
603
+ "#62ac84",
604
+ "#4e9670",
605
+ "#3e7a5a",
606
+ "#2f5e44",
607
+ "#20412f",
608
+ "#12251b"
609
+ ],
610
+ foam: [
611
+ "#edf6f7",
612
+ "#d2e9eb",
613
+ "#b0d9dd",
614
+ "#8bc6cc",
615
+ "#6ab3bb",
616
+ "#569da5",
617
+ "#438088",
618
+ "#33636a",
619
+ "#23454a",
620
+ "#14292c"
621
+ ],
622
+ red: [
623
+ "#f9eef0",
624
+ "#efd3d8",
625
+ "#e3b2bb",
626
+ "#d68e9b",
627
+ "#c86c7c",
628
+ "#b25566",
629
+ "#944454",
630
+ "#733442",
631
+ "#52252f",
632
+ "#33161d"
633
+ ],
634
+ gray: [
635
+ "#f4f0f2",
636
+ "#e4dde1",
637
+ "#cec5cb",
638
+ "#b5aab2",
639
+ "#9a8e96",
640
+ "#7e737a",
641
+ "#635a60",
642
+ "#4a4248",
643
+ "#332d31",
644
+ "#1e1a1c"
645
+ ],
646
+ dark: [
647
+ "#e0d8e0",
648
+ "#b0a6b2",
649
+ "#817786",
650
+ "#615768",
651
+ "#4a3f54",
652
+ "#3a3044",
653
+ "#2a2436",
654
+ "#211e2e",
655
+ "#1a1724",
656
+ "#110f1a"
657
+ ]
658
+ },
659
+ components: {
660
+ Button: Button.extend({
661
+ defaultProps: { fw: 500 },
662
+ styles: { root: { transition: "background-color 0.15s ease, opacity 0.15s ease" } }
663
+ }),
664
+ ActionIcon: ActionIcon.extend({ styles: { root: { transition: "background-color 0.15s ease, opacity 0.15s ease" } } }),
665
+ Paper: Paper.extend({
666
+ defaultProps: { shadow: "sm" },
667
+ styles: { root: { border: "1px solid var(--mantine-color-default-border)" } }
668
+ }),
669
+ Card: Card.extend({
670
+ defaultProps: { shadow: "sm" },
671
+ styles: { root: { border: "1px solid var(--mantine-color-default-border)" } }
672
+ }),
673
+ TextInput: TextInput.extend({ styles: { input: { border: "1px solid var(--mantine-color-default-border)" } } }),
674
+ Badge: Badge.extend({ defaultProps: { fw: 500 } })
675
+ }
676
+ };
677
+
678
+ //#endregion
679
+ //#region ../../src/core/atoms/themes/softBrutalism.ts
680
+ /**
681
+ * Soft Brutalism theme.
682
+ *
683
+ * Pastel pop palette with solid offset shadows, rounded corners, and bold borders.
684
+ * A friendlier take on neubrutalism — playful but production-ready.
685
+ */
686
+ const softBrutalismTheme = {
687
+ name: "Soft Brutalism",
688
+ description: "Pastel pop with bold borders and offset shadows",
689
+ head: { link: [
690
+ {
691
+ rel: "preconnect",
692
+ href: "https://fonts.googleapis.com"
693
+ },
694
+ {
695
+ rel: "preconnect",
696
+ href: "https://fonts.gstatic.com",
697
+ crossorigin: ""
698
+ },
699
+ {
700
+ rel: "stylesheet",
701
+ href: "https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap"
702
+ }
703
+ ] },
704
+ primaryColor: "lavender",
705
+ primaryShade: {
706
+ light: 5,
707
+ dark: 7
708
+ },
709
+ autoContrast: true,
710
+ cursorType: "pointer",
711
+ fontFamily: "Inter, -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Noto Sans\", Helvetica, Arial, sans-serif",
712
+ fontFamilyMonospace: "ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, \"Liberation Mono\", monospace",
713
+ headings: {
714
+ fontFamily: "Inter, -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Noto Sans\", Helvetica, Arial, sans-serif",
715
+ fontWeight: "700",
716
+ textWrap: "wrap",
717
+ sizes: {
718
+ h1: {
719
+ fontSize: "2rem",
720
+ lineHeight: "1.25"
721
+ },
722
+ h2: {
723
+ fontSize: "1.5rem",
724
+ lineHeight: "1.3"
725
+ },
726
+ h3: {
727
+ fontSize: "1.25rem",
728
+ lineHeight: "1.4"
729
+ },
730
+ h4: {
731
+ fontSize: "1rem",
732
+ lineHeight: "1.5"
733
+ },
734
+ h5: {
735
+ fontSize: "0.875rem",
736
+ lineHeight: "1.5"
737
+ },
738
+ h6: {
739
+ fontSize: "0.75rem",
740
+ lineHeight: "1.5"
741
+ }
742
+ }
743
+ },
744
+ defaultRadius: "md",
745
+ radius: {
746
+ xs: "6px",
747
+ sm: "8px",
748
+ md: "12px",
749
+ lg: "16px",
750
+ xl: "24px"
751
+ },
752
+ shadows: {
753
+ xs: "2px 2px 0 0 rgba(100, 80, 140, 0.15)",
754
+ sm: "3px 3px 0 0 rgba(100, 80, 140, 0.2)",
755
+ md: "4px 4px 0 0 rgba(100, 80, 140, 0.2)",
756
+ lg: "6px 6px 0 0 rgba(100, 80, 140, 0.25)",
757
+ xl: "8px 8px 0 0 rgba(100, 80, 140, 0.3)"
758
+ },
759
+ colors: {
760
+ lavender: [
761
+ "#f3f0fa",
762
+ "#e4dcf4",
763
+ "#d1c4e9",
764
+ "#b4a7d6",
765
+ "#9a8bc4",
766
+ "#7f6cb0",
767
+ "#6a549e",
768
+ "#543f87",
769
+ "#3d2d6b",
770
+ "#2a1d52"
771
+ ],
772
+ peach: [
773
+ "#fef3ec",
774
+ "#fce4d0",
775
+ "#f9d0ae",
776
+ "#f4b886",
777
+ "#f4a261",
778
+ "#e68a42",
779
+ "#c67234",
780
+ "#a35a28",
781
+ "#6b3a1a",
782
+ "#4a2710"
783
+ ],
784
+ mint: [
785
+ "#ecfaf0",
786
+ "#d4f2dc",
787
+ "#b3e8c2",
788
+ "#8edba4",
789
+ "#81c995",
790
+ "#5ab874",
791
+ "#42a05c",
792
+ "#2e8548",
793
+ "#1a5c2e",
794
+ "#0f3f1e"
795
+ ],
796
+ coral: [
797
+ "#fef0ef",
798
+ "#fcd9d7",
799
+ "#f8b8b4",
800
+ "#f29490",
801
+ "#e97171",
802
+ "#d65454",
803
+ "#b83e3e",
804
+ "#962d2d",
805
+ "#6b1f1f",
806
+ "#4a1414"
807
+ ],
808
+ gray: [
809
+ "#faf8f6",
810
+ "#f0ece8",
811
+ "#ddd7d0",
812
+ "#c4bbb2",
813
+ "#a89e95",
814
+ "#8c8279",
815
+ "#6e655d",
816
+ "#524b44",
817
+ "#3a342f",
818
+ "#24211e"
819
+ ],
820
+ dark: [
821
+ "#d4d0dc",
822
+ "#a9a2b5",
823
+ "#7e7690",
824
+ "#5c546e",
825
+ "#443c56",
826
+ "#342d45",
827
+ "#2a2339",
828
+ "#1e1a2e",
829
+ "#161224",
830
+ "#0f0c1a"
831
+ ]
832
+ },
833
+ components: {
834
+ Button: Button.extend({
835
+ defaultProps: { fw: 600 },
836
+ styles: { root: {
837
+ border: "2px solid currentColor",
838
+ boxShadow: "3px 3px 0 0 rgba(100, 80, 140, 0.2)",
839
+ transition: "box-shadow 0.15s ease, transform 0.15s ease"
840
+ } }
841
+ }),
842
+ ActionIcon: ActionIcon.extend({ styles: { root: {
843
+ border: "2px solid currentColor",
844
+ boxShadow: "2px 2px 0 0 rgba(100, 80, 140, 0.15)"
845
+ } } }),
846
+ Paper: Paper.extend({
847
+ defaultProps: { shadow: "sm" },
848
+ styles: { root: { border: "2px solid var(--mantine-color-default-border)" } }
849
+ }),
850
+ Card: Card.extend({
851
+ defaultProps: { shadow: "sm" },
852
+ styles: { root: { border: "2px solid var(--mantine-color-default-border)" } }
853
+ }),
854
+ TextInput: TextInput.extend({ styles: { input: {
855
+ border: "2px solid var(--mantine-color-default-border)",
856
+ transition: "box-shadow 0.15s ease, border-color 0.15s ease"
857
+ } } }),
858
+ Badge: Badge.extend({
859
+ defaultProps: { fw: 600 },
860
+ styles: { root: { border: "2px solid currentColor" } }
861
+ })
862
+ }
863
+ };
864
+
865
+ //#endregion
866
+ //#region ../../src/core/atoms/themes/terminal.ts
867
+ /**
868
+ * Terminal theme.
869
+ *
870
+ * Monospace everything, green-on-black, zero radius.
871
+ * CRT/hacker aesthetic for developer tools and dashboards.
872
+ */
873
+ const terminalTheme = {
874
+ name: "Terminal",
875
+ description: "Green phosphor on black — monospace hacker aesthetic",
876
+ defaultColorScheme: "dark",
877
+ primaryColor: "terminal",
878
+ primaryShade: {
879
+ light: 5,
880
+ dark: 4
881
+ },
882
+ autoContrast: true,
883
+ fontFamily: "ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, \"Liberation Mono\", monospace",
884
+ fontFamilyMonospace: "ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, \"Liberation Mono\", monospace",
885
+ headings: {
886
+ fontFamily: "ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, \"Liberation Mono\", monospace",
887
+ fontWeight: "700",
888
+ textWrap: "wrap",
889
+ sizes: {
890
+ h1: {
891
+ fontSize: "1.75rem",
892
+ lineHeight: "1.3"
893
+ },
894
+ h2: {
895
+ fontSize: "1.375rem",
896
+ lineHeight: "1.35"
897
+ },
898
+ h3: {
899
+ fontSize: "1.125rem",
900
+ lineHeight: "1.4"
901
+ },
902
+ h4: {
903
+ fontSize: "1rem",
904
+ lineHeight: "1.5"
905
+ },
906
+ h5: {
907
+ fontSize: "0.875rem",
908
+ lineHeight: "1.5"
909
+ },
910
+ h6: {
911
+ fontSize: "0.75rem",
912
+ lineHeight: "1.5"
913
+ }
914
+ }
915
+ },
916
+ defaultRadius: "0",
917
+ radius: {
918
+ xs: "0",
919
+ sm: "0",
920
+ md: "0",
921
+ lg: "2px",
922
+ xl: "4px"
923
+ },
924
+ shadows: {
925
+ xs: "none",
926
+ sm: "none",
927
+ md: "0 0 8px rgba(0, 255, 65, 0.08)",
928
+ lg: "0 0 16px rgba(0, 255, 65, 0.1)",
929
+ xl: "0 0 24px rgba(0, 255, 65, 0.12)"
930
+ },
931
+ colors: {
932
+ terminal: [
933
+ "#e6fff0",
934
+ "#b3ffd1",
935
+ "#80ffb3",
936
+ "#4dff94",
937
+ "#00ff41",
938
+ "#00d636",
939
+ "#00ad2b",
940
+ "#008521",
941
+ "#005c17",
942
+ "#00330d"
943
+ ],
944
+ amber: [
945
+ "#fff8e6",
946
+ "#ffecb3",
947
+ "#ffe080",
948
+ "#ffd54d",
949
+ "#ffca28",
950
+ "#d4a520",
951
+ "#aa8418",
952
+ "#806310",
953
+ "#554208",
954
+ "#2b2104"
955
+ ],
956
+ red: [
957
+ "#ffe6e6",
958
+ "#ffb3b3",
959
+ "#ff8080",
960
+ "#ff4d4d",
961
+ "#ff1a1a",
962
+ "#d41515",
963
+ "#aa1010",
964
+ "#800c0c",
965
+ "#550808",
966
+ "#2b0404"
967
+ ],
968
+ gray: [
969
+ "#e8eaed",
970
+ "#c8cdd3",
971
+ "#a4aab3",
972
+ "#808892",
973
+ "#5f6872",
974
+ "#474f58",
975
+ "#363c44",
976
+ "#282d33",
977
+ "#1c2026",
978
+ "#12151a"
979
+ ],
980
+ dark: [
981
+ "#c9cdd2",
982
+ "#8b9198",
983
+ "#5c636b",
984
+ "#3d444c",
985
+ "#2b3138",
986
+ "#1e242b",
987
+ "#151a20",
988
+ "#0e1216",
989
+ "#080c0f",
990
+ "#020303"
991
+ ]
992
+ },
993
+ components: {
994
+ Button: Button.extend({
995
+ defaultProps: { fw: 600 },
996
+ styles: { root: {
997
+ border: "1px solid currentColor",
998
+ textTransform: "uppercase",
999
+ letterSpacing: "0.05em",
1000
+ fontSize: "0.8125rem"
1001
+ } }
1002
+ }),
1003
+ ActionIcon: ActionIcon.extend({ styles: { root: { border: "1px solid currentColor" } } }),
1004
+ Paper: Paper.extend({ styles: { root: { border: "1px solid var(--mantine-color-default-border)" } } }),
1005
+ Card: Card.extend({ styles: { root: { border: "1px solid var(--mantine-color-default-border)" } } }),
1006
+ TextInput: TextInput.extend({ styles: { input: {
1007
+ border: "1px solid var(--mantine-color-default-border)",
1008
+ fontFamily: "inherit"
1009
+ } } }),
1010
+ Badge: Badge.extend({
1011
+ defaultProps: { fw: 600 },
1012
+ styles: { root: {
1013
+ border: "1px solid currentColor",
1014
+ textTransform: "uppercase",
1015
+ letterSpacing: "0.05em"
1016
+ } }
1017
+ })
1018
+ }
1019
+ };
1020
+
169
1021
  //#endregion
170
1022
  //#region ../../src/core/atoms/alephaThemeListAtom.ts
171
1023
  const alephaThemeListAtom = $atom({
172
1024
  name: "alepha.ui.themeList",
173
1025
  schema: t.array(t.json()),
174
- default: [defaultTheme, midnightTheme]
1026
+ default: [
1027
+ defaultTheme,
1028
+ midnightTheme,
1029
+ softBrutalismTheme,
1030
+ terminalTheme,
1031
+ editorialTheme,
1032
+ rosePineTheme,
1033
+ monochromeTheme
1034
+ ]
175
1035
  });
176
1036
 
177
1037
  //#endregion
178
1038
  //#region ../../src/core/providers/ThemeProvider.ts
179
- var ThemeProvider = class {
1039
+ var ThemeProvider = class ThemeProvider {
180
1040
  alepha = $inject(Alepha);
181
1041
  cookie = $cookie({
182
1042
  name: "theme",
183
1043
  schema: alephaThemeAtom.schema,
184
1044
  ttl: [1, "year"]
185
1045
  });
1046
+ overridesCookie = $cookie({
1047
+ name: "themeOverrides",
1048
+ schema: alephaThemeOverridesAtom.schema,
1049
+ ttl: [1, "year"]
1050
+ });
186
1051
  head = $head(() => {
187
1052
  const theme = this.getTheme();
188
1053
  if (!theme || !theme.name) return {};
189
- return { htmlAttributes: { "data-theme": theme.name } };
1054
+ return {
1055
+ htmlAttributes: { "data-theme": this.slugify(theme.name) },
1056
+ ...theme.head
1057
+ };
190
1058
  });
191
1059
  setTheme(index) {
192
- const newTheme = this.alepha.store.get(alephaThemeListAtom)[index];
193
- if (!newTheme) throw new AlephaError(`Theme with index ${index} not found`);
1060
+ if (!this.alepha.store.get(alephaThemeListAtom)[index]) throw new AlephaError(`Theme with index ${index} not found`);
194
1061
  this.cookie.set({ index });
195
1062
  this.alepha.store.set(alephaThemeAtom, { index });
196
- if (typeof document === "undefined") return;
197
- document.documentElement.removeAttribute("data-theme");
198
- if (newTheme.name) document.documentElement.setAttribute("data-theme", newTheme.name);
1063
+ if (!this.alepha.isBrowser()) return;
1064
+ this.alepha.inject(BrowserHeadProvider).refreshGlobalHead();
199
1065
  }
1066
+ slugify(name) {
1067
+ return name.toLowerCase().replace(/\s+/g, "-");
1068
+ }
1069
+ static FONT_SIZE_MULTIPLIERS = {
1070
+ xs: .85,
1071
+ sm: .925,
1072
+ md: 1,
1073
+ lg: 1.1,
1074
+ xl: 1.25
1075
+ };
1076
+ static SCALE_VALUES = {
1077
+ xs: .85,
1078
+ sm: .925,
1079
+ md: 1,
1080
+ lg: 1.1,
1081
+ xl: 1.25
1082
+ };
1083
+ static DEFAULT_FONT_SIZES = {
1084
+ xs: "0.75rem",
1085
+ sm: "0.875rem",
1086
+ md: "1rem",
1087
+ lg: "1.125rem",
1088
+ xl: "1.25rem"
1089
+ };
200
1090
  getTheme() {
201
1091
  const index = this.getThemeIndex();
202
1092
  const list = this.alepha.store.get(alephaThemeListAtom);
203
- return list[index] || list[0] || defaultTheme;
1093
+ const base = list[index] || list[0] || defaultTheme;
1094
+ const overrides = this.getThemeOverrides();
1095
+ if (!overrides.primaryColor && !overrides.radius && !overrides.fontFamily && !overrides.fontSize && !overrides.scale) return base;
1096
+ const merged = {
1097
+ ...base,
1098
+ ...overrides.primaryColor && { primaryColor: overrides.primaryColor },
1099
+ ...overrides.radius && { defaultRadius: overrides.radius },
1100
+ ...overrides.fontFamily && { fontFamily: overrides.fontFamily },
1101
+ ...overrides.scale && overrides.scale !== "md" && { scale: ThemeProvider.SCALE_VALUES[overrides.scale] ?? 1 }
1102
+ };
1103
+ if (overrides.fontSize && overrides.fontSize !== "md") {
1104
+ const multiplier = ThemeProvider.FONT_SIZE_MULTIPLIERS[overrides.fontSize] ?? 1;
1105
+ const baseSizes = base.fontSizes ?? ThemeProvider.DEFAULT_FONT_SIZES;
1106
+ merged.fontSizes = Object.fromEntries(Object.entries(baseSizes).map(([key, val]) => [key, `${(Number.parseFloat(String(val)) * multiplier).toFixed(4)}rem`]));
1107
+ }
1108
+ return merged;
1109
+ }
1110
+ setThemeOverrides(overrides) {
1111
+ this.overridesCookie.set(overrides);
1112
+ this.alepha.store.set(alephaThemeOverridesAtom, overrides);
1113
+ if (!this.alepha.isBrowser()) return;
1114
+ this.alepha.inject(BrowserHeadProvider).refreshGlobalHead();
1115
+ }
1116
+ getThemeOverrides() {
1117
+ try {
1118
+ return this.overridesCookie.get() ?? this.alepha.store.get(alephaThemeOverridesAtom) ?? {};
1119
+ } catch {
1120
+ return this.alepha.store.get(alephaThemeOverridesAtom) ?? {};
1121
+ }
1122
+ }
1123
+ resetThemeOverrides() {
1124
+ this.setThemeOverrides({});
204
1125
  }
205
1126
  getThemeIndex() {
206
1127
  try {
@@ -307,14 +1228,21 @@ var DialogService = class {
307
1228
  */
308
1229
  alert(options) {
309
1230
  return new Promise((resolve) => {
1231
+ let resolved = false;
1232
+ const done = () => {
1233
+ if (resolved) return;
1234
+ resolved = true;
1235
+ resolve();
1236
+ };
310
1237
  const modalId = this.open({
311
1238
  ...options,
312
1239
  title: options?.title || "Alert",
1240
+ onClose: done,
313
1241
  content: /* @__PURE__ */ jsx(AlertDialog, {
314
1242
  options,
315
1243
  onClose: () => {
316
1244
  this.close(modalId);
317
- resolve();
1245
+ done();
318
1246
  }
319
1247
  })
320
1248
  });
@@ -325,16 +1253,23 @@ var DialogService = class {
325
1253
  */
326
1254
  confirm(options) {
327
1255
  return new Promise((resolve) => {
1256
+ let resolved = false;
1257
+ const done = (confirmed) => {
1258
+ if (resolved) return;
1259
+ resolved = true;
1260
+ resolve(confirmed);
1261
+ };
328
1262
  const modalId = this.open({
329
1263
  ...options,
330
1264
  title: options?.title || "Confirm",
331
1265
  closeOnClickOutside: false,
332
1266
  closeOnEscape: false,
1267
+ onClose: () => done(false),
333
1268
  content: /* @__PURE__ */ jsx(ConfirmDialog, {
334
1269
  options,
335
1270
  onConfirm: (confirmed) => {
336
1271
  this.close(modalId);
337
- resolve(confirmed);
1272
+ done(confirmed);
338
1273
  }
339
1274
  })
340
1275
  });
@@ -345,16 +1280,23 @@ var DialogService = class {
345
1280
  */
346
1281
  prompt(options) {
347
1282
  return new Promise((resolve) => {
1283
+ let resolved = false;
1284
+ const done = (value) => {
1285
+ if (resolved) return;
1286
+ resolved = true;
1287
+ resolve(value);
1288
+ };
348
1289
  const modalId = this.open({
349
1290
  ...options,
350
1291
  title: options?.title || "Input",
351
1292
  closeOnClickOutside: false,
352
1293
  closeOnEscape: false,
1294
+ onClose: () => done(null),
353
1295
  content: /* @__PURE__ */ jsx(PromptDialog, {
354
1296
  options,
355
1297
  onSubmit: (value) => {
356
1298
  this.close(modalId);
357
- resolve(value);
1299
+ done(value);
358
1300
  }
359
1301
  })
360
1302
  });
@@ -458,20 +1400,34 @@ var UiRouter = class {
458
1400
  /**
459
1401
  * Hook to get and set the current theme.
460
1402
  *
461
- * Returns a tuple with the current theme and a function to set the theme.
1403
+ * Returns a tuple with the current theme, a function to set the theme,
1404
+ * and expert mode controls for fine-grained customization.
462
1405
  *
463
1406
  * ```tsx
464
- * const [theme, setTheme] = useTheme();
1407
+ * const [theme, setTheme, expert] = useTheme();
465
1408
  * ```
466
1409
  */
467
1410
  const useTheme = () => {
468
1411
  useStore(alephaThemeAtom);
1412
+ useStore(alephaThemeOverridesAtom);
469
1413
  const themeProvider = useInject(ThemeProvider);
470
1414
  const theme = themeProvider.getTheme();
471
1415
  const setTheme = (theme) => {
472
1416
  themeProvider.setTheme(theme.index);
473
1417
  };
474
- return [theme, setTheme];
1418
+ return [
1419
+ theme,
1420
+ setTheme,
1421
+ {
1422
+ overrides: themeProvider.getThemeOverrides(),
1423
+ setOverrides: (overrides) => {
1424
+ themeProvider.setThemeOverrides(overrides);
1425
+ },
1426
+ resetOverrides: () => {
1427
+ themeProvider.resetThemeOverrides();
1428
+ }
1429
+ }
1430
+ ];
475
1431
  };
476
1432
 
477
1433
  //#endregion
@@ -569,16 +1525,16 @@ const AlephaMantineProvider = (props) => {
569
1525
  const ui = {
570
1526
  colors: {
571
1527
  transparent: "transparent",
572
- background: "var(--alepha-background)",
1528
+ background: "var(--alepha-ground)",
573
1529
  surface: "var(--alepha-surface)",
574
1530
  elevated: "var(--alepha-elevated)",
575
1531
  border: "var(--alepha-border)"
576
1532
  },
577
1533
  sizes: { icon: {
578
- xs: 14,
579
- sm: 16,
580
- md: 20,
581
- lg: 24,
1534
+ xs: 16,
1535
+ sm: 20,
1536
+ md: 24,
1537
+ lg: 28,
582
1538
  xl: 32
583
1539
  } }
584
1540
  };
@@ -592,51 +1548,13 @@ function isComponentType(param) {
592
1548
 
593
1549
  //#endregion
594
1550
  //#region ../../src/core/components/buttons/ActionButton.tsx
595
- const ActionMenuItem = (props) => {
596
- const { item, index } = props;
597
- const router = useRouter();
598
- const action = useAction({ handler: async (e) => {
599
- await item.onClick?.();
600
- } }, [item.onClick]);
601
- if (item.type === "divider") return /* @__PURE__ */ jsx(Menu.Divider, {}, index);
602
- if (item.type === "label") return /* @__PURE__ */ jsx(Menu.Label, { children: item.label }, index);
603
- if (item.children && item.children.length > 0) return /* @__PURE__ */ jsxs(Menu, {
604
- trigger: "hover",
605
- position: "right-start",
606
- offset: 2,
607
- children: [/* @__PURE__ */ jsx(Menu.Target, { children: /* @__PURE__ */ jsx(Menu.Item, {
608
- leftSection: item.icon,
609
- rightSection: /* @__PURE__ */ jsx(IconChevronRight, { size: 14 }),
610
- children: item.label
611
- }) }), /* @__PURE__ */ jsx(Menu.Dropdown, { children: item.children.map((child, childIndex) => /* @__PURE__ */ jsx(ActionMenuItem, {
612
- item: child,
613
- index: childIndex
614
- }, childIndex)) })]
615
- }, index);
616
- const menuItemProps = {};
617
- if (props.item.onClick) menuItemProps.onClick = action.run;
618
- else if (props.item.href) Object.assign(menuItemProps, router.anchor(props.item.href));
619
- return /* @__PURE__ */ jsx(Menu.Item, {
620
- leftSection: item.icon,
621
- onClick: item.onClick,
622
- color: item.color,
623
- rightSection: item.active ? /* @__PURE__ */ jsx(ThemeIcon, {
624
- size: "xs",
625
- variant: "transparent",
626
- children: /* @__PURE__ */ jsx(IconCheck, {})
627
- }) : void 0,
628
- ...menuItemProps,
629
- children: item.label
630
- }, index);
631
- };
632
1551
  const ActionButton = (_props) => {
633
1552
  const theme = useMantineTheme();
634
1553
  const props = { ..._props };
635
- const { tooltip, menu, icon, ...restProps } = props;
636
- if (props.variant === "subtle" || props.variant === "outline") restProps.color ??= "gray";
1554
+ if (props.variant === "minimal") {}
1555
+ const { tooltip, menu, icon, iconSize, ...restProps } = props;
637
1556
  if (props.intent) {
638
- if (props.intent === "none") restProps.color ??= "gray";
639
- else if (props.intent === "primary") restProps.color ??= theme.primaryColor;
1557
+ if (props.intent === "primary") restProps.color ??= theme.primaryColor;
640
1558
  else if (props.intent === "success") {
641
1559
  restProps.c ??= "white";
642
1560
  restProps.color ??= "green";
@@ -651,10 +1569,11 @@ const ActionButton = (_props) => {
651
1569
  }
652
1570
  if (props.icon) {
653
1571
  const sizes = ui.sizes.icon;
654
- const icon = isComponentType(props.icon) ? /* @__PURE__ */ jsx(props.icon, { size: sizes[props.size || "md"] }) : /* @__PURE__ */ jsx("span", { children: props.icon });
1572
+ const iconSize = props.iconSize ?? sizes[props.size || "sm"];
1573
+ const icon = isComponentType(props.icon) ? /* @__PURE__ */ jsx(props.icon, { size: iconSize }) : /* @__PURE__ */ jsx("span", { children: props.icon });
655
1574
  if (!props.children) {
656
1575
  restProps.children = Children.only(icon);
657
- restProps.px ??= "xs";
1576
+ restProps.p ??= 8;
658
1577
  } else restProps.leftSection = icon;
659
1578
  }
660
1579
  if (props.leftSection && !props.children) restProps.px ??= "xs";
@@ -677,6 +1596,7 @@ const ActionButton = (_props) => {
677
1596
  children: /* @__PURE__ */ jsx(ActionButton, {
678
1597
  px: "xs",
679
1598
  ...rest,
1599
+ "aria-label": typeof children === "string" ? children : void 0,
680
1600
  tooltip,
681
1601
  menu,
682
1602
  children: leftSection
@@ -833,7 +1753,7 @@ const ActionClickButton = ({ preventDefault, ...props }) => {
833
1753
  * Action for navigation with active state support.
834
1754
  */
835
1755
  const ActionNavigationButton = (props) => {
836
- const { active: options, classNameActive, variantActive, propsActive, routerGoOptions, onClick: propsOnClick, anchor, ...buttonProps } = props;
1756
+ const { active: options, classNameActive, variantActive, propsActive, routerGoOptions, onClick: propsOnClick, anchorProps: buttonAnchorProps, anchor, ...buttonProps } = props;
837
1757
  const router = useRouter();
838
1758
  const { isPending, isActive } = useActive(options ? {
839
1759
  href: props.href,
@@ -847,11 +1767,11 @@ const ActionNavigationButton = (props) => {
847
1767
  };
848
1768
  const className = buttonProps.className || "";
849
1769
  if (isActive && options !== false && classNameActive) buttonProps.className = `${className} ${classNameActive}`.trim();
850
- if (props.anchorProps || anchor) return /* @__PURE__ */ jsx(Anchor, {
1770
+ if (buttonAnchorProps || anchor) return /* @__PURE__ */ jsx(Anchor, {
851
1771
  component: "a",
852
1772
  ...anchorProps,
853
1773
  ...buttonProps,
854
- ...props.anchorProps,
1774
+ ...buttonAnchorProps,
855
1775
  onClick: combinedOnClick,
856
1776
  children: props.children
857
1777
  });
@@ -874,6 +1794,38 @@ const ActionHrefButton = (props) => {
874
1794
  children: props.children
875
1795
  });
876
1796
  };
1797
+ const ActionMenuItem = (props) => {
1798
+ const { item, index } = props;
1799
+ const router = useRouter();
1800
+ const action = useAction({ handler: async (e) => {
1801
+ await item.onClick?.();
1802
+ } }, [item.onClick]);
1803
+ if (item.type === "divider") return /* @__PURE__ */ jsx(Menu.Divider, {}, index);
1804
+ if (item.type === "label") return /* @__PURE__ */ jsx(Menu.Label, { children: item.label }, index);
1805
+ if (item.children && item.children.length > 0) return /* @__PURE__ */ jsxs(Menu, {
1806
+ trigger: "hover",
1807
+ position: "right-start",
1808
+ offset: 2,
1809
+ children: [/* @__PURE__ */ jsx(Menu.Target, { children: /* @__PURE__ */ jsx(Menu.Item, {
1810
+ leftSection: item.icon,
1811
+ rightSection: /* @__PURE__ */ jsx(IconChevronRight, { size: 14 }),
1812
+ children: item.label
1813
+ }) }), /* @__PURE__ */ jsx(Menu.Dropdown, { children: item.children.map((child, childIndex) => /* @__PURE__ */ jsx(ActionMenuItem, {
1814
+ item: child,
1815
+ index: childIndex
1816
+ }, childIndex)) })]
1817
+ }, index);
1818
+ const menuItemProps = {};
1819
+ if (props.item.onClick) menuItemProps.onClick = action.run;
1820
+ else if (props.item.href) Object.assign(menuItemProps, router.anchor(props.item.href));
1821
+ return /* @__PURE__ */ jsx(Menu.Item, {
1822
+ leftSection: item.icon ?? (item.active ? /* @__PURE__ */ jsx(IconCheck, { size: ui.sizes.icon.sm }) : /* @__PURE__ */ jsx(Flex, { w: ui.sizes.icon.sm })),
1823
+ onClick: item.onClick,
1824
+ color: item.color,
1825
+ ...menuItemProps,
1826
+ children: item.label
1827
+ }, index);
1828
+ };
877
1829
 
878
1830
  //#endregion
879
1831
  //#region ../../src/core/components/buttons/BurgerButton.tsx
@@ -905,11 +1857,11 @@ const DarkModeButton = (props) => {
905
1857
  const toggleColorScheme = () => {
906
1858
  setColorScheme((document.documentElement.getAttribute("data-mantine-color-scheme") ?? "light") === "dark" ? "light" : "dark");
907
1859
  };
908
- const size = props.size ?? "md";
909
- const iconSize = ui.sizes.icon[size] ?? ui.sizes.icon.md;
1860
+ const size = props.size ?? "sm";
1861
+ const iconSize = ui.sizes.icon[size] ?? ui.sizes.icon.sm;
910
1862
  return /* @__PURE__ */ jsx(ActionButton, {
911
1863
  onClick: toggleColorScheme,
912
- variant: props.variant ?? "subtle",
1864
+ variant: props.variant ?? "default",
913
1865
  size,
914
1866
  "aria-label": "Toggle color scheme",
915
1867
  icon: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(IconSun, {
@@ -928,7 +1880,7 @@ const DarkModeButton = (props) => {
928
1880
  const LanguageButton = (props) => {
929
1881
  const i18n = useI18n();
930
1882
  return /* @__PURE__ */ jsx(ActionButton, {
931
- variant: "subtle",
1883
+ variant: "default",
932
1884
  icon: IconLanguage,
933
1885
  menu: { items: i18n.languages.map((lang) => ({
934
1886
  label: i18n.tr(lang),
@@ -947,8 +1899,7 @@ const OmnibarButton = (props) => {
947
1899
  if (props.collapsed) return /* @__PURE__ */ jsx(ActionButton, {
948
1900
  variant: "subtle",
949
1901
  onClick: spotlight.open,
950
- radius: "md",
951
- icon: /* @__PURE__ */ jsx(IconSearch, { size: 16 }),
1902
+ icon: IconSearch,
952
1903
  tooltip: {
953
1904
  label: "Search",
954
1905
  position: "right"
@@ -985,6 +1936,261 @@ const OmnibarButton = (props) => {
985
1936
  });
986
1937
  };
987
1938
 
1939
+ //#endregion
1940
+ //#region ../../src/core/hooks/useDialog.ts
1941
+ /**
1942
+ * Use this hook to access the Dialog Service for showing various dialog types.
1943
+ *
1944
+ * @example
1945
+ * ```tsx
1946
+ * const dialog = useDialog();
1947
+ * await dialog.alert({ title: "Alert", message: "This is an alert message" });
1948
+ * const confirmed = await dialog.confirm({ title: "Confirm", message: "Are you sure?" });
1949
+ * const input = await dialog.prompt({ title: "Input", message: "Enter your name:" });
1950
+ * ```
1951
+ */
1952
+ const useDialog = () => {
1953
+ return useInject(DialogService);
1954
+ };
1955
+
1956
+ //#endregion
1957
+ //#region ../../src/core/components/buttons/ThemeExpertModal.tsx
1958
+ const MANTINE_COLORS = [
1959
+ "red",
1960
+ "pink",
1961
+ "grape",
1962
+ "violet",
1963
+ "indigo",
1964
+ "blue",
1965
+ "cyan",
1966
+ "teal",
1967
+ "green",
1968
+ "lime",
1969
+ "yellow",
1970
+ "orange"
1971
+ ];
1972
+ const RADIUS_OPTIONS = [
1973
+ {
1974
+ label: "xs",
1975
+ value: "xs"
1976
+ },
1977
+ {
1978
+ label: "sm",
1979
+ value: "sm"
1980
+ },
1981
+ {
1982
+ label: "md",
1983
+ value: "md"
1984
+ },
1985
+ {
1986
+ label: "lg",
1987
+ value: "lg"
1988
+ },
1989
+ {
1990
+ label: "xl",
1991
+ value: "xl"
1992
+ }
1993
+ ];
1994
+ const SIZE_OPTIONS = [
1995
+ {
1996
+ label: "xs",
1997
+ value: "xs"
1998
+ },
1999
+ {
2000
+ label: "sm",
2001
+ value: "sm"
2002
+ },
2003
+ {
2004
+ label: "md",
2005
+ value: "md"
2006
+ },
2007
+ {
2008
+ label: "lg",
2009
+ value: "lg"
2010
+ },
2011
+ {
2012
+ label: "xl",
2013
+ value: "xl"
2014
+ }
2015
+ ];
2016
+ const FONT_OPTIONS = [
2017
+ {
2018
+ label: "System",
2019
+ value: ""
2020
+ },
2021
+ {
2022
+ label: "Inter",
2023
+ value: "Inter, sans-serif"
2024
+ },
2025
+ {
2026
+ label: "Mono",
2027
+ value: "ui-monospace, SFMono-Regular, Menlo, monospace"
2028
+ },
2029
+ {
2030
+ label: "Serif",
2031
+ value: "Georgia, 'Times New Roman', serif"
2032
+ }
2033
+ ];
2034
+ const ThemeExpertModal = () => {
2035
+ const [, , expert] = useTheme();
2036
+ const dialog = useDialog();
2037
+ const mantineTheme = useMantineTheme();
2038
+ const { overrides, setOverrides } = expert;
2039
+ const currentColor = overrides.primaryColor || mantineTheme.primaryColor;
2040
+ const currentRadius = overrides.radius || mantineTheme.defaultRadius || "md";
2041
+ const currentFont = overrides.fontFamily || "";
2042
+ const currentFontSize = overrides.fontSize || "md";
2043
+ const currentScale = overrides.scale || "md";
2044
+ const updateOverrides = (patch) => {
2045
+ setOverrides({
2046
+ ...overrides,
2047
+ ...patch
2048
+ });
2049
+ };
2050
+ return /* @__PURE__ */ jsxs(Flex, {
2051
+ direction: "column",
2052
+ gap: "lg",
2053
+ children: [
2054
+ /* @__PURE__ */ jsxs(Flex, {
2055
+ direction: "column",
2056
+ gap: "xs",
2057
+ children: [/* @__PURE__ */ jsx(Text, {
2058
+ fw: 500,
2059
+ size: "sm",
2060
+ children: "Primary Color"
2061
+ }), /* @__PURE__ */ jsx(SimpleGrid, {
2062
+ cols: 6,
2063
+ spacing: "xs",
2064
+ children: MANTINE_COLORS.map((color) => /* @__PURE__ */ jsx(Flex, {
2065
+ justify: "center",
2066
+ children: /* @__PURE__ */ jsx(ColorSwatch, {
2067
+ color: mantineTheme.colors[color]?.[6] ?? color,
2068
+ onClick: () => updateOverrides({ primaryColor: color }),
2069
+ style: { cursor: "pointer" },
2070
+ size: 32,
2071
+ children: currentColor === color && /* @__PURE__ */ jsx(IconCheck, {
2072
+ size: 14,
2073
+ color: "white"
2074
+ })
2075
+ })
2076
+ }, color))
2077
+ })]
2078
+ }),
2079
+ /* @__PURE__ */ jsxs(Flex, {
2080
+ direction: "column",
2081
+ gap: "xs",
2082
+ children: [/* @__PURE__ */ jsx(Text, {
2083
+ fw: 500,
2084
+ size: "sm",
2085
+ children: "Border Radius"
2086
+ }), /* @__PURE__ */ jsx(Flex, {
2087
+ gap: "xs",
2088
+ children: RADIUS_OPTIONS.map((opt) => /* @__PURE__ */ jsx(ActionButton, {
2089
+ variant: String(currentRadius) === opt.value ? "filled" : "default",
2090
+ size: "xs",
2091
+ flex: 1,
2092
+ onClick: () => updateOverrides({ radius: opt.value }),
2093
+ children: opt.label
2094
+ }, opt.value))
2095
+ })]
2096
+ }),
2097
+ /* @__PURE__ */ jsxs(Flex, {
2098
+ direction: "column",
2099
+ gap: "xs",
2100
+ children: [/* @__PURE__ */ jsx(Text, {
2101
+ fw: 500,
2102
+ size: "sm",
2103
+ children: "Font Family"
2104
+ }), /* @__PURE__ */ jsx(Select, {
2105
+ data: FONT_OPTIONS,
2106
+ value: currentFont,
2107
+ onChange: (value) => updateOverrides({ fontFamily: value ?? "" }),
2108
+ allowDeselect: false
2109
+ })]
2110
+ }),
2111
+ /* @__PURE__ */ jsxs(Flex, {
2112
+ direction: "column",
2113
+ gap: "xs",
2114
+ children: [/* @__PURE__ */ jsx(Text, {
2115
+ fw: 500,
2116
+ size: "sm",
2117
+ children: "Font Size"
2118
+ }), /* @__PURE__ */ jsx(Flex, {
2119
+ gap: "xs",
2120
+ children: SIZE_OPTIONS.map((opt) => /* @__PURE__ */ jsx(ActionButton, {
2121
+ variant: currentFontSize === opt.value ? "filled" : "default",
2122
+ size: "xs",
2123
+ flex: 1,
2124
+ onClick: () => updateOverrides({ fontSize: opt.value }),
2125
+ children: opt.label
2126
+ }, opt.value))
2127
+ })]
2128
+ }),
2129
+ /* @__PURE__ */ jsxs(Flex, {
2130
+ direction: "column",
2131
+ gap: "xs",
2132
+ children: [/* @__PURE__ */ jsx(Text, {
2133
+ fw: 500,
2134
+ size: "sm",
2135
+ children: "Scale"
2136
+ }), /* @__PURE__ */ jsx(Flex, {
2137
+ gap: "xs",
2138
+ children: SIZE_OPTIONS.map((opt) => /* @__PURE__ */ jsx(ActionButton, {
2139
+ variant: currentScale === opt.value ? "filled" : "default",
2140
+ size: "xs",
2141
+ flex: 1,
2142
+ onClick: () => updateOverrides({ scale: opt.value }),
2143
+ children: opt.label
2144
+ }, opt.value))
2145
+ })]
2146
+ }),
2147
+ /* @__PURE__ */ jsxs(Flex, {
2148
+ justify: "space-between",
2149
+ children: [/* @__PURE__ */ jsx(ActionButton, {
2150
+ variant: "subtle",
2151
+ color: "red",
2152
+ onClick: () => expert.resetOverrides(),
2153
+ children: "Reset"
2154
+ }), /* @__PURE__ */ jsx(ActionButton, {
2155
+ variant: "default",
2156
+ px: "xl",
2157
+ onClick: () => dialog.close(),
2158
+ children: "OK"
2159
+ })]
2160
+ })
2161
+ ]
2162
+ });
2163
+ };
2164
+
2165
+ //#endregion
2166
+ //#region ../../src/core/components/buttons/ThemeButton.tsx
2167
+ const ThemeButton = (props) => {
2168
+ const { expert, ...actionProps } = props;
2169
+ const [theme, setTheme] = useTheme();
2170
+ const themeList = useStore(alephaThemeListAtom)[0];
2171
+ const dialog = useDialog();
2172
+ const items = themeList.map((it, index) => ({
2173
+ label: it.name,
2174
+ onClick: () => setTheme({ index }),
2175
+ active: theme.name === it.name
2176
+ }));
2177
+ if (expert) items.push({ type: "divider" }, {
2178
+ label: "Customize...",
2179
+ onClick: () => {
2180
+ dialog.open({
2181
+ title: "Customize Theme",
2182
+ content: /* @__PURE__ */ jsx(ThemeExpertModal, {})
2183
+ });
2184
+ }
2185
+ });
2186
+ return /* @__PURE__ */ jsx(ActionButton, {
2187
+ variant: "default",
2188
+ icon: IconPalette,
2189
+ menu: { items },
2190
+ ...actionProps
2191
+ });
2192
+ };
2193
+
988
2194
  //#endregion
989
2195
  //#region ../../src/core/components/buttons/ToggleSidebarButton.tsx
990
2196
  const ToggleSidebarButton = (props) => {
@@ -992,8 +2198,7 @@ const ToggleSidebarButton = (props) => {
992
2198
  return /* @__PURE__ */ jsx(ActionButton, {
993
2199
  icon: sidebar.collapsed ? IconLayoutSidebarRightCollapse : IconLayoutSidebarLeftCollapse,
994
2200
  visibleFrom: "md",
995
- variant: "subtle",
996
- size: "md",
2201
+ variant: "default",
997
2202
  onClick: () => {
998
2203
  setSidebar({
999
2204
  ...sidebar,
@@ -1011,7 +2216,7 @@ const ToggleSidebarButton = (props) => {
1011
2216
  //#endregion
1012
2217
  //#region ../../src/core/components/Flex.tsx
1013
2218
  const Flex$1 = forwardRef((props, ref) => {
1014
- const { fill, center, centerX, centerY, col, ...rest } = props;
2219
+ const { fill, center, centerX, centerY, col, ground, surface, elevated, rounded, bordered, borderedTop, borderedBottom, shadowed, overflow, ...rest } = props;
1015
2220
  if (fill) rest.flex ??= 1;
1016
2221
  if (col) rest.direction ??= "column";
1017
2222
  if (center) {
@@ -1020,6 +2225,21 @@ const Flex$1 = forwardRef((props, ref) => {
1020
2225
  }
1021
2226
  if (centerX) rest.justify ??= "center";
1022
2227
  if (centerY) rest.align ??= "center";
2228
+ if (ground) rest.bg = "var(--alepha-ground)";
2229
+ else if (surface) rest.bg = "var(--alepha-surface)";
2230
+ else if (elevated) rest.bg = "var(--alepha-elevated)";
2231
+ if (rounded) rest.bdrs = rounded === true ? "md" : rounded;
2232
+ if (bordered) rest.bd = "1px solid var(--alepha-border)";
2233
+ if (borderedTop) rest.style = {
2234
+ borderTop: "1px solid var(--alepha-border)",
2235
+ ...rest.style ?? {}
2236
+ };
2237
+ if (borderedBottom) rest.style = {
2238
+ borderBottom: "1px solid var(--alepha-border)",
2239
+ ...rest.style ?? {}
2240
+ };
2241
+ if (shadowed) rest.className = `${rest.className ?? ""} shadow-${shadowed === true ? "md" : shadowed}`.trim();
2242
+ if (overflow) rest.className = `${rest.className ?? ""} overflow-auto`.trim();
1023
2243
  return /* @__PURE__ */ jsx(Flex, {
1024
2244
  ref,
1025
2245
  ...rest
@@ -1043,6 +2263,7 @@ const AppBar = (props) => {
1043
2263
  if ("type" in item) {
1044
2264
  if (item.type === "burger") return /* @__PURE__ */ jsx(BurgerButton, {}, index);
1045
2265
  if (item.type === "dark") return /* @__PURE__ */ jsx(DarkModeButton, { ...item.props }, index);
2266
+ if (item.type === "theme") return /* @__PURE__ */ jsx(ThemeButton, { ...item.props }, index);
1046
2267
  if (item.type === "search") return /* @__PURE__ */ jsx(OmnibarButton, { ...item.props }, index);
1047
2268
  if (item.type === "lang") return /* @__PURE__ */ jsx(LanguageButton, { ...item.props }, index);
1048
2269
  if (item.type === "spacer") return /* @__PURE__ */ jsx(Flex$1, { w: 16 }, index);
@@ -1156,7 +2377,8 @@ const AppBar = (props) => {
1156
2377
  * Pages should define a `label` in their `$page()` options for best results.
1157
2378
  * Falls back to the page name converted to Title Case.
1158
2379
  */
1159
- const Breadcrumb = ({ home = "Home", separator, size = "sm", ...groupProps }) => {
2380
+ const Breadcrumb = (props) => {
2381
+ const { home = "Home", separator, size = "sm", ...groupProps } = props;
1160
2382
  const state = useRouterState();
1161
2383
  const router = useRouter();
1162
2384
  const crumbs = [];
@@ -1211,11 +2433,175 @@ const Container$1 = forwardRef((props, ref) => {
1211
2433
  });
1212
2434
  Container$1.displayName = "Container";
1213
2435
 
2436
+ //#endregion
2437
+ //#region ../../src/core/helpers/renderIcon.tsx
2438
+ const renderIcon = (icon, size) => {
2439
+ if (!icon) return null;
2440
+ if (isValidElement(icon)) return icon;
2441
+ if (isComponentType(icon)) return /* @__PURE__ */ jsx(icon, { size: size ?? ui.sizes.icon.md });
2442
+ return icon;
2443
+ };
2444
+
2445
+ //#endregion
2446
+ //#region ../../src/core/components/Text.tsx
2447
+ const INTENT_COLORS = {
2448
+ primary: "blue",
2449
+ info: "cyan",
2450
+ success: "green",
2451
+ warning: "yellow",
2452
+ danger: "red"
2453
+ };
2454
+ const Text$1 = forwardRef((props, ref) => {
2455
+ const { intent, bold, italic, light, muted, small, uppercase, capitalize, center, monospace, title, ...rest } = props;
2456
+ if (intent) rest.c ??= INTENT_COLORS[intent];
2457
+ if (bold) rest.fw ??= 700;
2458
+ if (light) rest.fw ??= 300;
2459
+ if (italic) rest.fs ??= "italic";
2460
+ if (muted) rest.c ??= "dimmed";
2461
+ if (small) rest.size ??= "xs";
2462
+ if (uppercase) rest.tt ??= "uppercase";
2463
+ if (capitalize) rest.tt ??= "capitalize";
2464
+ if (center) rest.ta ??= "center";
2465
+ if (monospace) rest.ff ??= "monospace";
2466
+ if (title) rest.size ??= "xl";
2467
+ return /* @__PURE__ */ jsx(Text, {
2468
+ ref,
2469
+ ...rest
2470
+ });
2471
+ });
2472
+ Text$1.displayName = "Text";
2473
+
2474
+ //#endregion
2475
+ //#region ../../src/core/components/layout/SidebarCollapsedItem.tsx
2476
+ const SidebarCollapsedItem = (props) => {
2477
+ const router = useRouter();
2478
+ const handleItemClick = () => {
2479
+ props.onItemClick?.(props.item);
2480
+ props.item.onClick?.();
2481
+ };
2482
+ const hasChildren = props.item.children && props.item.children.length > 0;
2483
+ const menu = hasChildren ? {
2484
+ on: "hover",
2485
+ position: "right",
2486
+ menuProps: {
2487
+ arrowPosition: "center",
2488
+ arrowSize: 10,
2489
+ withArrow: true
2490
+ },
2491
+ items: [{
2492
+ type: "label",
2493
+ label: props.item.label
2494
+ }, ...props.item.children.filter((child) => !child.can || child.can()).map((child) => ({
2495
+ label: child.label,
2496
+ icon: renderIcon(child.icon, ui.sizes.icon.sm),
2497
+ href: child.href,
2498
+ active: child.href ? router.isActive(child.href, { startWith: child.activeStartsWith }) : void 0
2499
+ }))]
2500
+ } : void 0;
2501
+ return /* @__PURE__ */ jsx(Flex$1, {
2502
+ w: "100%",
2503
+ justify: "center",
2504
+ pos: "relative",
2505
+ children: /* @__PURE__ */ jsx(ActionButton, {
2506
+ size: props.item.theme?.size ?? props.theme.button?.size ?? (props.level === 0 ? "sm" : "xs"),
2507
+ bd: 0,
2508
+ variant: "default",
2509
+ propsActive: { variant: "outline" },
2510
+ tooltip: hasChildren ? void 0 : {
2511
+ label: props.item.label,
2512
+ position: "right"
2513
+ },
2514
+ onClick: hasChildren ? void 0 : handleItemClick,
2515
+ icon: renderIcon(props.item.icon, ui.sizes.icon.sm) ?? /* @__PURE__ */ jsx(IconSquareRounded, { size: ui.sizes.icon.sm }),
2516
+ href: hasChildren ? void 0 : props.item.href,
2517
+ target: hasChildren ? void 0 : props.item.target,
2518
+ menu,
2519
+ ...props.item.actionProps
2520
+ })
2521
+ });
2522
+ };
2523
+
2524
+ //#endregion
2525
+ //#region ../../src/core/components/layout/SidebarItem.tsx
2526
+ const SidebarItem = (props) => {
2527
+ const maxLevel = 2;
2528
+ const router = useRouter();
2529
+ const isActive = useCallback((item) => {
2530
+ if (!item.children) return false;
2531
+ for (const child of item.children) {
2532
+ if (child.href) {
2533
+ if (router.isActive(child.href)) return true;
2534
+ }
2535
+ if (isActive(child)) return true;
2536
+ }
2537
+ return false;
2538
+ }, []);
2539
+ const [isOpen, setIsOpen] = useState(isActive(props.item));
2540
+ useEvents({ "react:transition:end": () => {
2541
+ if (isActive(props.item)) setIsOpen(true);
2542
+ } }, []);
2543
+ if (props.level > maxLevel) return null;
2544
+ const handleItemClick = (e) => {
2545
+ if (!props.item.target) e.preventDefault();
2546
+ if (props.item.children && props.item.children.length > 0) setIsOpen(!isOpen);
2547
+ else {
2548
+ props.onItemClick?.(props.item);
2549
+ props.item.onClick?.();
2550
+ }
2551
+ };
2552
+ return /* @__PURE__ */ jsxs(Flex$1, {
2553
+ direction: "column",
2554
+ ps: props.level === 0 ? 0 : 32,
2555
+ pos: "relative",
2556
+ children: [/* @__PURE__ */ jsx(ActionButton, {
2557
+ w: "100%",
2558
+ justify: "space-between",
2559
+ href: props.item.href,
2560
+ target: props.item.target,
2561
+ size: props.item.theme?.size ?? props.theme.button?.size ?? (props.level === 0 ? "sm" : "xs"),
2562
+ bd: 0,
2563
+ fw: "normal",
2564
+ variant: "default",
2565
+ propsActive: { variant: "outline" },
2566
+ radius: props.item.theme?.radius ?? props.theme.button?.radius ?? "md",
2567
+ onClick: handleItemClick,
2568
+ leftSection: /* @__PURE__ */ jsxs(Flex$1, {
2569
+ w: "100%",
2570
+ align: "center",
2571
+ gap: "sm",
2572
+ children: [renderIcon(props.item.icon, ui.sizes.icon.sm), /* @__PURE__ */ jsx(Flex$1, {
2573
+ direction: "column",
2574
+ children: /* @__PURE__ */ jsx(Flex$1, { children: props.item.label })
2575
+ })]
2576
+ }),
2577
+ rightSection: props.item.children ? /* @__PURE__ */ jsx(Flex$1, { children: isOpen ? /* @__PURE__ */ jsx(IconChevronDown, { size: 14 }) : /* @__PURE__ */ jsx(IconChevronRight, { size: 14 }) }) : props.item.rightSection,
2578
+ ...props.item.actionProps
2579
+ }), props.item.children && isOpen && /* @__PURE__ */ jsxs(Flex$1, {
2580
+ direction: "column",
2581
+ "data-parent-level": props.level,
2582
+ gap: 2,
2583
+ py: 2,
2584
+ children: [/* @__PURE__ */ jsx(Flex$1, { style: {
2585
+ position: "absolute",
2586
+ width: 1,
2587
+ background: "linear-gradient(to bottom, transparent, var(--mantine-color-default-border), transparent)",
2588
+ top: 48,
2589
+ left: 20 + 32 * props.level,
2590
+ bottom: 16
2591
+ } }), props.item.children.filter((child) => !child.can || child.can()).map((child, index) => /* @__PURE__ */ jsx(SidebarItem, {
2592
+ item: child,
2593
+ level: props.level + 1,
2594
+ onItemClick: props.onItemClick,
2595
+ theme: props.theme
2596
+ }, index))]
2597
+ })]
2598
+ });
2599
+ };
2600
+
1214
2601
  //#endregion
1215
2602
  //#region ../../src/core/components/layout/Sidebar.tsx
1216
2603
  const Sidebar = (props) => {
1217
2604
  const router = useRouter();
1218
- const { onItemClick } = props;
1219
2605
  const divider = (key, fill, collapsed) => {
1220
2606
  return /* @__PURE__ */ jsx(Flex$1, {
1221
2607
  h: 1,
@@ -1233,6 +2619,9 @@ const Sidebar = (props) => {
1233
2619
  if (item.type === "divider") return divider(key, item.fill, collapsed);
1234
2620
  if (item.type === "search") return /* @__PURE__ */ jsx(Flex$1, {
1235
2621
  mb: "xs",
2622
+ w: "100%",
2623
+ justify: "center",
2624
+ pos: "relative",
1236
2625
  children: /* @__PURE__ */ jsx(OmnibarButton, { collapsed })
1237
2626
  }, key);
1238
2627
  if (item.type === "toggle") return /* @__PURE__ */ jsx(ToggleSidebarButton, {}, key);
@@ -1240,7 +2629,7 @@ const Sidebar = (props) => {
1240
2629
  if (item.children && item.children.length > 0) {
1241
2630
  if (!item.children.some((child) => !("can" in child) || !child.can || child.can())) return null;
1242
2631
  }
1243
- if (collapsed) return /* @__PURE__ */ jsxs(Fragment$1, { children: [divider(`${key}-d`, void 0, collapsed), item.children?.map((child, index) => renderNode(child, `s${key}-${index}`, collapsed))] }, key);
2632
+ if (collapsed) return /* @__PURE__ */ jsx(Fragment$1, { children: item.children?.map((child, index) => renderNode(child, `s${key}-${index}`, collapsed)) }, key);
1244
2633
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Flex$1, {
1245
2634
  mt: "md",
1246
2635
  align: "center",
@@ -1263,13 +2652,13 @@ const Sidebar = (props) => {
1263
2652
  if (collapsed) return /* @__PURE__ */ jsx(SidebarCollapsedItem, {
1264
2653
  item,
1265
2654
  level: 0,
1266
- onItemClick,
2655
+ onItemClick: props.onItemClick,
1267
2656
  theme: props.theme ?? {}
1268
2657
  }, key);
1269
2658
  return /* @__PURE__ */ jsx(SidebarItem, {
1270
2659
  item,
1271
2660
  level: 0,
1272
- onItemClick,
2661
+ onItemClick: props.onItemClick,
1273
2662
  theme: props.theme ?? {}
1274
2663
  }, key);
1275
2664
  };
@@ -1290,7 +2679,7 @@ const Sidebar = (props) => {
1290
2679
  return [];
1291
2680
  };
1292
2681
  const padding = "md";
1293
- const gap = props.items ? props.gap ?? 4 : "xs";
2682
+ const gap = props.items ? props.gap ?? 8 : "xs";
1294
2683
  const menu = useMemo(() => getSidebarNodes(), [props.items, props.autoPopulateMenu]);
1295
2684
  const renderSidebar = (collapsed) => /* @__PURE__ */ jsxs(Flex$1, {
1296
2685
  flex: 1,
@@ -1332,117 +2721,6 @@ const Sidebar = (props) => {
1332
2721
  })] });
1333
2722
  return renderSidebar(false);
1334
2723
  };
1335
- const SidebarItem = (props) => {
1336
- const { item, level } = props;
1337
- const maxLevel = 2;
1338
- const router = useRouter();
1339
- const isActive = useCallback((item) => {
1340
- if (!item.children) return false;
1341
- for (const child of item.children) {
1342
- if (child.href) {
1343
- if (router.isActive(child.href)) return true;
1344
- }
1345
- if (isActive(child)) return true;
1346
- }
1347
- return false;
1348
- }, []);
1349
- const [isOpen, setIsOpen] = useState(isActive(item));
1350
- useEvents({ "react:transition:end": () => {
1351
- if (isActive(item)) setIsOpen(true);
1352
- } }, []);
1353
- if (level > maxLevel) return null;
1354
- const handleItemClick = (e) => {
1355
- if (!props.item.target) e.preventDefault();
1356
- if (item.children && item.children.length > 0) setIsOpen(!isOpen);
1357
- else {
1358
- props.onItemClick?.(item);
1359
- item.onClick?.();
1360
- }
1361
- };
1362
- return /* @__PURE__ */ jsxs(Flex$1, {
1363
- direction: "column",
1364
- ps: level === 0 ? 0 : 32,
1365
- pos: "relative",
1366
- children: [/* @__PURE__ */ jsx(ActionButton, {
1367
- w: "100%",
1368
- justify: "space-between",
1369
- href: props.item.href,
1370
- target: props.item.target,
1371
- size: props.item.theme?.size ?? props.theme.button?.size ?? (level === 0 ? "sm" : "xs"),
1372
- bd: 0,
1373
- fw: "normal",
1374
- variant: "default",
1375
- propsActive: {
1376
- variant: "outline",
1377
- fw: "bold"
1378
- },
1379
- radius: props.item.theme?.radius ?? props.theme.button?.radius ?? "md",
1380
- onClick: handleItemClick,
1381
- leftSection: /* @__PURE__ */ jsxs(Flex$1, {
1382
- w: "100%",
1383
- align: "center",
1384
- gap: "sm",
1385
- children: [renderIcon(item.icon, ui.sizes.icon.sm), /* @__PURE__ */ jsx(Flex$1, {
1386
- direction: "column",
1387
- children: /* @__PURE__ */ jsx(Flex$1, { children: item.label })
1388
- })]
1389
- }),
1390
- rightSection: item.children ? /* @__PURE__ */ jsx(Flex$1, { children: isOpen ? /* @__PURE__ */ jsx(IconChevronDown, { size: 14 }) : /* @__PURE__ */ jsx(IconChevronRight, { size: 14 }) }) : props.item.rightSection,
1391
- ...props.item.actionProps
1392
- }), item.children && isOpen && /* @__PURE__ */ jsxs(Flex$1, {
1393
- direction: "column",
1394
- "data-parent-level": level,
1395
- children: [/* @__PURE__ */ jsx(Flex$1, { style: {
1396
- position: "absolute",
1397
- width: 1,
1398
- background: "linear-gradient(to bottom, transparent, var(--mantine-color-default-border), transparent)",
1399
- top: 48,
1400
- left: 20 + 32 * level,
1401
- bottom: 16
1402
- } }), item.children.filter((child) => !child.can || child.can()).map((child, index) => /* @__PURE__ */ jsx(SidebarItem, {
1403
- item: child,
1404
- level: level + 1,
1405
- onItemClick: props.onItemClick,
1406
- theme: props.theme
1407
- }, index))]
1408
- })]
1409
- });
1410
- };
1411
- const SidebarCollapsedItem = (props) => {
1412
- const { item, level } = props;
1413
- const router = useRouter();
1414
- const handleItemClick = () => {
1415
- props.onItemClick?.(item);
1416
- item.onClick?.();
1417
- };
1418
- const hasChildren = item.children && item.children.length > 0;
1419
- const menu = hasChildren ? {
1420
- on: "hover",
1421
- position: "right",
1422
- items: item.children.filter((child) => !child.can || child.can()).map((child) => ({
1423
- label: child.label,
1424
- icon: renderIcon(child.icon, ui.sizes.icon.sm),
1425
- href: child.href,
1426
- active: child.href ? router.isActive(child.href, { startWith: child.activeStartsWith }) : void 0
1427
- }))
1428
- } : void 0;
1429
- return /* @__PURE__ */ jsx(ActionButton, {
1430
- size: props.item.theme?.size ?? props.theme.button?.size ?? (level === 0 ? "sm" : "xs"),
1431
- variant: "subtle",
1432
- variantActive: "default",
1433
- tooltip: hasChildren ? void 0 : {
1434
- label: item.label,
1435
- position: "right"
1436
- },
1437
- radius: props.item.theme?.radius ?? props.theme.button?.radius ?? "md",
1438
- onClick: hasChildren ? void 0 : handleItemClick,
1439
- icon: renderIcon(item.icon, ui.sizes.icon.sm) ?? /* @__PURE__ */ jsx(IconSquareRounded, { size: ui.sizes.icon.sm }),
1440
- href: hasChildren ? void 0 : props.item.href,
1441
- target: hasChildren ? void 0 : props.item.target,
1442
- menu,
1443
- ...props.item.actionProps
1444
- });
1445
- };
1446
2724
 
1447
2725
  //#endregion
1448
2726
  //#region ../../src/core/components/layout/DashboardShell.tsx
@@ -1483,13 +2761,16 @@ const DashboardShell = (props) => {
1483
2761
  const fHeight = props.footerHeight ?? 24;
1484
2762
  const headerHeight = hasAppBar ? hHeight : 0;
1485
2763
  const footerHeight = footerElement ? fHeight : 0;
2764
+ const navbarWidth = collapsed ? collapsedWidth : expandedWidth;
2765
+ const mainContent = props.children ?? /* @__PURE__ */ jsx(NestedView, {});
1486
2766
  return /* @__PURE__ */ jsxs(AppShell, {
1487
2767
  layout: "alt",
1488
2768
  w: "100%",
2769
+ h: "100vh",
1489
2770
  flex: 1,
1490
2771
  header: hasAppBar ? { height: hHeight } : void 0,
1491
2772
  navbar: hasSidebar ? {
1492
- width: { base: collapsed ? collapsedWidth : expandedWidth },
2773
+ width: { base: navbarWidth },
1493
2774
  breakpoint: "md",
1494
2775
  collapsed: { mobile: sidebar.closed }
1495
2776
  } : void 0,
@@ -1504,73 +2785,49 @@ const DashboardShell = (props) => {
1504
2785
  })
1505
2786
  }),
1506
2787
  hasSidebar && /* @__PURE__ */ jsxs(AppShell.Navbar, {
1507
- className: "alepha-sidebar-navbar",
1508
2788
  ...props.appShellNavbarProps,
1509
2789
  children: [
1510
2790
  props.navbarHeader ? /* @__PURE__ */ jsx(Flex$1, {
1511
2791
  style: { borderBottom: "1px solid var(--mantine-color-default-border)" },
1512
2792
  h: headerHeight,
1513
- children: props.navbarHeader
2793
+ children: props.navbarHeader({ collapsed })
1514
2794
  }) : null,
1515
2795
  /* @__PURE__ */ jsx(Sidebar, {
1516
2796
  ...props.sidebarProps ?? {},
1517
2797
  collapsed
1518
- }),
1519
- props.navbarFooter ? /* @__PURE__ */ jsx(Flex$1, {
1520
- style: { borderTop: "1px solid var(--mantine-color-default-border)" },
1521
- h: footerHeight,
1522
- children: props.navbarFooter
1523
- }) : null
1524
- ]
1525
- }),
1526
- /* @__PURE__ */ jsx(AppShell.Main, {
1527
- pos: "relative",
1528
- ...props.appShellMainProps,
1529
- children: props.children ?? /* @__PURE__ */ jsx(NestedView, {})
1530
- }),
1531
- footerElement && /* @__PURE__ */ jsx(AppShell.Footer, {
1532
- ...props.appShellFooterProps,
1533
- children: footerElement
1534
- })
1535
- ]
1536
- });
1537
- };
1538
-
1539
- //#endregion
1540
- //#region ../../src/core/components/Text.tsx
1541
- const INTENT_COLORS = {
1542
- primary: "blue",
1543
- info: "cyan",
1544
- success: "green",
1545
- warning: "yellow",
1546
- danger: "red"
1547
- };
1548
- const Text$1 = forwardRef((props, ref) => {
1549
- const { intent, bold, italic, light, muted, small, uppercase, capitalize, center, monospace, title, ...rest } = props;
1550
- if (intent) rest.c ??= INTENT_COLORS[intent];
1551
- if (bold) rest.fw ??= 700;
1552
- if (light) rest.fw ??= 300;
1553
- if (italic) rest.fs ??= "italic";
1554
- if (muted) rest.c ??= "dimmed";
1555
- if (small) rest.size ??= "sm";
1556
- if (uppercase) rest.tt ??= "uppercase";
1557
- if (capitalize) rest.tt ??= "capitalize";
1558
- if (center) rest.ta ??= "center";
1559
- if (monospace) rest.ff ??= "monospace";
1560
- if (title) rest.size ??= "xl";
1561
- return /* @__PURE__ */ jsx(Text, {
1562
- ref,
1563
- ...rest
2798
+ }),
2799
+ props.navbarFooter ? /* @__PURE__ */ jsx(Flex$1, {
2800
+ style: { borderTop: "1px solid var(--mantine-color-default-border)" },
2801
+ h: footerHeight,
2802
+ children: props.navbarFooter
2803
+ }) : null
2804
+ ]
2805
+ }),
2806
+ /* @__PURE__ */ jsx(AppShell.Main, {
2807
+ display: "flex",
2808
+ bg: "var(--alepha-ground)",
2809
+ pos: "relative",
2810
+ h: props.fill ? "100%" : "inherit",
2811
+ ...props.appShellMainProps,
2812
+ children: props.container ? /* @__PURE__ */ jsx(Container$1, {
2813
+ ...typeof props.container === "boolean" ? {} : props.container,
2814
+ children: mainContent
2815
+ }) : mainContent
2816
+ }),
2817
+ footerElement && /* @__PURE__ */ jsx(AppShell.Footer, {
2818
+ ...props.appShellFooterProps,
2819
+ children: footerElement
2820
+ })
2821
+ ]
1564
2822
  });
1565
- });
1566
- Text$1.displayName = "Text";
2823
+ };
1567
2824
 
1568
2825
  //#endregion
1569
2826
  //#region ../../src/core/form/utils/parseInput.ts
1570
2827
  const parseInput = (props, form) => {
1571
2828
  const disabled = false;
1572
2829
  const id = props.input.props.id;
1573
- 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);
2830
+ 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);
1574
2831
  const description = props.description ?? ("description" in props.input.schema && typeof props.input.schema.description === "string" ? props.input.schema.description : void 0);
1575
2832
  const error = form.error && form.error instanceof TypeBoxError ? form.error.value.message : void 0;
1576
2833
  const icon = !props.icon ? getDefaultIcon({
@@ -1578,17 +2835,20 @@ const parseInput = (props, form) => {
1578
2835
  format: props.input.schema && "format" in props.input.schema && typeof props.input.schema.format === "string" ? props.input.schema.format : void 0,
1579
2836
  name: props.input.props.name,
1580
2837
  isEnum: props.input.schema && "enum" in props.input.schema && Boolean(props.input.schema.enum),
1581
- isArray: props.input.schema && "type" in props.input.schema && props.input.schema.type === "array"
1582
- }) : isValidElement(props.icon) ? props.icon : createElement(props.icon, { size: ui.sizes.icon.md });
2838
+ isArray: props.input.schema && "type" in props.input.schema && props.input.schema.type === "array",
2839
+ size: props.size
2840
+ }) : isValidElement(props.icon) ? props.icon : createElement(props.icon, { size: ui.sizes.icon.sm });
1583
2841
  const format = props.input.schema && "format" in props.input.schema && typeof props.input.schema.format === "string" ? props.input.schema.format : void 0;
1584
2842
  const required = props.input.required;
1585
2843
  const schema = props.input.schema;
2844
+ const testId = props.input.props?.["data-testid"];
1586
2845
  const inputProps = {
1587
2846
  label,
1588
2847
  description,
1589
2848
  error,
1590
2849
  required,
1591
- disabled
2850
+ disabled,
2851
+ ...testId ? { "data-testid": testId } : {}
1592
2852
  };
1593
2853
  if ("minLength" in schema && typeof schema.minLength === "number") inputProps.minLength = schema.minLength;
1594
2854
  if ("maxLength" in schema && typeof schema.maxLength === "number") inputProps.maxLength = schema.maxLength;
@@ -1613,8 +2873,8 @@ const useArrayItems = (input) => {
1613
2873
  const alepha = useAlepha();
1614
2874
  const keyCounter = useRef(0);
1615
2875
  const [items, setItemsState] = useState(() => {
1616
- const defaultValue = input?.props?.defaultValue;
1617
- if (Array.isArray(defaultValue)) return defaultValue.map((value) => ({
2876
+ const initial = input?.initialValue;
2877
+ if (Array.isArray(initial)) return initial.map((value) => ({
1618
2878
  key: keyCounter.current++,
1619
2879
  value
1620
2880
  }));
@@ -1640,22 +2900,9 @@ const useArrayItems = (input) => {
1640
2900
  if (!input?.form) return;
1641
2901
  const formId = input.form.id;
1642
2902
  const fieldPath = input.path;
1643
- const listeners = [alepha.events.on("form:reset", (event) => {
1644
- if (event.id === formId) {
1645
- const defaultValue = input.props?.defaultValue;
1646
- keyCounter.current = 0;
1647
- if (Array.isArray(defaultValue)) setItemsState(defaultValue.map((value) => ({
1648
- key: keyCounter.current++,
1649
- value
1650
- })));
1651
- else setItemsState([]);
1652
- }
1653
- }), alepha.events.on("form:change", (event) => {
2903
+ return alepha.events.on("form:change", (event) => {
1654
2904
  if (event.id === formId && event.path === fieldPath) syncFromFormValue(event.value);
1655
- })];
1656
- return () => {
1657
- for (const unsub of listeners) unsub();
1658
- };
2905
+ });
1659
2906
  }, [
1660
2907
  alepha,
1661
2908
  input,
@@ -1680,10 +2927,10 @@ const createArrayItemInput = (parentInput, itemSchema, index, _itemKey, value, o
1680
2927
  path: `${parentInput.path}/${index}`,
1681
2928
  required: false,
1682
2929
  form: parentInput.form,
2930
+ initialValue: value,
1683
2931
  props: {
1684
2932
  id: `${parentInput.props.id}-${index}`,
1685
- name: `${parentInput.props.name}[${index}]`,
1686
- defaultValue: value
2933
+ name: `${parentInput.props.name}[${index}]`
1687
2934
  },
1688
2935
  set: onValueChange
1689
2936
  };
@@ -1698,10 +2945,10 @@ const createArrayItemFieldInput = (parentInput, itemSchema, fieldName, index, _i
1698
2945
  path: `${parentInput.path}/${index}/${fieldName}`,
1699
2946
  required: itemSchema.required?.includes(fieldName) ?? false,
1700
2947
  form: parentInput.form,
2948
+ initialValue: itemValue?.[fieldName],
1701
2949
  props: {
1702
2950
  id: `${parentInput.props.id}-${index}-${fieldName}`,
1703
- name: `${parentInput.props.name}[${index}].${fieldName}`,
1704
- defaultValue: itemValue?.[fieldName]
2951
+ name: `${parentInput.props.name}[${index}].${fieldName}`
1705
2952
  },
1706
2953
  set: (value) => onFieldChange(fieldName, value)
1707
2954
  };
@@ -1919,7 +3166,9 @@ const ControlArray = (props) => {
1919
3166
  * Automatically detects date formats from schema and renders appropriate picker.
1920
3167
  */
1921
3168
  const ControlDate = (props) => {
1922
- const { inputProps, id, icon, format } = parseInput(props, useFormState(props.input));
3169
+ const form = useFormState(props.input);
3170
+ const [value, setValue] = useFieldValue(props.input);
3171
+ const { inputProps, id, icon, format } = parseInput(props, form);
1923
3172
  if (!props.input?.props) return null;
1924
3173
  if (props.datetime || format === "date-time") {
1925
3174
  const dateTimePickerProps = typeof props.datetime === "object" ? props.datetime : {};
@@ -1927,10 +3176,8 @@ const ControlDate = (props) => {
1927
3176
  ...inputProps,
1928
3177
  id,
1929
3178
  leftSection: icon,
1930
- defaultValue: props.input.props.defaultValue ? new Date(props.input.props.defaultValue) : void 0,
1931
- onChange: (value) => {
1932
- props.input.set(value ? new Date(value).toISOString() : void 0);
1933
- },
3179
+ value: value ? new Date(value) : null,
3180
+ onChange: (val) => setValue(val ? new Date(val).toISOString() : void 0),
1934
3181
  ...dateTimePickerProps
1935
3182
  });
1936
3183
  }
@@ -1940,10 +3187,8 @@ const ControlDate = (props) => {
1940
3187
  ...inputProps,
1941
3188
  id,
1942
3189
  leftSection: icon,
1943
- defaultValue: props.input.props.defaultValue ? new Date(props.input.props.defaultValue) : void 0,
1944
- onChange: (value) => {
1945
- props.input.set(value ? new Date(value).toISOString().slice(0, 10) : void 0);
1946
- },
3190
+ value: value ? new Date(value) : null,
3191
+ onChange: (val) => setValue(val ? new Date(val).toISOString().slice(0, 10) : void 0),
1947
3192
  ...dateInputProps
1948
3193
  });
1949
3194
  }
@@ -1953,10 +3198,8 @@ const ControlDate = (props) => {
1953
3198
  ...inputProps,
1954
3199
  id,
1955
3200
  leftSection: icon,
1956
- defaultValue: props.input.props.defaultValue,
1957
- onChange: (event) => {
1958
- props.input.set(event.currentTarget.value);
1959
- },
3201
+ value: value ?? "",
3202
+ onChange: (event) => setValue(event.currentTarget.value),
1960
3203
  ...timeInputProps
1961
3204
  });
1962
3205
  }
@@ -1969,14 +3212,10 @@ const ControlDate = (props) => {
1969
3212
  *
1970
3213
  */
1971
3214
  const ControlNumber = (props) => {
1972
- const { inputProps, id, icon } = parseInput(props, useFormState(props.input));
1973
- const ref = useRef(null);
1974
- const [value, setValue] = useState(props.input.props.defaultValue);
1975
- useEvents({ "form:reset": (event) => {
1976
- if (event.id === props.input?.form.id && ref.current) setValue(props.input.props.defaultValue);
1977
- } }, [props.input]);
3215
+ const form = useFormState(props.input);
3216
+ const [value, setValue] = useFieldValue(props.input);
3217
+ const { inputProps, id, icon } = parseInput(props, form);
1978
3218
  if (!props.input?.props) return null;
1979
- const { type, ...inputPropsWithoutType } = props.input.props;
1980
3219
  if (props.sliderProps) {
1981
3220
  const min = props.sliderProps.min ?? inputProps.minimum ?? 0;
1982
3221
  const max = props.sliderProps.max ?? inputProps.maximum ?? 100;
@@ -1989,34 +3228,25 @@ const ControlNumber = (props) => {
1989
3228
  },
1990
3229
  children: /* @__PURE__ */ jsx(Slider, {
1991
3230
  ...inputProps,
1992
- ref,
1993
3231
  id,
1994
- ...inputPropsWithoutType,
1995
3232
  ...props.sliderProps,
1996
- value,
3233
+ value: value ?? 0,
1997
3234
  min,
1998
3235
  max,
1999
3236
  label: () => value,
2000
- onChange: (val) => {
2001
- setValue(val);
2002
- props.input.set(val);
2003
- }
3237
+ onChange: (val) => setValue(val)
2004
3238
  })
2005
3239
  })
2006
3240
  });
2007
3241
  }
2008
3242
  return /* @__PURE__ */ jsx(NumberInput, {
2009
3243
  ...inputProps,
2010
- ref,
2011
3244
  id,
2012
3245
  leftSection: icon,
2013
- ...inputPropsWithoutType,
2014
3246
  ...props.numberInputProps,
2015
3247
  value: value ?? "",
2016
3248
  onChange: (val) => {
2017
- const newValue = val !== null ? Number(val) : void 0;
2018
- setValue(newValue);
2019
- props.input.set(newValue);
3249
+ setValue(val !== null ? Number(val) : void 0);
2020
3250
  }
2021
3251
  });
2022
3252
  };
@@ -2099,92 +3329,9 @@ const ControlObject = (props) => {
2099
3329
  };
2100
3330
 
2101
3331
  //#endregion
2102
- //#region ../../src/core/form/components/ControlQueryBuilder.tsx
2103
- /**
2104
- * Query builder with text input and help popover.
2105
- * Generates query strings for parseQueryString syntax.
2106
- */
2107
- const ControlQueryBuilder = ({ schema, value = "", onChange, placeholder = "Enter query or click for assistance...", ...textInputProps }) => {
2108
- const [helpOpened, setHelpOpened] = useState(false);
2109
- const [textValue, setTextValue] = useState(value);
2110
- const inputRef = useRef(null);
2111
- const fields = schema ? extractSchemaFields(schema) : [];
2112
- const [error, setError] = useState(null);
2113
- const isValid = (value) => {
2114
- try {
2115
- parseQueryString(value.trim());
2116
- } catch (e) {
2117
- setError(e.message);
2118
- return false;
2119
- }
2120
- setError(null);
2121
- return true;
2122
- };
2123
- const handleTextChange = (newValue) => {
2124
- setTextValue(newValue);
2125
- if (isValid(newValue)) onChange?.(newValue);
2126
- };
2127
- const handleClear = () => {
2128
- setTextValue("");
2129
- onChange?.("");
2130
- isValid("");
2131
- };
2132
- const handleInsert = (text) => {
2133
- const newValue = textValue ? `${textValue}${text} ` : `${text} `;
2134
- setTextValue(newValue);
2135
- if (isValid(newValue)) onChange?.(newValue);
2136
- setTimeout(() => {
2137
- inputRef.current?.focus();
2138
- const length = inputRef.current?.value.length || 0;
2139
- inputRef.current?.setSelectionRange(length, length);
2140
- }, 0);
2141
- };
2142
- useEvents({ "form:change": (event) => {
2143
- if (event.id === inputRef.current?.form?.id) {
2144
- if (event.path === textInputProps["data-path"]) setTextValue(event.value ?? "");
2145
- }
2146
- } }, []);
2147
- return /* @__PURE__ */ jsxs(Popover, {
2148
- width: 800,
2149
- position: "bottom-start",
2150
- shadow: "md",
2151
- opened: helpOpened,
2152
- onChange: setHelpOpened,
2153
- closeOnClickOutside: true,
2154
- closeOnEscape: true,
2155
- transitionProps: {
2156
- transition: "fade-up",
2157
- duration: 200,
2158
- timingFunction: "ease"
2159
- },
2160
- children: [/* @__PURE__ */ jsx(Popover.Target, { children: /* @__PURE__ */ jsx(TextInput, {
2161
- ref: inputRef,
2162
- placeholder,
2163
- value: textValue,
2164
- onChange: (e) => handleTextChange(e.currentTarget.value),
2165
- onFocus: () => setHelpOpened(true),
2166
- leftSection: error ? /* @__PURE__ */ jsx(IconInfoTriangle, { size: 16 }) : /* @__PURE__ */ jsx(IconFilter, { size: 16 }),
2167
- rightSection: textValue && /* @__PURE__ */ jsx(ActionIcon, {
2168
- size: "sm",
2169
- variant: "subtle",
2170
- color: "gray",
2171
- onClick: handleClear,
2172
- children: /* @__PURE__ */ jsx(IconX, { size: 14 })
2173
- }),
2174
- ...textInputProps
2175
- }) }), /* @__PURE__ */ jsx(Popover.Dropdown, {
2176
- bg: "transparent",
2177
- p: "xs",
2178
- bd: `1px solid ${ui.colors.border}`,
2179
- style: { backdropFilter: "blur(20px)" },
2180
- children: /* @__PURE__ */ jsx(QueryHelp, {
2181
- fields,
2182
- onInsert: handleInsert
2183
- })
2184
- })]
2185
- });
2186
- };
2187
- function QueryHelp({ fields, onInsert }) {
3332
+ //#region ../../src/core/form/components/ControlQueryBuilderHelp.tsx
3333
+ const ControlQueryBuilderHelp = (props) => {
3334
+ const { fields, onInsert } = props;
2188
3335
  return /* @__PURE__ */ jsxs(Flex, {
2189
3336
  gap: "md",
2190
3337
  align: "flex-start",
@@ -2347,110 +3494,313 @@ function QueryHelp({ fields, onInsert }) {
2347
3494
  })
2348
3495
  ]
2349
3496
  });
2350
- }
3497
+ };
3498
+
3499
+ //#endregion
3500
+ //#region ../../src/core/form/components/ControlQueryBuilder.tsx
3501
+ /**
3502
+ * Query builder with text input and help popover.
3503
+ * Generates query strings for parseQueryString syntax.
3504
+ */
3505
+ const ControlQueryBuilder = (props) => {
3506
+ const { schema, value = "", onChange, placeholder = "Enter query or click for assistance...", ...textInputProps } = props;
3507
+ const [helpOpened, setHelpOpened] = useState(false);
3508
+ const [textValue, setTextValue] = useState(value);
3509
+ const inputRef = useRef(null);
3510
+ const fields = schema ? extractSchemaFields(schema) : [];
3511
+ const [error, setError] = useState(null);
3512
+ const isValid = (value) => {
3513
+ try {
3514
+ parseQueryString(value.trim());
3515
+ } catch (e) {
3516
+ setError(e.message);
3517
+ return false;
3518
+ }
3519
+ setError(null);
3520
+ return true;
3521
+ };
3522
+ const handleTextChange = (newValue) => {
3523
+ setTextValue(newValue);
3524
+ if (isValid(newValue)) onChange?.(newValue);
3525
+ };
3526
+ const handleClear = () => {
3527
+ setTextValue("");
3528
+ onChange?.("");
3529
+ isValid("");
3530
+ };
3531
+ const handleInsert = (text) => {
3532
+ const newValue = textValue ? `${textValue}${text} ` : `${text} `;
3533
+ setTextValue(newValue);
3534
+ if (isValid(newValue)) onChange?.(newValue);
3535
+ setTimeout(() => {
3536
+ inputRef.current?.focus();
3537
+ const length = inputRef.current?.value.length || 0;
3538
+ inputRef.current?.setSelectionRange(length, length);
3539
+ }, 0);
3540
+ };
3541
+ useEvents({ "form:change": (event) => {
3542
+ if (event.id === inputRef.current?.form?.id) {
3543
+ if (event.path === textInputProps["data-path"]) setTextValue(event.value ?? "");
3544
+ }
3545
+ } }, []);
3546
+ return /* @__PURE__ */ jsxs(Popover, {
3547
+ width: 800,
3548
+ position: "bottom-start",
3549
+ shadow: "md",
3550
+ opened: helpOpened,
3551
+ onChange: setHelpOpened,
3552
+ closeOnClickOutside: true,
3553
+ closeOnEscape: true,
3554
+ transitionProps: {
3555
+ transition: "fade-up",
3556
+ duration: 200,
3557
+ timingFunction: "ease"
3558
+ },
3559
+ children: [/* @__PURE__ */ jsx(Popover.Target, { children: /* @__PURE__ */ jsx(TextInput, {
3560
+ ref: inputRef,
3561
+ placeholder,
3562
+ value: textValue,
3563
+ onChange: (e) => handleTextChange(e.currentTarget.value),
3564
+ onFocus: () => setHelpOpened(true),
3565
+ leftSection: error ? /* @__PURE__ */ jsx(IconInfoTriangle, { size: 16 }) : /* @__PURE__ */ jsx(IconFilter, { size: 16 }),
3566
+ rightSection: textValue && /* @__PURE__ */ jsx(ActionIcon, {
3567
+ size: "sm",
3568
+ variant: "subtle",
3569
+ color: "gray",
3570
+ onClick: handleClear,
3571
+ children: /* @__PURE__ */ jsx(IconX, { size: 14 })
3572
+ }),
3573
+ ...textInputProps
3574
+ }) }), /* @__PURE__ */ jsx(Popover.Dropdown, {
3575
+ bg: "transparent",
3576
+ p: "xs",
3577
+ bd: `1px solid ${ui.colors.border}`,
3578
+ style: { backdropFilter: "blur(20px)" },
3579
+ children: /* @__PURE__ */ jsx(ControlQueryBuilderHelp, {
3580
+ fields,
3581
+ onInsert: handleInsert
3582
+ })
3583
+ })]
3584
+ });
3585
+ };
2351
3586
 
2352
3587
  //#endregion
2353
3588
  //#region ../../src/core/form/components/ControlSelect.tsx
2354
3589
  /**
2355
- * ControlSelect component for handling Select, MultiSelect, and TagsInput.
3590
+ * ControlSelect component for handling Select, MultiSelect, Autocomplete, and TagsInput.
2356
3591
  *
2357
3592
  * Features:
2358
3593
  * - Basic Select with enum support
2359
3594
  * - MultiSelect for array of enums
2360
- * - TagsInput for array of strings (no enum)
2361
- * - Future: Lazy loading
2362
- * - Future: Searchable/filterable options
2363
- * - Future: Custom option rendering
3595
+ * - Autocomplete for creatable single values
3596
+ * - TagsInput for creatable array values
3597
+ * - Async lazy loading with auto short/long mode detection
3598
+ * - Short mode: client-side filtering with cached data
3599
+ * - Long mode: debounced server search
2364
3600
  *
2365
3601
  * Automatically detects enum values and array types from schema.
2366
3602
  */
2367
3603
  const ControlSelect = (props) => {
2368
- const { inputProps, id, icon } = parseInput(props, useFormState(props.input));
3604
+ const form = useFormState(props.input);
3605
+ const [value, setValue] = useFieldValue(props.input);
3606
+ const { inputProps, id, icon } = parseInput(props, form);
2369
3607
  const isArray = props.input.schema && "type" in props.input.schema && props.input.schema.type === "array";
2370
- let itemsEnum;
2371
- if (isArray && "items" in props.input.schema && props.input.schema.items) {
2372
- const items = props.input.schema.items;
2373
- if ("enum" in items && Array.isArray(items.enum)) itemsEnum = items.enum;
2374
- }
3608
+ const isNumeric = props.input.schema && "type" in props.input.schema && (props.input.schema.type === "integer" || props.input.schema.type === "number");
3609
+ const isBoolean = props.input.schema && "type" in props.input.schema && props.input.schema.type === "boolean";
2375
3610
  const enumValues = props.input.schema && "enum" in props.input.schema && Array.isArray(props.input.schema.enum) ? props.input.schema.enum : [];
2376
- const [data, setData] = useState([]);
3611
+ const { data: asyncData, loading, mode, search } = useAsyncLoader(props.loader, props.loaderThreshold ?? 100, props.loaderDebounce ?? 300, props.input.initialValue);
3612
+ const [staticData, setStaticData] = useState([]);
3613
+ const enumKey = JSON.stringify(enumValues);
2377
3614
  useEffect(() => {
2378
- if (!props.input?.props) return;
2379
- if (props.loader) props.loader().then(setData);
2380
- else setData(enumValues);
2381
- }, [props.input, props.loader]);
3615
+ if (!props.input?.props || props.loader) return;
3616
+ if (isBoolean && enumValues.length === 0) setStaticData([{
3617
+ value: "true",
3618
+ label: "True"
3619
+ }, {
3620
+ value: "false",
3621
+ label: "False"
3622
+ }]);
3623
+ else setStaticData(enumValues);
3624
+ }, [
3625
+ props.input,
3626
+ props.loader,
3627
+ enumKey,
3628
+ isBoolean
3629
+ ]);
3630
+ const data = props.loader ? asyncData : staticData;
2382
3631
  if (!props.input?.props) return null;
2383
- if (props.segmented) {
2384
- const segmentedControlProps = typeof props.segmented === "object" ? props.segmented : {};
3632
+ /**
3633
+ * Coerce value for numeric schemas Select values are always strings.
3634
+ */
3635
+ const coerceValue = (val) => {
3636
+ if (val == null) return val;
3637
+ if (isNumeric) return Number(val);
3638
+ if (isBoolean) return val === "true";
3639
+ return val;
3640
+ };
3641
+ if (props.segmentedProps) {
3642
+ const segmentedControlProps = typeof props.segmentedProps === "object" ? props.segmentedProps : {};
3643
+ const segmentedData = segmentedControlProps.data ?? data.slice(0, 10);
2385
3644
  return /* @__PURE__ */ jsx(Input.Wrapper, {
2386
3645
  ...inputProps,
2387
- children: /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(SegmentedControl, {
2388
- disabled: inputProps.disabled,
2389
- defaultValue: String(props.input.props.defaultValue),
2390
- ...segmentedControlProps,
2391
- onChange: (value) => {
2392
- props.input.set(value);
2393
- },
2394
- data: data.slice(0, 10)
2395
- }) })
3646
+ children: /* @__PURE__ */ jsx(Flex, {
3647
+ my: "calc(var(--mantine-spacing-xs) / 2)",
3648
+ children: /* @__PURE__ */ jsx(SegmentedControl, {
3649
+ disabled: inputProps.disabled,
3650
+ value: value != null ? String(value) : "",
3651
+ ...segmentedControlProps,
3652
+ onChange: (val) => {
3653
+ setValue(coerceValue(val));
3654
+ },
3655
+ data: segmentedData
3656
+ })
3657
+ })
2396
3658
  });
2397
3659
  }
2398
- if (props.autocomplete) {
2399
- const autocompleteProps = typeof props.autocomplete === "object" ? props.autocomplete : {};
2400
- return /* @__PURE__ */ jsx(Autocomplete, {
3660
+ const sharedProps = {
3661
+ size: props.size,
3662
+ id,
3663
+ leftSection: loading ? /* @__PURE__ */ jsx(Loader, {
3664
+ color: "gray",
3665
+ size: 10
3666
+ }) : icon,
3667
+ data
3668
+ };
3669
+ const selectableProps = {
3670
+ ...sharedProps,
3671
+ searchable: true,
3672
+ rightSection: /* @__PURE__ */ jsx("span", {})
3673
+ };
3674
+ const longModeProps = mode === "long" ? {
3675
+ filter: ({ options }) => options,
3676
+ onSearchChange: search.run
3677
+ } : {};
3678
+ if (props.creatable && (isArray || props.tagsInputProps)) {
3679
+ const tagsInputExtraProps = props.tagsInputProps ?? {};
3680
+ return /* @__PURE__ */ jsx(TagsInput, {
2401
3681
  ...inputProps,
2402
- size: props.size,
2403
- id,
2404
- leftSection: icon,
2405
- data,
2406
- ...props.input.props,
2407
- ...autocompleteProps
3682
+ ...sharedProps,
3683
+ ...longModeProps,
3684
+ value: Array.isArray(value) ? value : [],
3685
+ onChange: (val) => {
3686
+ setValue(val);
3687
+ },
3688
+ ...tagsInputExtraProps
2408
3689
  });
2409
3690
  }
2410
- if (isArray && !itemsEnum || props.tags) {
2411
- const tagsInputProps = typeof props.tags === "object" ? props.tags : {};
2412
- return /* @__PURE__ */ jsx(TagsInput, {
3691
+ if (props.creatable) {
3692
+ const autocompleteExtraProps = props.autocompleteProps ?? {};
3693
+ return /* @__PURE__ */ jsx(Autocomplete, {
2413
3694
  ...inputProps,
2414
- size: props.size,
2415
- id,
2416
- leftSection: icon,
2417
- defaultValue: Array.isArray(props.input.props.defaultValue) ? props.input.props.defaultValue : [],
2418
- onChange: (value) => {
2419
- props.input.set(value);
3695
+ ...sharedProps,
3696
+ ...longModeProps,
3697
+ value: value != null ? String(value) : "",
3698
+ onChange: (val) => {
3699
+ setValue(coerceValue(val));
2420
3700
  },
2421
- ...tagsInputProps
3701
+ ...autocompleteExtraProps
2422
3702
  });
2423
3703
  }
2424
- if (isArray && itemsEnum || props.multi) {
2425
- const data = itemsEnum?.map((value) => ({
2426
- value,
2427
- label: value
2428
- })) || [];
2429
- const multiSelectProps = typeof props.multi === "object" ? props.multi : {};
3704
+ if (isArray || props.multiSelectProps) {
3705
+ const multiSelectExtraProps = typeof props.multiSelectProps === "object" ? props.multiSelectProps : {};
2430
3706
  return /* @__PURE__ */ jsx(MultiSelect, {
2431
3707
  ...inputProps,
2432
- size: props.size,
2433
- id,
2434
- leftSection: icon,
2435
- data,
2436
- defaultValue: Array.isArray(props.input.props.defaultValue) ? props.input.props.defaultValue : [],
2437
- onChange: (value) => {
2438
- props.input.set(value);
3708
+ ...selectableProps,
3709
+ ...longModeProps,
3710
+ value: Array.isArray(value) ? value : [],
3711
+ onChange: (val) => {
3712
+ setValue(val);
2439
3713
  },
2440
- ...multiSelectProps
3714
+ ...multiSelectExtraProps
2441
3715
  });
2442
3716
  }
2443
- const selectProps = typeof props.select === "object" ? props.select : {};
3717
+ const selectExtraProps = typeof props.selectProps === "object" ? props.selectProps : {};
3718
+ if (mode === "static") return /* @__PURE__ */ jsx(Select, {
3719
+ ...inputProps,
3720
+ ...selectableProps,
3721
+ value: value != null ? String(value) : null,
3722
+ onChange: (val) => {
3723
+ setValue(coerceValue(val));
3724
+ },
3725
+ ...selectExtraProps
3726
+ });
2444
3727
  return /* @__PURE__ */ jsx(Select, {
2445
3728
  ...inputProps,
2446
- size: props.size,
2447
- id,
2448
- leftSection: icon,
2449
- rightSection: null,
3729
+ ...selectableProps,
3730
+ ...longModeProps,
3731
+ value: value != null ? String(value) : null,
3732
+ onChange: (val) => {
3733
+ setValue(coerceValue(val));
3734
+ },
3735
+ ...selectExtraProps
3736
+ });
3737
+ };
3738
+ /**
3739
+ * Hook for async select data loading with auto short/long mode detection.
3740
+ */
3741
+ const useAsyncLoader = (loader, threshold, debounceMs, defaultValue) => {
3742
+ const [data, setData] = useState([]);
3743
+ const [loading, setLoading] = useState(false);
3744
+ const [mode, setMode] = useState("static");
3745
+ const cache = useRef(/* @__PURE__ */ new Map());
3746
+ useAction({
3747
+ name: "select:loader:init",
3748
+ runOnInit: true,
3749
+ handler: async () => {
3750
+ if (!loader) {
3751
+ setMode("static");
3752
+ return;
3753
+ }
3754
+ setLoading(true);
3755
+ try {
3756
+ const result = await loader("");
3757
+ const isShort = result.length <= threshold;
3758
+ setMode(isShort ? "short" : "long");
3759
+ cache.current.set("", result);
3760
+ setData(result);
3761
+ if (!isShort && defaultValue != null && String(defaultValue) !== "") {
3762
+ const resolved = await loader("", [String(defaultValue)]);
3763
+ if (resolved.length > 0) setData((prev) => {
3764
+ const existing = new Set(prev.map((d) => typeof d === "string" ? d : d.value));
3765
+ const newItems = resolved.filter((r) => {
3766
+ const val = typeof r === "string" ? r : r.value;
3767
+ return !existing.has(val);
3768
+ });
3769
+ return [...prev, ...newItems];
3770
+ });
3771
+ }
3772
+ } finally {
3773
+ setLoading(false);
3774
+ }
3775
+ }
3776
+ }, [loader, threshold]);
3777
+ return {
2450
3778
  data,
2451
- ...props.input.props,
2452
- ...selectProps
2453
- });
3779
+ loading,
3780
+ mode,
3781
+ search: useAction({
3782
+ debounce: debounceMs,
3783
+ handler: async (text) => {
3784
+ if (!loader || mode !== "long") return;
3785
+ if (cache.current.has(text)) {
3786
+ setData(cache.current.get(text));
3787
+ return;
3788
+ }
3789
+ setLoading(true);
3790
+ try {
3791
+ const result = await loader(text);
3792
+ cache.current.set(text, result);
3793
+ setData(result);
3794
+ } finally {
3795
+ setLoading(false);
3796
+ }
3797
+ }
3798
+ }, [
3799
+ loader,
3800
+ mode,
3801
+ debounceMs
3802
+ ])
3803
+ };
2454
3804
  };
2455
3805
 
2456
3806
  //#endregion
@@ -2481,6 +3831,7 @@ const ControlSelect = (props) => {
2481
3831
  */
2482
3832
  const Control = (_props) => {
2483
3833
  const form = useFormState(_props.input, ["error"]);
3834
+ const [value, setValue] = useFieldValue(_props.input);
2484
3835
  if (!_props.input?.props) return null;
2485
3836
  const { inputProps, id, icon, format, schema } = parseInput(_props, form);
2486
3837
  const props = {
@@ -2488,12 +3839,11 @@ const Control = (_props) => {
2488
3839
  ...schema.$control
2489
3840
  };
2490
3841
  if (props.query) return /* @__PURE__ */ jsx(ControlQueryBuilder, {
2491
- ...props.input.props,
2492
3842
  ...inputProps,
2493
3843
  schema: props.query,
2494
- value: props.input.props.value,
2495
- onChange: (value) => {
2496
- props.input.set(value);
3844
+ value,
3845
+ onChange: (val) => {
3846
+ setValue(val);
2497
3847
  }
2498
3848
  });
2499
3849
  if (props.custom) {
@@ -2504,9 +3854,9 @@ const Control = (_props) => {
2504
3854
  flex: 1,
2505
3855
  mt: "calc(var(--mantine-spacing-xs) / 2)",
2506
3856
  children: /* @__PURE__ */ jsx(Custom, {
2507
- defaultValue: props.input.props.defaultValue,
2508
- onChange: (value) => {
2509
- props.input.set(value);
3857
+ value,
3858
+ onChange: (val) => {
3859
+ setValue(val);
2510
3860
  }
2511
3861
  })
2512
3862
  })
@@ -2517,7 +3867,7 @@ const Control = (_props) => {
2517
3867
  const controlObjectProps = typeof props.object === "object" ? props.object : {};
2518
3868
  return /* @__PURE__ */ jsx(ControlObject, {
2519
3869
  input: props.input,
2520
- title: props.title,
3870
+ label: props.label,
2521
3871
  description: props.description,
2522
3872
  ...controlObjectProps
2523
3873
  });
@@ -2528,18 +3878,18 @@ const Control = (_props) => {
2528
3878
  const controlArrayProps = typeof props.array === "object" ? props.array : {};
2529
3879
  return /* @__PURE__ */ jsx(ControlArray, {
2530
3880
  input: props.input,
2531
- title: props.title,
3881
+ label: props.label,
2532
3882
  description: props.description,
2533
3883
  ...controlArrayProps
2534
3884
  });
2535
3885
  }
2536
- if (props.number || props.input.schema && "type" in props.input.schema && (props.input.schema.type === "number" || props.input.schema.type === "integer")) {
3886
+ if (props.number || !props.select && props.input.schema && "type" in props.input.schema && (props.input.schema.type === "number" || props.input.schema.type === "integer")) {
2537
3887
  const controlNumberProps = typeof props.number === "object" ? props.number : {};
2538
3888
  if (props.slider) controlNumberProps.sliderProps ??= {};
2539
3889
  return /* @__PURE__ */ jsx(ControlNumber, {
2540
3890
  size: props.size,
2541
3891
  input: props.input,
2542
- title: props.title,
3892
+ label: props.label,
2543
3893
  description: props.description,
2544
3894
  icon,
2545
3895
  ...controlNumberProps
@@ -2552,9 +3902,7 @@ const Control = (_props) => {
2552
3902
  size: props.size,
2553
3903
  id,
2554
3904
  leftSection: icon,
2555
- onChange: (file) => {
2556
- props.input.set(file);
2557
- },
3905
+ onChange: (file) => setValue(file),
2558
3906
  ...fileInputProps
2559
3907
  });
2560
3908
  }
@@ -2565,17 +3913,18 @@ const Control = (_props) => {
2565
3913
  size: props.size,
2566
3914
  id,
2567
3915
  leftSection: icon,
2568
- ...props.input.props,
3916
+ value: value ?? "",
3917
+ onChange: (val) => setValue(val),
2569
3918
  ...colorInputProps
2570
3919
  });
2571
3920
  }
2572
3921
  if (props.input.schema && "enum" in props.input.schema && props.input.schema.enum || isArray && !isArrayOfObjects || props.select) {
2573
3922
  const opts = typeof props.select === "object" ? props.select : {};
2574
- if (props.segmented) opts.segmented ??= {};
3923
+ if (props.segmented) opts.segmentedProps ??= {};
2575
3924
  return /* @__PURE__ */ jsx(ControlSelect, {
2576
3925
  size: props.size,
2577
3926
  input: props.input,
2578
- title: props.title,
3927
+ label: props.label,
2579
3928
  description: props.description,
2580
3929
  icon,
2581
3930
  ...opts
@@ -2589,16 +3938,16 @@ const Control = (_props) => {
2589
3938
  size: props.size,
2590
3939
  id,
2591
3940
  color: "blue",
2592
- defaultChecked: props.input.props.defaultValue,
3941
+ checked: Boolean(value),
2593
3942
  onChange: (event) => {
2594
- props.input.set(event.currentTarget.checked);
3943
+ setValue(event.currentTarget.checked);
2595
3944
  },
2596
3945
  ...switchProps
2597
3946
  });
2598
3947
  }
2599
3948
  const opts = {
2600
3949
  input: props.input,
2601
- select: { data: [{
3950
+ selectProps: { data: [{
2602
3951
  value: "true",
2603
3952
  label: "Yes"
2604
3953
  }, {
@@ -2608,7 +3957,7 @@ const Control = (_props) => {
2608
3957
  };
2609
3958
  return /* @__PURE__ */ jsx(ControlSelect, {
2610
3959
  size: props.size,
2611
- title: props.title,
3960
+ label: props.label,
2612
3961
  description: props.description,
2613
3962
  icon,
2614
3963
  ...opts
@@ -2621,7 +3970,8 @@ const Control = (_props) => {
2621
3970
  size: props.size,
2622
3971
  id,
2623
3972
  leftSection: icon,
2624
- ...props.input.props,
3973
+ value: value ?? "",
3974
+ onChange: (ev) => setValue(ev.target.value),
2625
3975
  ...passwordInputProps
2626
3976
  });
2627
3977
  }
@@ -2632,14 +3982,15 @@ const Control = (_props) => {
2632
3982
  size: props.size,
2633
3983
  id,
2634
3984
  leftSection: icon,
2635
- ...props.input.props,
3985
+ value: value ?? "",
3986
+ onChange: (ev) => setValue(ev.target.value),
2636
3987
  ...textAreaProps
2637
3988
  });
2638
3989
  }
2639
3990
  if (props.date || props.datetime || props.time || format === "date" || format === "date-time" || format === "time") return /* @__PURE__ */ jsx(ControlDate, {
2640
3991
  size: props.size,
2641
3992
  input: props.input,
2642
- title: props.title,
3993
+ label: props.label,
2643
3994
  description: props.description,
2644
3995
  icon,
2645
3996
  date: props.date,
@@ -2654,7 +4005,7 @@ const Control = (_props) => {
2654
4005
  case "uri": return "url";
2655
4006
  case "tel":
2656
4007
  case "phone": return "tel";
2657
- default: return;
4008
+ default: return props.input.props.type ?? "text";
2658
4009
  }
2659
4010
  };
2660
4011
  return /* @__PURE__ */ jsx(TextInput, {
@@ -2663,14 +4014,9 @@ const Control = (_props) => {
2663
4014
  id,
2664
4015
  leftSection: icon,
2665
4016
  type: getInputType(),
2666
- ...props.input.props,
2667
- ...textInputProps,
2668
- inputWrapperOrder: [
2669
- "label",
2670
- "input",
2671
- "description",
2672
- "error"
2673
- ]
4017
+ value: value ?? "",
4018
+ onChange: (ev) => setValue(ev.target.value),
4019
+ ...textInputProps
2674
4020
  });
2675
4021
  };
2676
4022
 
@@ -2719,6 +4065,7 @@ const Control = (_props) => {
2719
4065
  */
2720
4066
  const TypeForm = (props) => {
2721
4067
  const { form, columns = 3, children, controlProps, fieldControlProps, skipFormElement = false, skipSubmitButton = false, submitButtonProps, fill = true, size } = props;
4068
+ const { dirty } = useFormState(form, ["dirty"]);
2722
4069
  const schema = props.schema || form.options.schema;
2723
4070
  if (!schema?.properties) return null;
2724
4071
  const supportedFields = Object.keys(schema.properties);
@@ -2781,10 +4128,12 @@ const TypeForm = (props) => {
2781
4128
  children: [/* @__PURE__ */ jsx(ActionButton, {
2782
4129
  variant: "subtle",
2783
4130
  type: "reset",
4131
+ disabled: !dirty,
2784
4132
  children: "Reset"
2785
4133
  }), /* @__PURE__ */ jsx(ActionButton, {
2786
4134
  intent: "primary",
2787
4135
  form,
4136
+ disabled: !dirty,
2788
4137
  ...submitButtonProps,
2789
4138
  children: submitButtonProps?.children ?? "Submit"
2790
4139
  })]
@@ -2804,33 +4153,27 @@ const TypeForm = (props) => {
2804
4153
  };
2805
4154
 
2806
4155
  //#endregion
2807
- //#region ../../src/core/helpers/renderIcon.tsx
2808
- const renderIcon = (icon, size) => {
2809
- if (!icon) return null;
2810
- if (isValidElement(icon)) return icon;
2811
- if (isComponentType(icon)) return /* @__PURE__ */ jsx(icon, { size: size ?? ui.sizes.icon.md });
2812
- return icon;
2813
- };
2814
-
2815
- //#endregion
2816
- //#region ../../src/core/hooks/useDialog.ts
2817
- /**
2818
- * Use this hook to access the Dialog Service for showing various dialog types.
2819
- *
2820
- * @example
2821
- * ```tsx
2822
- * const dialog = useDialog();
2823
- * await dialog.alert({ title: "Alert", message: "This is an alert message" });
2824
- * const confirmed = await dialog.confirm({ title: "Confirm", message: "Are you sure?" });
2825
- * const input = await dialog.prompt({ title: "Input", message: "Enter your name:" });
2826
- * ```
2827
- */
2828
- const useDialog = () => {
2829
- return useInject(DialogService);
4156
+ //#region ../../src/core/json/components/JsonViewerCopyButton.tsx
4157
+ const JsonViewerCopyButton = (props) => {
4158
+ const [copied, setCopied] = useState(false);
4159
+ const handleCopy = useCallback((e) => {
4160
+ e.stopPropagation();
4161
+ navigator.clipboard.writeText(props.value);
4162
+ setCopied(true);
4163
+ setTimeout(() => setCopied(false), 1500);
4164
+ }, [props.value]);
4165
+ return /* @__PURE__ */ jsx(ActionIcon, {
4166
+ size: props.iconSize + 4,
4167
+ variant: "transparent",
4168
+ c: copied ? "green" : "dimmed",
4169
+ onClick: handleCopy,
4170
+ className: "alepha-json-viewer-copy",
4171
+ children: copied ? /* @__PURE__ */ jsx(IconCheck, { size: props.iconSize }) : /* @__PURE__ */ jsx(IconCopy, { size: props.iconSize })
4172
+ });
2830
4173
  };
2831
4174
 
2832
4175
  //#endregion
2833
- //#region ../../src/core/json/components/JsonViewer.tsx
4176
+ //#region ../../src/core/json/components/JsonViewerShared.ts
2834
4177
  const SIZE_CONFIG = {
2835
4178
  xs: {
2836
4179
  icon: 14,
@@ -2879,77 +4222,21 @@ const getValueType = (val) => {
2879
4222
  if (Array.isArray(val)) return "array";
2880
4223
  return typeof val;
2881
4224
  };
2882
- function buildTreeNodes(data, path = [], key, isArrayItem = false, maxDepth = 10) {
2883
- const currentPath = key !== void 0 ? [...path, key] : path;
2884
- const nodeId = currentPath.length > 0 ? currentPath.join(".") : "root";
2885
- if (currentPath.length > maxDepth) return {
2886
- value: nodeId,
2887
- label: key ?? "",
2888
- nodeValue: data,
2889
- nodeKey: key,
2890
- path: currentPath,
2891
- isArrayItem
2892
- };
2893
- const type = getValueType(data);
2894
- if (type === "object" || type === "array") {
2895
- 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);
2896
- return {
2897
- value: nodeId,
2898
- label: key ?? "",
2899
- nodeValue: data,
2900
- nodeKey: key,
2901
- path: currentPath,
2902
- isArrayItem,
2903
- children: children.length > 0 ? children : void 0
2904
- };
2905
- }
2906
- return {
2907
- value: nodeId,
2908
- label: key ?? "",
2909
- nodeValue: data,
2910
- nodeKey: key,
2911
- path: currentPath,
2912
- isArrayItem
2913
- };
2914
- }
2915
- function getExpandedIds(nodes, targetDepth, currentDepth = 0) {
2916
- if (currentDepth >= targetDepth) return [];
2917
- const ids = [];
2918
- for (const node of nodes) if (node.children) {
2919
- ids.push(node.value);
2920
- ids.push(...getExpandedIds(node.children, targetDepth, currentDepth + 1));
2921
- }
2922
- return ids;
2923
- }
2924
- const CopyButton = ({ value, iconSize }) => {
2925
- const [copied, setCopied] = useState(false);
2926
- const handleCopy = useCallback((e) => {
2927
- e.stopPropagation();
2928
- navigator.clipboard.writeText(value);
2929
- setCopied(true);
2930
- setTimeout(() => setCopied(false), 1500);
2931
- }, [value]);
2932
- return /* @__PURE__ */ jsx(ActionIcon, {
2933
- size: iconSize + 4,
2934
- variant: "transparent",
2935
- c: copied ? "green" : "dimmed",
2936
- onClick: handleCopy,
2937
- className: "alepha-json-viewer-copy",
2938
- children: copied ? /* @__PURE__ */ jsx(IconCheck, { size: iconSize }) : /* @__PURE__ */ jsx(IconCopy, { size: iconSize })
2939
- });
2940
- };
2941
- const RowNode = ({ node, expanded, hasChildren, elementProps, size, config, showQuotes, showCopyButton, renderValue }) => {
2942
- const { nodeValue, nodeKey, path, isArrayItem, isRoot } = node;
4225
+
4226
+ //#endregion
4227
+ //#region ../../src/core/json/components/JsonViewerRowNode.tsx
4228
+ const JsonViewerRowNode = (props) => {
4229
+ const { nodeValue, nodeKey, path, isArrayItem } = props.node;
2943
4230
  const type = getValueType(nodeValue);
2944
4231
  const isExpandable = type === "object" || type === "array";
2945
4232
  const getPreview = () => {
2946
4233
  if (!isExpandable) return null;
2947
4234
  const count = (type === "array" ? nodeValue : Object.keys(nodeValue)).length;
2948
4235
  const label = type === "array" ? "item" : "key";
2949
- if (!expanded) return /* @__PURE__ */ jsx(Text, {
4236
+ if (!props.expanded) return /* @__PURE__ */ jsx(Text, {
2950
4237
  fs: "italic",
2951
4238
  component: "span",
2952
- size,
4239
+ size: props.size,
2953
4240
  style: STYLES.preview,
2954
4241
  children: count === 0 ? type === "array" ? "[]" : "{}" : type === "array" ? `[ ${count} ${count === 1 ? label : `${label}s`} ]` : `{ ${count} ${count === 1 ? label : `${label}s`} }`
2955
4242
  });
@@ -2959,25 +4246,25 @@ const RowNode = ({ node, expanded, hasChildren, elementProps, size, config, show
2959
4246
  return /* @__PURE__ */ jsxs(Flex, {
2960
4247
  gap: 6,
2961
4248
  wrap: "nowrap",
2962
- ...elementProps,
2963
- className: `alepha-json-viewer-row ${elementProps.className || ""}`,
4249
+ ...props.elementProps,
4250
+ className: `alepha-json-viewer-row ${props.elementProps.className || ""}`,
2964
4251
  children: [
2965
- hasChildren ? expanded ? /* @__PURE__ */ jsx(IconChevronDown, {
2966
- size: config.icon,
4252
+ props.hasChildren ? props.expanded ? /* @__PURE__ */ jsx(IconChevronDown, {
4253
+ size: props.config.icon,
2967
4254
  style: STYLES.chevron
2968
4255
  }) : /* @__PURE__ */ jsx(IconChevronRight, {
2969
- size: config.icon,
4256
+ size: props.config.icon,
2970
4257
  style: STYLES.chevron
2971
4258
  }) : /* @__PURE__ */ jsx("span", { style: {
2972
- width: config.icon,
4259
+ width: props.config.icon,
2973
4260
  flexShrink: 0
2974
4261
  } }),
2975
4262
  nodeKey !== void 0 && !isArrayItem && /* @__PURE__ */ jsxs(Text, {
2976
4263
  component: "span",
2977
- size,
4264
+ size: props.size,
2978
4265
  children: [/* @__PURE__ */ jsx("span", {
2979
4266
  style: STYLES.key,
2980
- children: showQuotes ? `"${nodeKey}"` : nodeKey
4267
+ children: props.showQuotes ? `"${nodeKey}"` : nodeKey
2981
4268
  }), /* @__PURE__ */ jsx("span", {
2982
4269
  style: STYLES.colon,
2983
4270
  children: ":"
@@ -2985,7 +4272,7 @@ const RowNode = ({ node, expanded, hasChildren, elementProps, size, config, show
2985
4272
  }),
2986
4273
  nodeKey !== void 0 && isArrayItem && /* @__PURE__ */ jsxs(Text, {
2987
4274
  component: "span",
2988
- size,
4275
+ size: props.size,
2989
4276
  children: [/* @__PURE__ */ jsx("span", {
2990
4277
  style: STYLES.key,
2991
4278
  children: nodeKey
@@ -2994,25 +4281,29 @@ const RowNode = ({ node, expanded, hasChildren, elementProps, size, config, show
2994
4281
  children: ":"
2995
4282
  })]
2996
4283
  }),
2997
- hasChildren ? getPreview() : isExpandable ? type === "array" ? /* @__PURE__ */ jsx(Text, {
4284
+ props.hasChildren ? getPreview() : isExpandable ? type === "array" ? /* @__PURE__ */ jsx(Text, {
2998
4285
  component: "span",
2999
- size,
4286
+ size: props.size,
3000
4287
  style: STYLES.preview,
3001
4288
  children: "[]"
3002
4289
  }) : /* @__PURE__ */ jsx(Text, {
3003
4290
  component: "span",
3004
- size,
4291
+ size: props.size,
3005
4292
  style: STYLES.preview,
3006
4293
  children: "{}"
3007
- }) : renderValue(nodeValue, nodeKey, path),
3008
- showCopyButton && /* @__PURE__ */ jsx(CopyButton, {
4294
+ }) : props.renderValue(nodeValue, nodeKey, path),
4295
+ props.showCopyButton && /* @__PURE__ */ jsx(JsonViewerCopyButton, {
3009
4296
  value: getCopyValue(),
3010
- iconSize: config.icon
4297
+ iconSize: props.config.icon
3011
4298
  })
3012
4299
  ]
3013
4300
  });
3014
4301
  };
3015
- const JsonViewer = ({ data, defaultExpandedDepth = 2, maxDepth = 10, size = "sm", showQuotes = false, showCopyButton = true, formatValue }) => {
4302
+
4303
+ //#endregion
4304
+ //#region ../../src/core/json/components/JsonViewer.tsx
4305
+ const JsonViewer = (props) => {
4306
+ const { data, defaultExpandedDepth = 2, maxDepth = 10, size = "sm", showQuotes = false, showCopyButton = true, formatValue } = props;
3016
4307
  const config = SIZE_CONFIG[size] || SIZE_CONFIG.sm;
3017
4308
  const treeData = useMemo(() => {
3018
4309
  const type = getValueType(data);
@@ -3092,7 +4383,7 @@ const JsonViewer = ({ data, defaultExpandedDepth = 2, maxDepth = 10, size = "sm"
3092
4383
  size
3093
4384
  ]);
3094
4385
  const renderNode = useCallback(({ node, expanded, hasChildren, elementProps }) => {
3095
- return /* @__PURE__ */ jsx(RowNode, {
4386
+ return /* @__PURE__ */ jsx(JsonViewerRowNode, {
3096
4387
  node,
3097
4388
  expanded,
3098
4389
  hasChildren,
@@ -3124,6 +4415,54 @@ const JsonViewer = ({ data, defaultExpandedDepth = 2, maxDepth = 10, size = "sm"
3124
4415
  styles: { root: STYLES.root }
3125
4416
  });
3126
4417
  };
4418
+ /**
4419
+ * Convert JSON to tree data structure.
4420
+ */
4421
+ const buildTreeNodes = (data, path = [], key, isArrayItem = false, maxDepth = 10) => {
4422
+ const currentPath = key !== void 0 ? [...path, key] : path;
4423
+ const nodeId = currentPath.length > 0 ? currentPath.join(".") : "root";
4424
+ if (currentPath.length > maxDepth) return {
4425
+ value: nodeId,
4426
+ label: key ?? "",
4427
+ nodeValue: data,
4428
+ nodeKey: key,
4429
+ path: currentPath,
4430
+ isArrayItem
4431
+ };
4432
+ const type = getValueType(data);
4433
+ if (type === "object" || type === "array") {
4434
+ 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);
4435
+ return {
4436
+ value: nodeId,
4437
+ label: key ?? "",
4438
+ nodeValue: data,
4439
+ nodeKey: key,
4440
+ path: currentPath,
4441
+ isArrayItem,
4442
+ children: children.length > 0 ? children : void 0
4443
+ };
4444
+ }
4445
+ return {
4446
+ value: nodeId,
4447
+ label: key ?? "",
4448
+ nodeValue: data,
4449
+ nodeKey: key,
4450
+ path: currentPath,
4451
+ isArrayItem
4452
+ };
4453
+ };
4454
+ /**
4455
+ * Get all expandable node IDs up to a certain depth.
4456
+ */
4457
+ const getExpandedIds = (nodes, targetDepth, currentDepth = 0) => {
4458
+ if (currentDepth >= targetDepth) return [];
4459
+ const ids = [];
4460
+ for (const node of nodes) if (node.children) {
4461
+ ids.push(node.value);
4462
+ ids.push(...getExpandedIds(node.children, targetDepth, currentDepth + 1));
4463
+ }
4464
+ return ids;
4465
+ };
3127
4466
 
3128
4467
  //#endregion
3129
4468
  //#region ../../src/core/table/interfaces/types.ts
@@ -3131,7 +4470,8 @@ const DEFAULT_MAX_VISIBLE_COLUMNS = 8;
3131
4470
 
3132
4471
  //#endregion
3133
4472
  //#region ../../src/core/table/components/DataTableFilters.tsx
3134
- const DataTableFilters = ({ schema, form, typeFormProps, filterVisibility }) => {
4473
+ const DataTableFilters = (props) => {
4474
+ const { schema, form, typeFormProps, filterVisibility } = props;
3135
4475
  const visibleSchema = useMemo(() => {
3136
4476
  const visibleKeys = Object.keys(schema.properties).filter((key) => filterVisibility[key] !== false);
3137
4477
  if (visibleKeys.length === 0) return null;
@@ -3142,13 +4482,14 @@ const DataTableFilters = ({ schema, form, typeFormProps, filterVisibility }) =>
3142
4482
  return t.object(visibleProps);
3143
4483
  }, [schema, filterVisibility]);
3144
4484
  if (!visibleSchema) return null;
3145
- return /* @__PURE__ */ jsx(Flex, {
3146
- w: "100%",
4485
+ return /* @__PURE__ */ jsx(Flex$1, {
4486
+ surface: true,
4487
+ flex: 1,
4488
+ mt: -4,
3147
4489
  p: "xs",
3148
- bg: ui.colors.surface,
3149
- style: { borderBottom: "1px solid var(--alepha-border)" },
4490
+ m: "xs",
4491
+ bdrs: "md",
3150
4492
  children: /* @__PURE__ */ jsx(TypeForm, {
3151
- size: "xs",
3152
4493
  ...typeFormProps,
3153
4494
  skipSubmitButton: true,
3154
4495
  fill: true,
@@ -3159,7 +4500,7 @@ const DataTableFilters = ({ schema, form, typeFormProps, filterVisibility }) =>
3159
4500
  sm: 2,
3160
4501
  md: 3,
3161
4502
  lg: 4,
3162
- xl: 6
4503
+ xl: 5
3163
4504
  }
3164
4505
  })
3165
4506
  });
@@ -3167,48 +4508,64 @@ const DataTableFilters = ({ schema, form, typeFormProps, filterVisibility }) =>
3167
4508
 
3168
4509
  //#endregion
3169
4510
  //#region ../../src/core/table/components/DataTablePagination.tsx
3170
- const DataTablePagination = ({ page, size, totalPages, onPageChange, onSizeChange }) => {
3171
- return /* @__PURE__ */ jsxs(Flex, {
4511
+ const DataTablePagination = ({ page, size, totalPages, totalElements, isFirst, isLast, offset, numberOfElements, onPageChange, onSizeChange }) => {
4512
+ const from = numberOfElements > 0 ? offset + 1 : 0;
4513
+ const to = offset + numberOfElements;
4514
+ const hasTotal = totalPages != null;
4515
+ return /* @__PURE__ */ jsxs(Flex$1, {
3172
4516
  align: "center",
3173
- justify: "end",
4517
+ justify: "space-between",
3174
4518
  gap: "md",
3175
- p: "xs",
4519
+ px: "xs",
4520
+ py: 4,
3176
4521
  style: { borderTop: "1px solid var(--alepha-border)" },
3177
- children: [/* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(Select, {
3178
- w: 96,
3179
- variant: "default",
3180
- value: size,
3181
- onChange: (value) => {
3182
- if (value) onSizeChange(Number(value));
3183
- },
3184
- data: [
3185
- {
3186
- value: "5",
3187
- label: "5"
3188
- },
3189
- {
3190
- value: "10",
3191
- label: "10"
3192
- },
3193
- {
3194
- value: "25",
3195
- label: "25"
3196
- },
3197
- {
3198
- value: "50",
3199
- label: "50"
4522
+ children: [/* @__PURE__ */ jsx(Flex$1, {
4523
+ align: "center",
4524
+ children: /* @__PURE__ */ jsx(Text$1, {
4525
+ size: "xs",
4526
+ c: "dimmed",
4527
+ children: totalElements != null ? `Showing ${from} - ${to} of ${totalElements}` : `Showing ${from} - ${to}`
4528
+ })
4529
+ }), /* @__PURE__ */ jsxs(Flex$1, {
4530
+ align: "center",
4531
+ gap: "md",
4532
+ children: [/* @__PURE__ */ jsx(Flex$1, { children: /* @__PURE__ */ jsx(Select, {
4533
+ color: "gray",
4534
+ c: "gray",
4535
+ size: "xs",
4536
+ w: 96,
4537
+ variant: "default",
4538
+ value: size,
4539
+ onChange: (value) => {
4540
+ if (value) onSizeChange(Number(value));
3200
4541
  },
3201
- {
3202
- value: "100",
3203
- label: "100"
3204
- }
3205
- ]
3206
- }) }), /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(Pagination, {
3207
- withEdges: true,
3208
- total: totalPages,
3209
- value: page,
3210
- onChange: onPageChange
3211
- }) })]
4542
+ data: [
4543
+ {
4544
+ value: "10",
4545
+ label: "10"
4546
+ },
4547
+ {
4548
+ value: "25",
4549
+ label: "25"
4550
+ },
4551
+ {
4552
+ value: "50",
4553
+ label: "50"
4554
+ },
4555
+ {
4556
+ value: "100",
4557
+ label: "100"
4558
+ }
4559
+ ]
4560
+ }) }), /* @__PURE__ */ jsx(Flex$1, { children: /* @__PURE__ */ jsx(Pagination, {
4561
+ size: "sm",
4562
+ withEdges: hasTotal,
4563
+ withPages: hasTotal,
4564
+ total: hasTotal ? totalPages : isLast !== false ? page : page + 1,
4565
+ value: page,
4566
+ onChange: onPageChange
4567
+ }) })]
4568
+ })]
3212
4569
  });
3213
4570
  };
3214
4571
 
@@ -3255,7 +4612,7 @@ const ColumnPicker = ({ columns, visibility, onVisibilityChange }) => {
3255
4612
  timingFunction: "ease"
3256
4613
  },
3257
4614
  children: [/* @__PURE__ */ jsx(Popover.Target, { children: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(ActionButton, {
3258
- variant: "subtle",
4615
+ variant: "minimal",
3259
4616
  icon: IconColumns,
3260
4617
  onClick: () => setOpened((o) => !o)
3261
4618
  }) }) }), /* @__PURE__ */ jsx(Popover.Dropdown, {
@@ -3285,12 +4642,12 @@ const ColumnPicker = ({ columns, visibility, onVisibilityChange }) => {
3285
4642
  gap: 4,
3286
4643
  children: [/* @__PURE__ */ jsx(ActionButton, {
3287
4644
  size: "compact-xs",
3288
- variant: "subtle",
4645
+ variant: "minimal",
3289
4646
  onClick: handleShowAll,
3290
4647
  children: "All"
3291
4648
  }), /* @__PURE__ */ jsx(ActionButton, {
3292
4649
  size: "compact-xs",
3293
- variant: "subtle",
4650
+ variant: "minimal",
3294
4651
  onClick: handleDefault,
3295
4652
  children: "Default"
3296
4653
  })]
@@ -3356,7 +4713,7 @@ const FilterPicker = ({ schema, visibility, onVisibilityChange }) => {
3356
4713
  timingFunction: "ease"
3357
4714
  },
3358
4715
  children: [/* @__PURE__ */ jsx(Popover.Target, { children: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(ActionButton, {
3359
- variant: "subtle",
4716
+ variant: "minimal",
3360
4717
  icon: IconFilter,
3361
4718
  onClick: () => setOpened((o) => !o)
3362
4719
  }) }) }), /* @__PURE__ */ jsx(Popover.Dropdown, {
@@ -3386,12 +4743,12 @@ const FilterPicker = ({ schema, visibility, onVisibilityChange }) => {
3386
4743
  gap: 4,
3387
4744
  children: [/* @__PURE__ */ jsx(ActionButton, {
3388
4745
  size: "compact-xs",
3389
- variant: "subtle",
4746
+ variant: "minimal",
3390
4747
  onClick: handleShowAll,
3391
4748
  children: "All"
3392
4749
  }), /* @__PURE__ */ jsx(ActionButton, {
3393
4750
  size: "compact-xs",
3394
- variant: "subtle",
4751
+ variant: "minimal",
3395
4752
  onClick: handleHideAll,
3396
4753
  children: "None"
3397
4754
  })]
@@ -3430,7 +4787,7 @@ const extractText = (node) => {
3430
4787
  const DataTableToolbar = ({ columns, filters, columnVisibility, filterVisibility, onColumnVisibilityChange, onFilterVisibilityChange, actions, onRefresh, items, withExport, selectedItems = [], checkboxActions, onClearSelection }) => {
3431
4788
  const hasSelection = selectedItems.length > 0;
3432
4789
  const exportableColumns = useCallback(() => {
3433
- return Object.entries(columns).filter(([key, col]) => !col.actions && columnVisibility[key] !== false);
4790
+ return Object.entries(columns).filter(([key]) => columnVisibility[key] !== false);
3434
4791
  }, [columns, columnVisibility]);
3435
4792
  const buildRows = useCallback(() => {
3436
4793
  const cols = exportableColumns();
@@ -3467,11 +4824,10 @@ const DataTableToolbar = ({ columns, filters, columnVisibility, filterVisibility
3467
4824
  };
3468
4825
  await action.onClick(ctx);
3469
4826
  };
3470
- return /* @__PURE__ */ jsxs(Flex, {
4827
+ return /* @__PURE__ */ jsxs(Flex$1, {
3471
4828
  p: "xs",
3472
- style: { borderBottom: "1px solid var(--alepha-border)" },
3473
4829
  children: [
3474
- /* @__PURE__ */ jsxs(Flex, {
4830
+ /* @__PURE__ */ jsxs(Flex$1, {
3475
4831
  gap: 4,
3476
4832
  align: "center",
3477
4833
  children: [
@@ -3486,7 +4842,7 @@ const DataTableToolbar = ({ columns, filters, columnVisibility, filterVisibility
3486
4842
  onVisibilityChange: onColumnVisibilityChange
3487
4843
  }),
3488
4844
  withExport && /* @__PURE__ */ jsx(ActionButton, {
3489
- variant: "subtle",
4845
+ variant: "minimal",
3490
4846
  icon: IconDownload,
3491
4847
  menu: { items: [{
3492
4848
  label: "Export as CSV",
@@ -3509,7 +4865,7 @@ const DataTableToolbar = ({ columns, filters, columnVisibility, filterVisibility
3509
4865
  children: [selectedItems.length, " selected"]
3510
4866
  }),
3511
4867
  /* @__PURE__ */ jsx(ActionButton, {
3512
- variant: "subtle",
4868
+ variant: "minimal",
3513
4869
  size: "compact-sm",
3514
4870
  icon: IconX,
3515
4871
  onClick: onClearSelection,
@@ -3526,14 +4882,14 @@ const DataTableToolbar = ({ columns, filters, columnVisibility, filterVisibility
3526
4882
  ] })
3527
4883
  ]
3528
4884
  }),
3529
- /* @__PURE__ */ jsx(Flex, { flex: 1 }),
3530
- /* @__PURE__ */ jsxs(Flex, {
4885
+ /* @__PURE__ */ jsx(Flex$1, { flex: 1 }),
4886
+ /* @__PURE__ */ jsxs(Flex$1, {
3531
4887
  gap: "xs",
3532
4888
  children: [actions?.map((props, index) => !isValidElement(props) ? /* @__PURE__ */ jsx(ActionButton, {
3533
4889
  ...props,
3534
4890
  children: props.label
3535
4891
  }, index) : props), /* @__PURE__ */ jsx(ActionButton, {
3536
- variant: "subtle",
4892
+ variant: "minimal",
3537
4893
  icon: IconRefresh,
3538
4894
  onClick: onRefresh
3539
4895
  })]
@@ -3642,12 +4998,16 @@ const FIT_STYLE = {
3642
4998
  };
3643
4999
  const DataTable = (props) => {
3644
5000
  const [items, setItems] = useState(typeof props.items === "function" ? { content: [] } : props.items);
3645
- const defaultSize = props.infinityScroll ? 100 : props.defaultSize || 10;
5001
+ const itemsRef = useRef(items);
5002
+ const [loaded, setLoaded] = useState(typeof props.items !== "function" || !props.submitOnInit);
5003
+ const defaultSize = props.defaultSize || (props.infinityScroll ? 100 : 10);
3646
5004
  const [page, setPage] = useState(1);
3647
5005
  const [size, setSize] = useState(String(defaultSize));
3648
5006
  const [currentPage, setCurrentPage] = useState(0);
3649
5007
  const alepha = useInject(Alepha);
5008
+ itemsRef.current = items;
3650
5009
  const sentinelRef = useRef(null);
5010
+ const debounceRef = useRef(null);
3651
5011
  const [columnVisibility, setColumnVisibility] = useState(() => {
3652
5012
  const entries = Object.entries(props.columns);
3653
5013
  let visibleCount = 0;
@@ -3720,13 +5080,14 @@ const DataTable = (props) => {
3720
5080
  }),
3721
5081
  handler: async (values) => {
3722
5082
  if (typeof props.items === "function") {
3723
- const response = await props.items(values, { items: items.content });
5083
+ const response = await props.items(values, { items: itemsRef.current.content });
3724
5084
  if (props.infinityScroll && values.page > 0) setItems((prev) => ({
3725
5085
  ...response,
3726
5086
  content: [...prev.content, ...response.content]
3727
5087
  }));
3728
5088
  else setItems(response);
3729
5089
  setCurrentPage(values.page);
5090
+ if (!loaded) setLoaded(true);
3730
5091
  }
3731
5092
  },
3732
5093
  onReset: async () => {
@@ -3746,9 +5107,23 @@ const DataTable = (props) => {
3746
5107
  return;
3747
5108
  }
3748
5109
  props.onFilterChange?.(key, value, form);
5110
+ if (props.skipSubmitOnChange) return;
5111
+ form.input.page.set(0);
5112
+ const delay = props.debounce ?? 300;
5113
+ if (delay > 0) {
5114
+ if (debounceRef.current) clearTimeout(debounceRef.current);
5115
+ debounceRef.current = setTimeout(() => {
5116
+ form.submit();
5117
+ }, delay);
5118
+ } else await form.submit();
3749
5119
  }
3750
- }, [items]);
5120
+ }, []);
3751
5121
  const dt = useInject(DateTimeProvider);
5122
+ useEffect(() => {
5123
+ return () => {
5124
+ if (debounceRef.current) clearTimeout(debounceRef.current);
5125
+ };
5126
+ }, []);
3752
5127
  useEffect(() => {
3753
5128
  if (props.submitOnInit) form.submit();
3754
5129
  if (props.submitEvery) {
@@ -3779,7 +5154,7 @@ const DataTable = (props) => {
3779
5154
  currentPage,
3780
5155
  form
3781
5156
  ]);
3782
- const totalColumns = visibleColumns.length + (panelConfig ? 1 : 0) + (props.withCheckbox ? 1 : 0);
5157
+ const totalColumns = visibleColumns.length + (panelConfig ? 1 : 0) + (props.withCheckbox ? 1 : 0) + (props.rowActions ? 1 : 0);
3783
5158
  const checkboxHeader = props.withCheckbox ? /* @__PURE__ */ jsx(Table.Th, {
3784
5159
  style: { width: 40 },
3785
5160
  children: /* @__PURE__ */ jsx(Checkbox, {
@@ -3802,18 +5177,20 @@ const DataTable = (props) => {
3802
5177
  userSelect: "none"
3803
5178
  } : {}
3804
5179
  },
3805
- children: /* @__PURE__ */ jsxs(Flex, {
5180
+ children: /* @__PURE__ */ jsxs(Flex$1, {
3806
5181
  align: "center",
3807
5182
  gap: 4,
3808
- children: [/* @__PURE__ */ jsx(Text, {
5183
+ children: [/* @__PURE__ */ jsx(Text$1, {
5184
+ bold: true,
5185
+ muted: true,
3809
5186
  size: "xs",
3810
5187
  children: col.label
3811
- }), col.sortable && /* @__PURE__ */ jsxs(Flex, {
5188
+ }), col.sortable && /* @__PURE__ */ jsxs(Flex$1, {
3812
5189
  c: "dimmed",
3813
5190
  children: [
3814
- sortDir === "asc" && /* @__PURE__ */ jsx(IconArrowUp, { size: ui.sizes.icon.sm }),
3815
- sortDir === "desc" && /* @__PURE__ */ jsx(IconArrowDown, { size: ui.sizes.icon.sm }),
3816
- sortDir === null && /* @__PURE__ */ jsx(IconArrowsSort, { size: ui.sizes.icon.sm })
5191
+ sortDir === "asc" && /* @__PURE__ */ jsx(IconArrowUp, { size: ui.sizes.icon.xs }),
5192
+ sortDir === "desc" && /* @__PURE__ */ jsx(IconArrowDown, { size: ui.sizes.icon.xs }),
5193
+ sortDir === null && /* @__PURE__ */ jsx(IconArrowsSort, { size: ui.sizes.icon.xs })
3817
5194
  ]
3818
5195
  })]
3819
5196
  })
@@ -3850,7 +5227,7 @@ const DataTable = (props) => {
3850
5227
  toggleExpand(itemKey);
3851
5228
  },
3852
5229
  style: { display: "inline-flex" },
3853
- children: /* @__PURE__ */ jsx(Flex, {
5230
+ children: /* @__PURE__ */ jsx(Flex$1, {
3854
5231
  c: "dimmed",
3855
5232
  align: "center",
3856
5233
  justify: "center",
@@ -3873,32 +5250,49 @@ const DataTable = (props) => {
3873
5250
  form,
3874
5251
  alepha
3875
5252
  };
3876
- if (col.actions) {
3877
- const rowActions = col.actions(item, ctx).filter((a) => a.visible !== false);
3878
- return /* @__PURE__ */ jsx(Table.Td, {
3879
- py: 2,
3880
- px: 4,
3881
- style: col.fit ? FIT_STYLE : void 0,
3882
- onClick: (e) => e.stopPropagation(),
3883
- children: /* @__PURE__ */ jsx(Flex, {
3884
- gap: 4,
3885
- children: rowActions.map(({ visible: _, ...actionProps }, i) => /* @__PURE__ */ jsx(ActionButton, {
3886
- variant: "subtle",
3887
- size: "xs",
3888
- preventDefault: true,
3889
- h: 20,
3890
- ...actionProps
3891
- }, i))
3892
- })
3893
- }, key);
3894
- }
5253
+ const content = col.value?.(item, ctx);
3895
5254
  return /* @__PURE__ */ jsx(Table.Td, {
3896
- py: 2,
3897
- px: 4,
3898
5255
  style: col.fit ? FIT_STYLE : void 0,
3899
- children: col.value?.(item, ctx)
5256
+ children: col.action ? /* @__PURE__ */ jsx(ActionButton, {
5257
+ td: "inherit",
5258
+ unstyled: true,
5259
+ ...col.action(item),
5260
+ children: content
5261
+ }) : content
3900
5262
  }, key);
3901
- })
5263
+ }),
5264
+ props.rowActions && (() => {
5265
+ const ctx = {
5266
+ index,
5267
+ form,
5268
+ alepha
5269
+ };
5270
+ const actions = props.rowActions(item, ctx).filter((a) => a.visible !== false);
5271
+ if (actions.length === 0) return /* @__PURE__ */ jsx(Table.Td, { style: FIT_STYLE });
5272
+ return /* @__PURE__ */ jsx(Table.Td, {
5273
+ py: 2,
5274
+ px: 4,
5275
+ style: FIT_STYLE,
5276
+ onClick: (e) => e.stopPropagation(),
5277
+ children: /* @__PURE__ */ jsx(ActionButton, {
5278
+ variant: "minimal",
5279
+ size: "xs",
5280
+ icon: IconDotsVertical,
5281
+ menu: { items: actions.map((action) => {
5282
+ const Icon = action.icon;
5283
+ return {
5284
+ label: action.label ?? (typeof action.tooltip === "string" ? action.tooltip : void 0),
5285
+ icon: Icon && isComponentType(Icon) ? /* @__PURE__ */ jsx(Icon, { size: 14 }) : Icon,
5286
+ onClick: action.onClick ? async () => {
5287
+ await action.onClick();
5288
+ if (!action.skipRefresh) await form.submit();
5289
+ } : void 0,
5290
+ color: action.color
5291
+ };
5292
+ }) }
5293
+ })
5294
+ });
5295
+ })()
3902
5296
  ]
3903
5297
  }, itemKey)];
3904
5298
  if (panelConfig && showPanel && isExpanded) elements.push(/* @__PURE__ */ jsx(Table.Tr, { children: /* @__PURE__ */ jsx(Table.Td, {
@@ -3916,13 +5310,19 @@ const DataTable = (props) => {
3916
5310
  "sort"
3917
5311
  ]);
3918
5312
  }, [props.filters, form.options.schema]);
3919
- return /* @__PURE__ */ jsxs(Flex, {
5313
+ return /* @__PURE__ */ jsxs(Flex$1, {
5314
+ gap: "xs",
3920
5315
  flex: 1,
3921
5316
  p: 0,
3922
- bdrs: "sm",
3923
5317
  direction: "column",
3924
- children: [
3925
- /* @__PURE__ */ jsx(DataTableToolbar, {
5318
+ style: { overflow: "hidden" },
5319
+ children: [/* @__PURE__ */ jsxs(Flex$1, {
5320
+ rounded: true,
5321
+ bordered: true,
5322
+ elevated: true,
5323
+ shadowed: "xs",
5324
+ col: true,
5325
+ children: [/* @__PURE__ */ jsx(DataTableToolbar, {
3926
5326
  columns: props.columns,
3927
5327
  filters: props.filters,
3928
5328
  columnVisibility,
@@ -3936,71 +5336,97 @@ const DataTable = (props) => {
3936
5336
  selectedItems: selection.selectedItems,
3937
5337
  checkboxActions: props.checkboxActions,
3938
5338
  onClearSelection: selection.clear
3939
- }),
3940
- filterSchema && props.filters && /* @__PURE__ */ jsx(DataTableFilters, {
5339
+ }), filterSchema && props.filters && /* @__PURE__ */ jsx(DataTableFilters, {
3941
5340
  schema: filterSchema,
3942
5341
  form,
3943
5342
  typeFormProps: props.typeFormProps,
3944
5343
  filterVisibility
3945
- }),
3946
- /* @__PURE__ */ jsx(Flex, {
3947
- className: "overflow-auto",
3948
- children: /* @__PURE__ */ jsxs(Table, {
3949
- "aria-label": "Data table",
3950
- withColumnBorders: true,
3951
- withRowBorders: true,
3952
- ...props.tableProps,
3953
- children: [/* @__PURE__ */ jsx(Table.Thead, {
3954
- style: {
3955
- position: "sticky",
3956
- top: 0,
3957
- zIndex: 1,
3958
- backgroundColor: "var(--mantine-color-body)"
3959
- },
3960
- children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
3961
- panelConfig && /* @__PURE__ */ jsx(Table.Th, { style: { width: 36 } }),
3962
- checkboxHeader,
3963
- head
3964
- ] })
3965
- }), /* @__PURE__ */ jsxs(Table.Tbody, {
3966
- style: {
3967
- opacity: form.submitting ? .5 : 1,
3968
- transition: "opacity 150ms ease"
3969
- },
3970
- children: [rows, items.content.length === 0 && /* @__PURE__ */ jsx(Table.Tr, { children: /* @__PURE__ */ jsx(Table.Td, {
5344
+ })]
5345
+ }), /* @__PURE__ */ jsxs(Flex$1, {
5346
+ col: true,
5347
+ rounded: true,
5348
+ bordered: true,
5349
+ elevated: true,
5350
+ shadowed: "xs",
5351
+ flex: 1,
5352
+ style: { minHeight: 0 },
5353
+ children: [
5354
+ /* @__PURE__ */ jsx(Flex$1, {
5355
+ className: "overflow-auto",
5356
+ flex: 1,
5357
+ style: { minHeight: 0 },
5358
+ col: true,
5359
+ children: /* @__PURE__ */ jsxs(Table, {
5360
+ "aria-label": "Data table",
5361
+ withRowBorders: true,
5362
+ highlightOnHover: true,
5363
+ ...props.tableProps,
5364
+ children: [/* @__PURE__ */ jsx(Table.Thead, {
5365
+ bdrs: "md",
5366
+ style: {
5367
+ position: "sticky",
5368
+ top: 0,
5369
+ zIndex: 1,
5370
+ backgroundColor: "var(--alepha-elevated)"
5371
+ },
5372
+ children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
5373
+ panelConfig && /* @__PURE__ */ jsx(Table.Th, { style: { width: 36 } }),
5374
+ checkboxHeader,
5375
+ head,
5376
+ props.rowActions && /* @__PURE__ */ jsx(Table.Th, { style: FIT_STYLE })
5377
+ ] })
5378
+ }), /* @__PURE__ */ jsx(Table.Tbody, { children: !loaded || form.submitting ? /* @__PURE__ */ jsx(Table.Tr, { children: /* @__PURE__ */ jsx(Table.Td, {
5379
+ colSpan: totalColumns || 1,
5380
+ py: "sm",
5381
+ children: /* @__PURE__ */ jsx(Flex$1, {
5382
+ justify: "center",
5383
+ p: "md",
5384
+ children: /* @__PURE__ */ jsx(Loader, {
5385
+ size: "sm",
5386
+ type: "dots"
5387
+ })
5388
+ })
5389
+ }) }) : rows.length === 0 ? /* @__PURE__ */ jsx(Table.Tr, { children: /* @__PURE__ */ jsx(Table.Td, {
3971
5390
  colSpan: totalColumns || 1,
3972
5391
  py: "xl",
3973
- style: { textAlign: "center" },
3974
- children: /* @__PURE__ */ jsx(Text, {
3975
- c: "dimmed",
3976
- size: "sm",
3977
- children: form.submitting ? "Loading…" : "No results"
5392
+ children: /* @__PURE__ */ jsx(Flex$1, {
5393
+ justify: "center",
5394
+ children: /* @__PURE__ */ jsx(Text$1, {
5395
+ c: "dimmed",
5396
+ size: "sm",
5397
+ children: props.emptyLabel ?? "No results"
5398
+ })
3978
5399
  })
3979
- }) })]
3980
- })]
5400
+ }) }) : rows })]
5401
+ })
5402
+ }),
5403
+ props.infinityScroll && /* @__PURE__ */ jsx("div", { ref: sentinelRef }),
5404
+ !props.infinityScroll && /* @__PURE__ */ jsx(DataTablePagination, {
5405
+ page,
5406
+ size,
5407
+ totalPages: items.page?.totalPages,
5408
+ totalElements: items.page?.totalElements,
5409
+ isFirst: items.page?.isFirst,
5410
+ isLast: items.page?.isLast,
5411
+ offset: items.page?.offset ?? 0,
5412
+ numberOfElements: items.content.length,
5413
+ onPageChange: (value) => {
5414
+ form.input.page.set(value - 1);
5415
+ },
5416
+ onSizeChange: (value) => {
5417
+ form.input.size.set(value);
5418
+ }
5419
+ }),
5420
+ drawerConfig && /* @__PURE__ */ jsx(Drawer, {
5421
+ opened: drawerItem !== null,
5422
+ onClose: () => setDrawerItem(null),
5423
+ position: "right",
5424
+ size: "xl",
5425
+ ...drawerConfig.props,
5426
+ children: drawerItem && drawerConfig.render(drawerItem)
3981
5427
  })
3982
- }),
3983
- props.infinityScroll && /* @__PURE__ */ jsx("div", { ref: sentinelRef }),
3984
- !props.infinityScroll && /* @__PURE__ */ jsx(DataTablePagination, {
3985
- page,
3986
- size,
3987
- totalPages: items.page?.totalPages ?? 1,
3988
- onPageChange: (value) => {
3989
- form.input.page.set(value - 1);
3990
- },
3991
- onSizeChange: (value) => {
3992
- form.input.size.set(value);
3993
- }
3994
- }),
3995
- drawerConfig && /* @__PURE__ */ jsx(Drawer, {
3996
- opened: drawerItem !== null,
3997
- onClose: () => setDrawerItem(null),
3998
- position: "right",
3999
- size: "xl",
4000
- ...drawerConfig.props,
4001
- children: drawerItem && drawerConfig.render(drawerItem)
4002
- })
4003
- ]
5428
+ ]
5429
+ })]
4004
5430
  });
4005
5431
  };
4006
5432
 
@@ -4099,8 +5525,8 @@ const OPERATOR_INFO = {
4099
5525
  * Get the default icon for an input based on its type, format, or name.
4100
5526
  */
4101
5527
  const getDefaultIcon = (params) => {
4102
- const { type, format, name, isEnum, isArray, size = "sm" } = params;
4103
- const iconSize = ui.sizes.icon[size];
5528
+ const { type, format, name, isEnum, isArray, size = "xs" } = params;
5529
+ const iconSize = ui.sizes.icon[size] - 4;
4104
5530
  if (format) switch (format) {
4105
5531
  case "email": return /* @__PURE__ */ jsx(IconMail, { size: iconSize });
4106
5532
  case "url":
@@ -4213,5 +5639,5 @@ const AlephaUI = $module({
4213
5639
  });
4214
5640
 
4215
5641
  //#endregion
4216
- export { AlephaMantineProvider as _, useDialog as a, Text$1 as c, Breadcrumb as d, Heading as f, ui as g, ActionButton as h, JsonViewer as i, DashboardShell as l, ToggleSidebarButton as m, capitalize as n, TypeForm as o, Flex$1 as p, DataTable as r, Control as s, AlephaUI as t, Sidebar as u, useToast as v };
4217
- //# sourceMappingURL=core-RCUw1Q-a.js.map
5642
+ 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, Breadcrumb as u, useToast as v };
5643
+ //# sourceMappingURL=core-DFgB3yU4.js.map