@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
@@ -3,6 +3,7 @@ import {
3
3
  type AutocompleteProps,
4
4
  Flex,
5
5
  Input,
6
+ Loader,
6
7
  MultiSelect,
7
8
  type MultiSelectProps,
8
9
  SegmentedControl,
@@ -12,39 +13,91 @@ import {
12
13
  TagsInput,
13
14
  type TagsInputProps,
14
15
  } from "@mantine/core";
15
- import { useFormState } from "alepha/react/form";
16
- import { useEffect, useState } from "react";
16
+ import type { Async } from "alepha";
17
+ import { useAction } from "alepha/react";
18
+ import { useFieldValue, useFormState } from "alepha/react/form";
19
+ import { useEffect, useRef, useState } from "react";
17
20
  import { type GenericControlProps, parseInput } from "../utils/parseInput.ts";
18
21
 
19
22
  export type SelectValueLabel =
20
23
  | string
21
24
  | { value: string; label: string; icon?: string };
22
25
 
26
+ type LoaderMode = "static" | "short" | "long";
27
+
23
28
  export interface ControlSelectProps extends GenericControlProps {
24
- select?: boolean | SelectProps;
25
- multi?: boolean | MultiSelectProps;
26
- tags?: boolean | TagsInputProps;
27
- autocomplete?: boolean | AutocompleteProps;
28
- segmented?: boolean | Partial<SegmentedControlProps>;
29
+ /**
30
+ * If true, allows creating new values not present in the options list.
31
+ * For single values, Select becomes an Autocomplete.
32
+ * For arrays, MultiSelect becomes a TagsInput.
33
+ */
34
+ creatable?: boolean;
35
+
36
+ /**
37
+ * Configure select with optional SelectProps.
38
+ */
39
+ selectProps?: boolean | SelectProps;
40
+
41
+ /**
42
+ * Configure select as multi-select (for array of enums) with optional MultiSelectProps.
43
+ */
44
+ multiSelectProps?: boolean | MultiSelectProps;
45
+
46
+ /**
47
+ * If true, renders a SegmentedControl instead of Select/MultiSelect.
48
+ */
49
+ segmentedProps?: boolean | Partial<SegmentedControlProps>;
50
+
51
+ /**
52
+ * Props passed to the Autocomplete component when creatable is true and the field is single-value.
53
+ */
54
+ autocompleteProps?: Partial<AutocompleteProps>;
55
+
56
+ /**
57
+ * Props passed to the TagsInput component when creatable is true and the field is array-value.
58
+ */
59
+ tagsInputProps?: Partial<TagsInputProps>;
60
+
61
+ /**
62
+ * Async loader for select options.
63
+ *
64
+ * @param search - Search text (empty string on initial load)
65
+ * @param resolve - Optional array of values to resolve labels for (used for default values in long mode)
66
+ */
67
+ loader?: (search: string, resolve?: string[]) => Async<SelectValueLabel[]>;
68
+
69
+ /**
70
+ * Threshold to distinguish short (client-filtered) from long (server-filtered) lists.
71
+ * If initial load returns <= threshold items, mode is "short" (cached, client-filtered).
72
+ * If > threshold, mode is "long" (debounced server search).
73
+ * @default 100
74
+ */
75
+ loaderThreshold?: number;
29
76
 
30
- loader?: () => Promise<SelectValueLabel[]>;
77
+ /**
78
+ * Debounce delay in ms for server search in long mode.
79
+ * @default 300
80
+ */
81
+ loaderDebounce?: number;
31
82
  }
32
83
 
33
84
  /**
34
- * ControlSelect component for handling Select, MultiSelect, and TagsInput.
85
+ * ControlSelect component for handling Select, MultiSelect, Autocomplete, and TagsInput.
35
86
  *
36
87
  * Features:
37
88
  * - Basic Select with enum support
38
89
  * - MultiSelect for array of enums
39
- * - TagsInput for array of strings (no enum)
40
- * - Future: Lazy loading
41
- * - Future: Searchable/filterable options
42
- * - Future: Custom option rendering
90
+ * - Autocomplete for creatable single values
91
+ * - TagsInput for creatable array values
92
+ * - Async lazy loading with auto short/long mode detection
93
+ * - Short mode: client-side filtering with cached data
94
+ * - Long mode: debounced server search
43
95
  *
44
96
  * Automatically detects enum values and array types from schema.
45
97
  */
46
98
  const ControlSelect = (props: ControlSelectProps) => {
47
99
  const form = useFormState(props.input);
100
+ const [value, setValue] = useFieldValue(props.input);
48
101
  const { inputProps, id, icon } = parseInput(props, form);
49
102
 
50
103
  // Detect if schema is an array type
@@ -53,14 +106,18 @@ const ControlSelect = (props: ControlSelectProps) => {
53
106
  "type" in props.input.schema &&
54
107
  props.input.schema.type === "array";
55
108
 
56
- // For arrays, check if items have enum (MultiSelect) or not (TagsInput)
57
- let itemsEnum: string[] | undefined;
58
- if (isArray && "items" in props.input.schema && props.input.schema.items) {
59
- const items: any = props.input.schema.items;
60
- if ("enum" in items && Array.isArray(items.enum)) {
61
- itemsEnum = items.enum;
62
- }
63
- }
109
+ // Detect if schema is numeric (for value coercion)
110
+ const isNumeric =
111
+ props.input.schema &&
112
+ "type" in props.input.schema &&
113
+ (props.input.schema.type === "integer" ||
114
+ props.input.schema.type === "number");
115
+
116
+ // Detect if schema is boolean (for value coercion)
117
+ const isBoolean =
118
+ props.input.schema &&
119
+ "type" in props.input.schema &&
120
+ props.input.schema.type === "boolean";
64
121
 
65
122
  // Extract enum values from schema (for non-array select)
66
123
  const enumValues =
@@ -70,132 +127,277 @@ const ControlSelect = (props: ControlSelectProps) => {
70
127
  ? props.input.schema.enum
71
128
  : [];
72
129
 
73
- const [data, setData] = useState<SelectValueLabel[]>([]);
130
+ // Async loader hook
131
+ const {
132
+ data: asyncData,
133
+ loading,
134
+ mode,
135
+ search,
136
+ } = useAsyncLoader(
137
+ props.loader,
138
+ props.loaderThreshold ?? 100,
139
+ props.loaderDebounce ?? 300,
140
+ props.input.initialValue,
141
+ );
74
142
 
75
- useEffect(() => {
76
- if (!props.input?.props) {
77
- return;
78
- }
143
+ // Static data from enum (no loader)
144
+ const [staticData, setStaticData] = useState<SelectValueLabel[]>([]);
79
145
 
80
- if (props.loader) {
81
- props.loader().then(setData);
146
+ const enumKey = JSON.stringify(enumValues);
147
+ useEffect(() => {
148
+ if (!props.input?.props || props.loader) return;
149
+ if (isBoolean && enumValues.length === 0) {
150
+ setStaticData([
151
+ { value: "true", label: "True" },
152
+ { value: "false", label: "False" },
153
+ ]);
82
154
  } else {
83
- setData(enumValues);
155
+ setStaticData(enumValues);
84
156
  }
85
- }, [props.input, props.loader]);
157
+ }, [props.input, props.loader, enumKey, isBoolean]);
158
+
159
+ const data = props.loader ? asyncData : staticData;
86
160
 
87
161
  if (!props.input?.props) {
88
162
  return null;
89
163
  }
90
164
 
91
- if (props.segmented) {
165
+ /**
166
+ * Coerce value for numeric schemas — Select values are always strings.
167
+ */
168
+ const coerceValue = (val: string | null) => {
169
+ if (val == null) return val;
170
+ if (isNumeric) return Number(val);
171
+ if (isBoolean) return val === "true";
172
+ return val;
173
+ };
174
+
175
+ // region <SegmentedControl/> — early return
176
+ if (props.segmentedProps) {
92
177
  const segmentedControlProps: Partial<SegmentedControlProps> =
93
- typeof props.segmented === "object" ? props.segmented : {};
178
+ typeof props.segmentedProps === "object" ? props.segmentedProps : {};
179
+ const segmentedData = segmentedControlProps.data ?? data.slice(0, 10);
94
180
 
95
181
  return (
96
182
  <Input.Wrapper {...inputProps}>
97
- <Flex>
183
+ <Flex my={"calc(var(--mantine-spacing-xs) / 2)"}>
98
184
  <SegmentedControl
99
185
  disabled={inputProps.disabled}
100
- defaultValue={String(props.input.props.defaultValue)}
186
+ value={value != null ? String(value) : ""}
101
187
  {...segmentedControlProps}
102
- onChange={(value) => {
103
- props.input.set(value);
188
+ onChange={(val) => {
189
+ setValue(coerceValue(val));
104
190
  }}
105
- data={data.slice(0, 10)}
191
+ data={segmentedData}
106
192
  />
107
193
  </Flex>
108
194
  </Input.Wrapper>
109
195
  );
110
196
  }
197
+ // endregion
198
+
199
+ // Shared props used by all select-like components
200
+ const sharedProps = {
201
+ size: props.size,
202
+ id,
203
+ leftSection: loading ? <Loader color={"gray"} size={10} /> : icon,
204
+ data,
205
+ };
111
206
 
112
- if (props.autocomplete) {
113
- const autocompleteProps =
114
- typeof props.autocomplete === "object" ? props.autocomplete : {};
207
+ // Select and MultiSelect: searchable + hide default chevron
208
+ const selectableProps = {
209
+ ...sharedProps,
210
+ searchable: true,
211
+ rightSection: <span />,
212
+ };
213
+
214
+ // Long mode additions: bypass client filter + wire server search
215
+ const longModeProps =
216
+ mode === "long"
217
+ ? {
218
+ filter: ({ options }: { options: any[] }) => options,
219
+ onSearchChange: search.run,
220
+ }
221
+ : {};
222
+
223
+ // region <TagsInput/> — creatable + array
224
+ if (props.creatable && (isArray || props.tagsInputProps)) {
225
+ const tagsInputExtraProps = props.tagsInputProps ?? {};
115
226
 
116
227
  return (
117
- <Autocomplete
228
+ <TagsInput
118
229
  {...inputProps}
119
- size={props.size}
120
- id={id}
121
- leftSection={icon}
122
- data={data}
123
- {...props.input.props}
124
- {...autocompleteProps}
230
+ {...sharedProps}
231
+ {...longModeProps}
232
+ value={Array.isArray(value) ? value : []}
233
+ onChange={(val) => {
234
+ setValue(val);
235
+ }}
236
+ {...tagsInputExtraProps}
125
237
  />
126
238
  );
127
239
  }
240
+ // endregion
241
+
242
+ // region <Autocomplete/> — creatable + single
243
+ if (props.creatable) {
244
+ const autocompleteExtraProps = props.autocompleteProps ?? {};
128
245
 
129
- // region <TagsInput/> - for array of strings without enum
130
- if ((isArray && !itemsEnum) || props.tags) {
131
- const tagsInputProps = typeof props.tags === "object" ? props.tags : {};
132
246
  return (
133
- <TagsInput
247
+ <Autocomplete
134
248
  {...inputProps}
135
- size={props.size}
136
- id={id}
137
- leftSection={icon}
138
- defaultValue={
139
- Array.isArray(props.input.props.defaultValue)
140
- ? props.input.props.defaultValue
141
- : []
142
- }
143
- onChange={(value) => {
144
- props.input.set(value);
249
+ {...sharedProps}
250
+ {...longModeProps}
251
+ value={value != null ? String(value) : ""}
252
+ onChange={(val) => {
253
+ setValue(coerceValue(val));
145
254
  }}
146
- {...tagsInputProps}
255
+ {...autocompleteExtraProps}
147
256
  />
148
257
  );
149
258
  }
150
259
  // endregion
151
260
 
152
- // region <MultiSelect/> - for array of enums
153
- if ((isArray && itemsEnum) || props.multi) {
154
- const data =
155
- itemsEnum?.map((value: string) => ({
156
- value,
157
- label: value,
158
- })) || [];
159
-
160
- const multiSelectProps = typeof props.multi === "object" ? props.multi : {};
261
+ // region <MultiSelect/> array (non-creatable)
262
+ if (isArray || props.multiSelectProps) {
263
+ const multiSelectExtraProps =
264
+ typeof props.multiSelectProps === "object" ? props.multiSelectProps : {};
161
265
 
162
266
  return (
163
267
  <MultiSelect
164
268
  {...inputProps}
165
- size={props.size}
166
- id={id}
167
- leftSection={icon}
168
- data={data}
169
- defaultValue={
170
- Array.isArray(props.input.props.defaultValue)
171
- ? props.input.props.defaultValue
172
- : []
173
- }
174
- onChange={(value) => {
175
- props.input.set(value);
269
+ {...selectableProps}
270
+ {...longModeProps}
271
+ value={Array.isArray(value) ? value : []}
272
+ onChange={(val) => {
273
+ setValue(val);
176
274
  }}
177
- {...multiSelectProps}
275
+ {...multiSelectExtraProps}
178
276
  />
179
277
  );
180
278
  }
181
279
  // endregion
182
280
 
183
- // region <Select/> - for single enum value
184
- const selectProps = typeof props.select === "object" ? props.select : {};
281
+ // region <Select/> single value (static, short, or long mode)
282
+ const selectExtraProps =
283
+ typeof props.selectProps === "object" ? props.selectProps : {};
284
+
285
+ // Static mode
286
+ if (mode === "static") {
287
+ return (
288
+ <Select
289
+ {...inputProps}
290
+ {...selectableProps}
291
+ value={value != null ? String(value) : null}
292
+ onChange={(val) => {
293
+ setValue(coerceValue(val));
294
+ }}
295
+ {...selectExtraProps}
296
+ />
297
+ );
298
+ }
185
299
 
300
+ // Short or long mode
186
301
  return (
187
302
  <Select
188
303
  {...inputProps}
189
- size={props.size}
190
- id={id}
191
- leftSection={icon}
192
- rightSection={null}
193
- data={data}
194
- {...props.input.props}
195
- {...selectProps}
304
+ {...selectableProps}
305
+ {...longModeProps}
306
+ value={value != null ? String(value) : null}
307
+ onChange={(val) => {
308
+ setValue(coerceValue(val));
309
+ }}
310
+ {...selectExtraProps}
196
311
  />
197
312
  );
198
313
  // endregion
199
314
  };
200
315
 
201
316
  export default ControlSelect;
317
+
318
+ // ---------------------------------------------------------------------------------------------------------------------
319
+
320
+ /**
321
+ * Hook for async select data loading with auto short/long mode detection.
322
+ */
323
+ const useAsyncLoader = (
324
+ loader: ControlSelectProps["loader"],
325
+ threshold: number,
326
+ debounceMs: number,
327
+ defaultValue: any,
328
+ ) => {
329
+ const [data, setData] = useState<SelectValueLabel[]>([]);
330
+ const [loading, setLoading] = useState(false);
331
+ const [mode, setMode] = useState<LoaderMode>("static");
332
+ const cache = useRef(new Map<string, SelectValueLabel[]>());
333
+
334
+ useAction(
335
+ {
336
+ name: "select:loader:init",
337
+ runOnInit: true,
338
+ handler: async () => {
339
+ if (!loader) {
340
+ setMode("static");
341
+ return;
342
+ }
343
+
344
+ setLoading(true);
345
+ try {
346
+ const result = await loader("");
347
+ const isShort = result.length <= threshold;
348
+ setMode(isShort ? "short" : "long");
349
+ cache.current.set("", result);
350
+ setData(result);
351
+
352
+ // In long mode, resolve default value label before clearing loading
353
+ if (!isShort && defaultValue != null && String(defaultValue) !== "") {
354
+ const resolved = await loader("", [String(defaultValue)]);
355
+ if (resolved.length > 0) {
356
+ setData((prev) => {
357
+ const existing = new Set(
358
+ prev.map((d) => (typeof d === "string" ? d : d.value)),
359
+ );
360
+ const newItems = resolved.filter((r) => {
361
+ const val = typeof r === "string" ? r : r.value;
362
+ return !existing.has(val);
363
+ });
364
+ return [...prev, ...newItems];
365
+ });
366
+ }
367
+ }
368
+ } finally {
369
+ setLoading(false);
370
+ }
371
+ },
372
+ },
373
+ [loader, threshold],
374
+ );
375
+
376
+ // Debounced search (long mode only)
377
+ const search = useAction<[string]>(
378
+ {
379
+ debounce: debounceMs,
380
+ handler: async (text) => {
381
+ if (!loader || mode !== "long") return;
382
+
383
+ // Check cache first (immediate, no network)
384
+ if (cache.current.has(text)) {
385
+ setData(cache.current.get(text)!);
386
+ return;
387
+ }
388
+
389
+ setLoading(true);
390
+ try {
391
+ const result = await loader(text);
392
+ cache.current.set(text, result);
393
+ setData(result);
394
+ } finally {
395
+ setLoading(false);
396
+ }
397
+ },
398
+ },
399
+ [loader, mode, debounceMs],
400
+ );
401
+
402
+ return { data, loading, mode, search };
403
+ };
@@ -500,7 +500,7 @@ describe("TypeForm", () => {
500
500
  return (
501
501
  <TypeForm
502
502
  form={form}
503
- controlProps={{ title: "Custom Title" }}
503
+ controlProps={{ label: "Custom Title" }}
504
504
  skipSubmitButton
505
505
  />
506
506
  );
@@ -530,8 +530,8 @@ describe("TypeForm", () => {
530
530
  <TypeForm
531
531
  form={form}
532
532
  fieldControlProps={{
533
- field1: { title: "Field One" },
534
- field2: { title: "Field Two" },
533
+ field1: { label: "Field One" },
534
+ field2: { label: "Field Two" },
535
535
  }}
536
536
  skipSubmitButton
537
537
  />
@@ -1,7 +1,7 @@
1
1
  import { ActionButton, type ActionSubmitButtonProps } from "@alepha/ui";
2
2
  import { Card, Flex, type FlexProps, Grid } from "@mantine/core";
3
3
  import type { TObject } from "alepha";
4
- import type { FormModel } from "alepha/react/form";
4
+ import { type FormModel, useFormState } from "alepha/react/form";
5
5
  import type { ReactNode } from "react";
6
6
  import Control, { type ControlProps } from "./Control.tsx";
7
7
 
@@ -96,6 +96,8 @@ const TypeForm = <T extends TObject>(props: TypeFormProps<T>) => {
96
96
  size,
97
97
  } = props;
98
98
 
99
+ const { dirty } = useFormState(form, ["dirty"]);
100
+
99
101
  const schema = props.schema || form.options.schema;
100
102
  if (!schema?.properties) {
101
103
  return null;
@@ -194,12 +196,13 @@ const TypeForm = <T extends TObject>(props: TypeFormProps<T>) => {
194
196
  <Flex></Flex>
195
197
  <Flex flex={1}></Flex>
196
198
  <Flex gap={"sm"}>
197
- <ActionButton variant={"subtle"} type={"reset"}>
199
+ <ActionButton variant={"subtle"} type={"reset"} disabled={!dirty}>
198
200
  Reset
199
201
  </ActionButton>
200
202
  <ActionButton
201
203
  intent={"primary"}
202
204
  form={form}
205
+ disabled={!dirty}
203
206
  {...submitButtonProps}
204
207
  >
205
208
  {submitButtonProps?.children ?? "Submit"}
@@ -2,13 +2,20 @@ import type { ControlProps } from "./components/Control.tsx";
2
2
 
3
3
  // ---------------------------------------------------------------------------------------------------------------------
4
4
 
5
- export type { ControlProps } from "./components/Control.tsx";
5
+ export type {
6
+ ControlProps,
7
+ CustomControlProps,
8
+ } from "./components/Control.tsx";
6
9
  export { default as Control } from "./components/Control.tsx";
7
10
  export { default as ControlArray } from "./components/ControlArray.tsx";
8
11
  export { default as ControlDate } from "./components/ControlDate.tsx";
9
12
  export { default as ControlNumber } from "./components/ControlNumber.tsx";
10
13
  export { default as ControlObject } from "./components/ControlObject.tsx";
11
14
  export { default as ControlQueryBuilder } from "./components/ControlQueryBuilder.tsx";
15
+ export type {
16
+ ControlSelectProps,
17
+ SelectValueLabel,
18
+ } from "./components/ControlSelect.tsx";
12
19
  export { default as ControlSelect } from "./components/ControlSelect.tsx";
13
20
  export type { TypeFormProps } from "./components/TypeForm.tsx";
14
21
  export { default as TypeForm } from "./components/TypeForm.tsx";
@@ -18,7 +18,7 @@ export const parseInput = (
18
18
  const disabled = false; // form.loading;
19
19
  const id = props.input.props.id;
20
20
  const label =
21
- props.title ??
21
+ props.label ??
22
22
  ("title" in props.input.schema &&
23
23
  typeof props.input.schema.title === "string"
24
24
  ? props.input.schema.title
@@ -57,10 +57,11 @@ export const parseInput = (
57
57
  props.input.schema &&
58
58
  "type" in props.input.schema &&
59
59
  props.input.schema.type === "array",
60
+ size: props.size,
60
61
  })
61
62
  : isValidElement(props.icon)
62
63
  ? props.icon
63
- : createElement(props.icon, { size: ui.sizes.icon.md });
64
+ : createElement(props.icon, { size: ui.sizes.icon.sm });
64
65
 
65
66
  const format =
66
67
  props.input.schema &&
@@ -72,12 +73,15 @@ export const parseInput = (
72
73
  const required = props.input.required;
73
74
  const schema = props.input.schema as TObject & { $control?: ControlProps };
74
75
 
76
+ const testId = (props.input.props as any)?.["data-testid"];
77
+
75
78
  const inputProps: InputProps = {
76
79
  label,
77
80
  description,
78
81
  error,
79
82
  required,
80
83
  disabled,
84
+ ...(testId ? { "data-testid": testId } : {}),
81
85
  };
82
86
 
83
87
  if ("minLength" in schema && typeof schema.minLength === "number") {
@@ -104,7 +108,7 @@ export const parseInput = (
104
108
 
105
109
  export interface GenericControlProps {
106
110
  input: BaseInputField;
107
- title?: string;
111
+ label?: string;
108
112
  description?: string;
109
113
  icon?: ReactElement | ((props: { size: number }) => ReactNode);
110
114
  size?: "xs" | "sm" | "md" | "lg" | "xl";
@@ -3,23 +3,36 @@ import {
3
3
  alephaThemeAtom,
4
4
  type CurrentAlephaTheme,
5
5
  } from "../atoms/alephaThemeAtom.ts";
6
+ import {
7
+ type AlephaThemeOverrides,
8
+ alephaThemeOverridesAtom,
9
+ } from "../atoms/alephaThemeOverridesAtom.ts";
6
10
  import type { AlephaTheme } from "../interfaces/AlephaTheme.ts";
7
11
  import { ThemeProvider } from "../providers/ThemeProvider.ts";
8
12
 
13
+ export interface ThemeExpert {
14
+ overrides: AlephaThemeOverrides;
15
+ setOverrides: (overrides: AlephaThemeOverrides) => void;
16
+ resetOverrides: () => void;
17
+ }
18
+
9
19
  /**
10
20
  * Hook to get and set the current theme.
11
21
  *
12
- * Returns a tuple with the current theme and a function to set the theme.
22
+ * Returns a tuple with the current theme, a function to set the theme,
23
+ * and expert mode controls for fine-grained customization.
13
24
  *
14
25
  * ```tsx
15
- * const [theme, setTheme] = useTheme();
26
+ * const [theme, setTheme, expert] = useTheme();
16
27
  * ```
17
28
  */
18
29
  export const useTheme = (): [
19
30
  AlephaTheme,
20
31
  (theme: CurrentAlephaTheme) => void,
32
+ ThemeExpert,
21
33
  ] => {
22
34
  useStore(alephaThemeAtom);
35
+ useStore(alephaThemeOverridesAtom);
23
36
 
24
37
  const themeProvider = useInject(ThemeProvider);
25
38
  const theme = themeProvider.getTheme();
@@ -27,5 +40,15 @@ export const useTheme = (): [
27
40
  themeProvider.setTheme(theme.index);
28
41
  };
29
42
 
30
- return [theme, setTheme] as const;
43
+ const expert: ThemeExpert = {
44
+ overrides: themeProvider.getThemeOverrides(),
45
+ setOverrides: (overrides: AlephaThemeOverrides) => {
46
+ themeProvider.setThemeOverrides(overrides);
47
+ },
48
+ resetOverrides: () => {
49
+ themeProvider.resetThemeOverrides();
50
+ },
51
+ };
52
+
53
+ return [theme, setTheme, expert] as const;
31
54
  };