@alepha/ui 0.18.2 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/{AdminApiKeys-BJhIwfD6.js → AdminApiKeys-Bt1PjO6o.js} +3 -4
- package/dist/admin/{AdminApiKeys-BJhIwfD6.js.map → AdminApiKeys-Bt1PjO6o.js.map} +1 -1
- package/dist/admin/{AdminAudits-DzD_4cDt.js → AdminAudits-C7c1CN4c.js} +3 -4
- package/dist/admin/{AdminAudits-DzD_4cDt.js.map → AdminAudits-C7c1CN4c.js.map} +1 -1
- package/dist/admin/{AdminDashboard-C92tIc6x.js → AdminDashboard-C3RXpTp6.js} +3 -4
- package/dist/admin/{AdminDashboard-C92tIc6x.js.map → AdminDashboard-C3RXpTp6.js.map} +1 -1
- package/dist/admin/{AdminFiles-DLpfhBkf.js → AdminFiles-31ivR6Wq.js} +3 -4
- package/dist/admin/{AdminFiles-DLpfhBkf.js.map → AdminFiles-31ivR6Wq.js.map} +1 -1
- package/dist/admin/{AdminJobDashboard-KIOkeMgE.js → AdminJobDashboard-BABLe7hL.js} +73 -25
- package/dist/admin/AdminJobDashboard-BABLe7hL.js.map +1 -0
- package/dist/admin/{AdminJobExecutions-D0Yo_PU0.js → AdminJobExecutions-D-G8RIlr.js} +3 -4
- package/dist/admin/{AdminJobExecutions-D0Yo_PU0.js.map → AdminJobExecutions-D-G8RIlr.js.map} +1 -1
- package/dist/admin/{AdminJobRegistry-PFajqaGK.js → AdminJobRegistry-oIS3K9NX.js} +3 -4
- package/dist/admin/{AdminJobRegistry-PFajqaGK.js.map → AdminJobRegistry-oIS3K9NX.js.map} +1 -1
- package/dist/admin/{AdminLayout-B1DXZHDn.js → AdminLayout-BmZ9mtXh.js} +8 -25
- package/dist/admin/AdminLayout-BmZ9mtXh.js.map +1 -0
- package/dist/admin/AdminNotifications-DHdzksww.js +541 -0
- package/dist/admin/AdminNotifications-DHdzksww.js.map +1 -0
- package/dist/admin/{AdminParameters-BspPeqp_.js → AdminParameters-CyZQSXnN.js} +118 -112
- package/dist/admin/AdminParameters-CyZQSXnN.js.map +1 -0
- package/dist/admin/{AdminSessions-BnH5CZQl.js → AdminSessions--xwELDSO.js} +3 -4
- package/dist/admin/{AdminSessions-BnH5CZQl.js.map → AdminSessions--xwELDSO.js.map} +1 -1
- package/dist/admin/{AdminUserLayout-DUbC6-BI.js → AdminUserLayout-DvBTG5gd.js} +82 -115
- package/dist/admin/AdminUserLayout-DvBTG5gd.js.map +1 -0
- package/dist/admin/{AdminUserProfile-DuTUnjdG.js → AdminUserProfile-CzsPBl6Z.js} +7 -6
- package/dist/admin/AdminUserProfile-CzsPBl6Z.js.map +1 -0
- package/dist/admin/{AdminUserSessions-DvZdAGpL.js → AdminUserSessions-C-aUnhVN.js} +3 -4
- package/dist/admin/{AdminUserSessions-DvZdAGpL.js.map → AdminUserSessions-C-aUnhVN.js.map} +1 -1
- package/dist/admin/{AdminUsers-CR9z0g_5.js → AdminUsers-BYwei5sj.js} +4 -4
- package/dist/admin/AdminUsers-BYwei5sj.js.map +1 -0
- package/dist/admin/{AuthLayout-DsUfp9RG.js → AuthLayout-CkPGLJku.js} +3 -4
- package/dist/admin/{AuthLayout-DsUfp9RG.js.map → AuthLayout-CkPGLJku.js.map} +1 -1
- package/dist/{demo/IconGoogle-CSQLPYwX.js → admin/IconGoogle-8Nkx6yax.js} +2 -4
- package/dist/admin/{IconGoogle-Ch1m3Uzl.js.map → IconGoogle-8Nkx6yax.js.map} +1 -1
- package/dist/admin/Login-DSBqNsZc.js +274 -0
- package/dist/admin/Login-DSBqNsZc.js.map +1 -0
- package/dist/admin/{Profile-B2EcIDB9.js → Profile-CDRjJo0P.js} +31 -29
- package/dist/admin/Profile-CDRjJo0P.js.map +1 -0
- package/dist/admin/{Register-Z3fxRbUF.js → Register-4QGFOnfh.js} +201 -146
- package/dist/admin/Register-4QGFOnfh.js.map +1 -0
- package/dist/admin/{ResetPassword-_Y1qTTKh.js → ResetPassword-Gxc9L_mY.js} +9 -10
- package/dist/admin/ResetPassword-Gxc9L_mY.js.map +1 -0
- package/dist/admin/{VerifyEmail-Bg22bwcC.js → VerifyEmail-D7G5NnaN.js} +25 -11
- package/dist/admin/VerifyEmail-D7G5NnaN.js.map +1 -0
- package/dist/admin/adminUserAtom-DCi4wf-v.js +11 -0
- package/dist/admin/adminUserAtom-DCi4wf-v.js.map +1 -0
- package/dist/admin/{core-BVO_TQxb.js → core-D1AbU50V.js} +662 -570
- package/dist/admin/core-D1AbU50V.js.map +1 -0
- package/dist/admin/index.d.ts +141 -53
- package/dist/admin/index.d.ts.map +1 -1
- package/dist/admin/index.js +67 -49
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/rolldown-runtime-CiIaOW0V.js +13 -0
- package/dist/{demo/AuthLayout-DN-ClJQk.js → auth/AuthLayout-CfRKcTqP.js} +3 -4
- package/dist/auth/{AuthLayout-C161NeF6.js.map → AuthLayout-CfRKcTqP.js.map} +1 -1
- package/dist/{admin/IconGoogle-Ch1m3Uzl.js → auth/IconGoogle-8Nkx6yax.js} +2 -4
- package/dist/auth/{IconGoogle-Ch1m3Uzl.js.map → IconGoogle-8Nkx6yax.js.map} +1 -1
- package/dist/auth/Login-DJyweoPS.js +274 -0
- package/dist/auth/Login-DJyweoPS.js.map +1 -0
- package/dist/auth/{Profile-BMpXJ0oi.js → Profile-Cy93pNTw.js} +31 -29
- package/dist/auth/Profile-Cy93pNTw.js.map +1 -0
- package/dist/auth/{Register-2gx8qll-.js → Register-CSqzzitW.js} +201 -146
- package/dist/auth/Register-CSqzzitW.js.map +1 -0
- package/dist/{demo/ResetPassword-CAPj8MO3.js → auth/ResetPassword-B61QPlQi.js} +9 -10
- package/dist/auth/ResetPassword-B61QPlQi.js.map +1 -0
- package/dist/{demo/VerifyEmail-DFmdCdYs.js → auth/VerifyEmail-CqBJ11id.js} +25 -11
- package/dist/auth/VerifyEmail-CqBJ11id.js.map +1 -0
- package/dist/auth/{core-DyfeVr5c.js → core-C6D3pazL.js} +403 -343
- package/dist/auth/core-C6D3pazL.js.map +1 -0
- package/dist/auth/index.d.ts +93 -54
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +30 -31
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/rolldown-runtime-CiIaOW0V.js +13 -0
- package/dist/core/index.d.ts +123 -62
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +878 -776
- package/dist/core/index.js.map +1 -1
- package/dist/{auth/AuthLayout-C161NeF6.js → demo/AuthLayout-Dq5tSLSc.js} +3 -4
- package/dist/demo/{AuthLayout-DN-ClJQk.js.map → AuthLayout-Dq5tSLSc.js.map} +1 -1
- package/dist/demo/DemoButton-_Ws2w-J0.js +181 -0
- package/dist/demo/DemoButton-_Ws2w-J0.js.map +1 -0
- package/dist/demo/DemoControlSelect-ChP4ZOpQ.js +304 -0
- package/dist/demo/DemoControlSelect-ChP4ZOpQ.js.map +1 -0
- package/dist/demo/DemoDataTable-Hwf_UUni.js +361 -0
- package/dist/demo/DemoDataTable-Hwf_UUni.js.map +1 -0
- package/dist/demo/{DemoDialog-DW8QEvD1.js → DemoDialog-B01OMVRd.js} +3 -4
- package/dist/demo/{DemoDialog-DW8QEvD1.js.map → DemoDialog-B01OMVRd.js.map} +1 -1
- package/dist/demo/{DemoFlex-CAhLUanT.js → DemoFlex-870PEl0V.js} +4 -5
- package/dist/demo/{DemoFlex-CAhLUanT.js.map → DemoFlex-870PEl0V.js.map} +1 -1
- package/dist/demo/{DemoHeading-yIFmNjHB.js → DemoHeading-C1YR27fz.js} +4 -5
- package/dist/demo/{DemoHeading-yIFmNjHB.js.map → DemoHeading-C1YR27fz.js.map} +1 -1
- package/dist/demo/{DemoHome-BSGuBHus.js → DemoHome-DRbL2eGf.js} +4 -5
- package/dist/demo/{DemoHome-BSGuBHus.js.map → DemoHome-DRbL2eGf.js.map} +1 -1
- package/dist/demo/{DemoJsonViewer-DsA2IpgV.js → DemoJsonViewer-DoABiqBW.js} +4 -5
- package/dist/demo/{DemoJsonViewer-DsA2IpgV.js.map → DemoJsonViewer-DoABiqBW.js.map} +1 -1
- package/dist/demo/{DemoLayout-Cy6xjn6P.js → DemoLayout-CN_PDCX2.js} +16 -8
- package/dist/demo/DemoLayout-CN_PDCX2.js.map +1 -0
- package/dist/demo/{DemoLogin-vqxgTu4P.js → DemoLogin-B5x-ug3Q.js} +51 -35
- package/dist/demo/DemoLogin-B5x-ug3Q.js.map +1 -0
- package/dist/demo/{DemoRegister-YHPvPg77.js → DemoRegister-Q6sg2xuV.js} +51 -53
- package/dist/demo/DemoRegister-Q6sg2xuV.js.map +1 -0
- package/dist/demo/{DemoResetPassword-mOW18Zlm.js → DemoResetPassword-DrqZfmEw.js} +14 -19
- package/dist/demo/DemoResetPassword-DrqZfmEw.js.map +1 -0
- package/dist/demo/{DemoSidebar-od7aLjP_.js → DemoSidebar-CfKS6w1o.js} +4 -5
- package/dist/demo/{DemoSidebar-od7aLjP_.js.map → DemoSidebar-CfKS6w1o.js.map} +1 -1
- package/dist/demo/{DemoText-DU3JeRS0.js → DemoText-pT6Gi5b5.js} +4 -5
- package/dist/demo/{DemoText-DU3JeRS0.js.map → DemoText-pT6Gi5b5.js.map} +1 -1
- package/dist/demo/{DemoToast-CUJEiPRa.js → DemoToast-I13NBzQQ.js} +3 -4
- package/dist/demo/{DemoToast-CUJEiPRa.js.map → DemoToast-I13NBzQQ.js.map} +1 -1
- package/dist/demo/{DemoTypeForm-C1dNkahD.js → DemoTypeForm-BqzcrtvN.js} +9 -6
- package/dist/demo/DemoTypeForm-BqzcrtvN.js.map +1 -0
- package/dist/demo/DemoVerifyEmail-HwD8xfQw.js +33 -0
- package/dist/demo/DemoVerifyEmail-HwD8xfQw.js.map +1 -0
- package/dist/{auth/IconGoogle-Ch1m3Uzl.js → demo/IconGoogle-CwQy4G9y.js} +2 -4
- package/dist/demo/{IconGoogle-CSQLPYwX.js.map → IconGoogle-CwQy4G9y.js.map} +1 -1
- package/dist/demo/Login-CqG1iJbn.js +274 -0
- package/dist/demo/Login-CqG1iJbn.js.map +1 -0
- package/dist/demo/{Profile-BE_Y3co2.js → Profile-C0ojJCaG.js} +31 -29
- package/dist/demo/Profile-C0ojJCaG.js.map +1 -0
- package/dist/demo/{Register-fXHmBpr3.js → Register-KKZwr_lL.js} +201 -146
- package/dist/demo/Register-KKZwr_lL.js.map +1 -0
- package/dist/{auth/ResetPassword-DBxt9hKk.js → demo/ResetPassword-DMrLFEtr.js} +9 -10
- package/dist/demo/ResetPassword-DMrLFEtr.js.map +1 -0
- package/dist/demo/{Showcase-BtEU0pY9.js → Showcase-D49Wud2v.js} +65 -68
- package/dist/demo/Showcase-D49Wud2v.js.map +1 -0
- package/dist/{auth/VerifyEmail-Z80Ubajk.js → demo/VerifyEmail-BFCAFz6T.js} +25 -11
- package/dist/demo/VerifyEmail-BFCAFz6T.js.map +1 -0
- package/dist/demo/{auth-Djd7SKiw.js → auth-D9qTZzCa.js} +18 -35
- package/dist/demo/{auth-Djd7SKiw.js.map → auth-D9qTZzCa.js.map} +1 -1
- package/dist/demo/{core-B7LNjM78.js → core-DRtQklr3.js} +752 -647
- package/dist/demo/core-DRtQklr3.js.map +1 -0
- package/dist/demo/index.d.ts +1 -0
- package/dist/demo/index.d.ts.map +1 -1
- package/dist/demo/index.js +25 -22
- package/dist/demo/index.js.map +1 -1
- package/dist/demo/rolldown-runtime-CiIaOW0V.js +13 -0
- package/package.json +19 -19
- package/src/admin/AdminRouter.tsx +42 -2
- package/src/admin/atoms/adminUserAtom.ts +7 -0
- package/src/admin/components/AdminLayout.tsx +2 -14
- package/src/admin/components/jobs/AdminJobDashboard.tsx +51 -20
- package/src/admin/components/notifications/AdminNotifications.tsx +519 -0
- package/src/admin/components/parameters/ParameterDetails.tsx +12 -270
- package/src/admin/components/parameters/ParameterDetailsConfigForm.tsx +238 -0
- package/src/admin/components/parameters/ParameterDetailsLoading.tsx +24 -0
- package/src/admin/components/parameters/ParameterHistory.tsx +10 -11
- package/src/admin/components/parameters/ParameterTree.tsx +28 -184
- package/src/admin/components/parameters/ParameterTreeNode.tsx +151 -0
- package/src/admin/components/shared/AdminResourceHeader.tsx +2 -25
- package/src/admin/components/shared/AdminResourceHeaderMenuItem.tsx +37 -0
- package/src/admin/components/shared/AdminResourceTabs.tsx +2 -26
- package/src/admin/components/shared/AdminResourceTabsItem.tsx +36 -0
- package/src/admin/components/users/AdminUserLayout.tsx +84 -127
- package/src/admin/components/users/AdminUserProfile.tsx +5 -2
- package/src/admin/components/users/AdminUsers.tsx +1 -1
- package/src/auth/components/Login.tsx +188 -121
- package/src/auth/components/Profile.tsx +1 -22
- package/src/auth/components/ProfileField.tsx +39 -0
- package/src/auth/components/Register.tsx +215 -158
- package/src/auth/components/ResetPassword.tsx +7 -11
- package/src/auth/components/VerifyEmail.tsx +35 -10
- package/src/auth/components/buttons/UserButton.tsx +19 -21
- package/src/auth/index.ts +1 -0
- package/src/core/components/Flex.tsx +34 -0
- package/src/core/components/buttons/ActionButton.tsx +105 -78
- package/src/core/components/data/DetailDrawer.tsx +102 -96
- package/src/core/components/data/DetailList.tsx +2 -1
- package/src/core/components/dialogs/PromptDialog.tsx +1 -1
- package/src/core/components/layout/Breadcrumb.tsx +4 -7
- package/src/core/components/layout/DashboardShell.tsx +18 -4
- package/src/core/components/layout/Sidebar.tsx +16 -241
- package/src/core/components/layout/SidebarCollapsedItem.tsx +91 -0
- package/src/core/components/layout/SidebarItem.tsx +146 -0
- package/src/core/components/layout/index.ts +3 -1
- package/src/core/form/components/Control.tsx +31 -29
- package/src/core/form/components/ControlArray.tsx +13 -39
- package/src/core/form/components/ControlDate.tsx +10 -21
- package/src/core/form/components/ControlNumber.tsx +4 -33
- package/src/core/form/components/ControlQueryBuilder.tsx +12 -175
- package/src/core/form/components/ControlQueryBuilderHelp.tsx +165 -0
- package/src/core/form/components/ControlSelect.browser.spec.tsx +343 -0
- package/src/core/form/components/ControlSelect.tsx +294 -92
- package/src/core/form/components/TypeForm.browser.spec.tsx +3 -3
- package/src/core/form/components/TypeForm.tsx +5 -2
- package/src/core/form/index.ts +8 -1
- package/src/core/form/utils/parseInput.ts +7 -3
- package/src/core/index.ts +3 -1
- package/src/core/json/components/JsonViewer.tsx +103 -319
- package/src/core/json/components/JsonViewerCopyButton.tsx +46 -0
- package/src/core/json/components/JsonViewerRowNode.tsx +120 -0
- package/src/core/json/components/JsonViewerShared.ts +76 -0
- package/src/core/services/DialogService.tsx +2 -2
- package/src/core/styles.css +13 -2
- package/src/core/table/components/ColumnPicker.tsx +3 -3
- package/src/core/table/components/DataTable.tsx +88 -29
- package/src/core/table/components/DataTableFilters.tsx +6 -11
- package/src/core/table/components/DataTablePagination.tsx +9 -3
- package/src/core/table/components/DataTableToolbar.tsx +7 -3
- package/src/core/table/components/FilterPicker.tsx +3 -3
- package/src/core/table/interfaces/types.ts +29 -0
- package/src/core/utils/icons.tsx +2 -2
- package/src/demo/DemoRouter.ts +8 -1
- package/src/demo/components/DemoLayout.tsx +12 -2
- package/src/demo/components/auth/DemoLogin.tsx +35 -28
- package/src/demo/components/auth/DemoRegister.tsx +35 -49
- package/src/demo/components/auth/DemoResetPassword.tsx +5 -9
- package/src/demo/components/auth/DemoVerifyEmail.tsx +7 -6
- package/src/demo/components/core/DemoButton.tsx +123 -103
- package/src/demo/components/core/DemoControlSelect.tsx +325 -0
- package/src/demo/components/core/DemoDataTable.tsx +255 -237
- package/src/demo/components/core/DemoTypeForm.tsx +7 -2
- package/src/demo/components/shared/MacWindow.tsx +5 -11
- package/src/demo/components/shared/Showcase.tsx +28 -42
- package/dist/admin/AdminJobDashboard-KIOkeMgE.js.map +0 -1
- package/dist/admin/AdminLayout-B1DXZHDn.js.map +0 -1
- package/dist/admin/AdminParameters-BspPeqp_.js.map +0 -1
- package/dist/admin/AdminUserLayout-DUbC6-BI.js.map +0 -1
- package/dist/admin/AdminUserProfile-DuTUnjdG.js.map +0 -1
- package/dist/admin/AdminUsers-CR9z0g_5.js.map +0 -1
- package/dist/admin/Login-DHbYJKwg.js +0 -219
- package/dist/admin/Login-DHbYJKwg.js.map +0 -1
- package/dist/admin/Profile-B2EcIDB9.js.map +0 -1
- package/dist/admin/Register-Z3fxRbUF.js.map +0 -1
- package/dist/admin/ResetPassword-_Y1qTTKh.js.map +0 -1
- package/dist/admin/VerifyEmail-Bg22bwcC.js.map +0 -1
- package/dist/admin/core-BVO_TQxb.js.map +0 -1
- package/dist/admin/rolldown-runtime-CjeV3_4I.js +0 -18
- package/dist/auth/Login-C7jIqf00.js +0 -219
- package/dist/auth/Login-C7jIqf00.js.map +0 -1
- package/dist/auth/Profile-BMpXJ0oi.js.map +0 -1
- package/dist/auth/Register-2gx8qll-.js.map +0 -1
- package/dist/auth/ResetPassword-DBxt9hKk.js.map +0 -1
- package/dist/auth/VerifyEmail-Z80Ubajk.js.map +0 -1
- package/dist/auth/core-DyfeVr5c.js.map +0 -1
- package/dist/auth/rolldown-runtime-CjeV3_4I.js +0 -18
- package/dist/demo/DemoButton-CGUyR9eM.js +0 -178
- package/dist/demo/DemoButton-CGUyR9eM.js.map +0 -1
- package/dist/demo/DemoDataTable-QFG-xXSx.js +0 -358
- package/dist/demo/DemoDataTable-QFG-xXSx.js.map +0 -1
- package/dist/demo/DemoLayout-Cy6xjn6P.js.map +0 -1
- package/dist/demo/DemoLogin-vqxgTu4P.js.map +0 -1
- package/dist/demo/DemoRegister-YHPvPg77.js.map +0 -1
- package/dist/demo/DemoResetPassword-mOW18Zlm.js.map +0 -1
- package/dist/demo/DemoTypeForm-C1dNkahD.js.map +0 -1
- package/dist/demo/DemoVerifyEmail-D9EcXZ38.js +0 -30
- package/dist/demo/DemoVerifyEmail-D9EcXZ38.js.map +0 -1
- package/dist/demo/Login-CoYf_P_F.js +0 -219
- package/dist/demo/Login-CoYf_P_F.js.map +0 -1
- package/dist/demo/Profile-BE_Y3co2.js.map +0 -1
- package/dist/demo/Register-fXHmBpr3.js.map +0 -1
- package/dist/demo/ResetPassword-CAPj8MO3.js.map +0 -1
- package/dist/demo/Showcase-BtEU0pY9.js.map +0 -1
- package/dist/demo/VerifyEmail-DFmdCdYs.js.map +0 -1
- package/dist/demo/core-B7LNjM78.js.map +0 -1
- package/dist/demo/rolldown-runtime-CjeV3_4I.js +0 -18
- 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 {
|
|
16
|
-
import {
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
|
|
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
|
-
* -
|
|
40
|
-
* -
|
|
41
|
-
* -
|
|
42
|
-
* -
|
|
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
|
-
//
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
-
|
|
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
|
-
|
|
76
|
-
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
143
|
+
// Static data from enum (no loader)
|
|
144
|
+
const [staticData, setStaticData] = useState<SelectValueLabel[]>([]);
|
|
79
145
|
|
|
80
|
-
|
|
81
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
186
|
+
value={value != null ? String(value) : ""}
|
|
101
187
|
{...segmentedControlProps}
|
|
102
|
-
onChange={(
|
|
103
|
-
|
|
188
|
+
onChange={(val) => {
|
|
189
|
+
setValue(coerceValue(val));
|
|
104
190
|
}}
|
|
105
|
-
data={
|
|
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
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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
|
-
<
|
|
228
|
+
<TagsInput
|
|
118
229
|
{...inputProps}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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
|
-
<
|
|
247
|
+
<Autocomplete
|
|
134
248
|
{...inputProps}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
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
|
-
{...
|
|
255
|
+
{...autocompleteExtraProps}
|
|
147
256
|
/>
|
|
148
257
|
);
|
|
149
258
|
}
|
|
150
259
|
// endregion
|
|
151
260
|
|
|
152
|
-
// region <MultiSelect/>
|
|
153
|
-
if (
|
|
154
|
-
const
|
|
155
|
-
|
|
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
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
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
|
-
{...
|
|
275
|
+
{...multiSelectExtraProps}
|
|
178
276
|
/>
|
|
179
277
|
);
|
|
180
278
|
}
|
|
181
279
|
// endregion
|
|
182
280
|
|
|
183
|
-
// region <Select/>
|
|
184
|
-
const
|
|
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
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
{...
|
|
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={{
|
|
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: {
|
|
534
|
-
field2: {
|
|
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
|
|
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"}
|
package/src/core/form/index.ts
CHANGED
|
@@ -2,13 +2,20 @@ import type { ControlProps } from "./components/Control.tsx";
|
|
|
2
2
|
|
|
3
3
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
4
4
|
|
|
5
|
-
export type {
|
|
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.
|
|
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.
|
|
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
|
-
|
|
111
|
+
label?: string;
|
|
108
112
|
description?: string;
|
|
109
113
|
icon?: ReactElement | ((props: { size: number }) => ReactNode);
|
|
110
114
|
size?: "xs" | "sm" | "md" | "lg" | "xl";
|
package/src/core/index.ts
CHANGED
|
@@ -93,7 +93,6 @@ export type {
|
|
|
93
93
|
SidebarButtonTheme,
|
|
94
94
|
SidebarDivider,
|
|
95
95
|
SidebarElement,
|
|
96
|
-
SidebarItemProps,
|
|
97
96
|
SidebarMenuItem,
|
|
98
97
|
SidebarNode,
|
|
99
98
|
SidebarProps,
|
|
@@ -103,6 +102,9 @@ export type {
|
|
|
103
102
|
SidebarTheme,
|
|
104
103
|
} from "./components/layout/Sidebar.tsx";
|
|
105
104
|
export { Sidebar } from "./components/layout/Sidebar.tsx";
|
|
105
|
+
export { SidebarCollapsedItem } from "./components/layout/SidebarCollapsedItem.tsx";
|
|
106
|
+
export type { SidebarItemProps } from "./components/layout/SidebarItem.tsx";
|
|
107
|
+
export { SidebarItem } from "./components/layout/SidebarItem.tsx";
|
|
106
108
|
export type { TextProps } from "./components/Text.tsx";
|
|
107
109
|
export { default as Text } from "./components/Text.tsx";
|
|
108
110
|
export * from "./constants/ui.ts";
|