@alepha/ui 0.17.2 → 0.18.1
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-CF_qOO3u.js → AdminApiKeys-C-6_Q-lH.js} +56 -192
- package/dist/admin/AdminApiKeys-C-6_Q-lH.js.map +1 -0
- package/dist/admin/{AdminAudits-BQno3hZG.js → AdminAudits-Bgbf04hO.js} +25 -61
- package/dist/admin/AdminAudits-Bgbf04hO.js.map +1 -0
- package/dist/admin/{AdminFiles-kvuUaASF.js → AdminFiles-B9a7G3cY.js} +6 -8
- package/dist/admin/AdminFiles-B9a7G3cY.js.map +1 -0
- package/dist/admin/{AdminJobDashboard-CrPxp0W1.js → AdminJobDashboard-DaTwf5OY.js} +55 -186
- package/dist/admin/AdminJobDashboard-DaTwf5OY.js.map +1 -0
- package/dist/admin/{AdminJobExecutions-D-b4Zt7W.js → AdminJobExecutions-B9cek5dl.js} +132 -168
- package/dist/admin/AdminJobExecutions-B9cek5dl.js.map +1 -0
- package/dist/admin/{AdminJobRegistry-CNX5cpDx.js → AdminJobRegistry-DFgV3oqx.js} +60 -83
- package/dist/admin/AdminJobRegistry-DFgV3oqx.js.map +1 -0
- package/dist/admin/AdminLayout-DHsvWxVB.js +70 -0
- package/dist/admin/AdminLayout-DHsvWxVB.js.map +1 -0
- package/dist/admin/{AdminParameters-DCGbpt2c.js → AdminParameters-DHw9ATgl.js} +53 -53
- package/dist/admin/AdminParameters-DHw9ATgl.js.map +1 -0
- package/dist/admin/{AdminSessions-DyhW6RZv.js → AdminSessions-BhGJPI3z.js} +11 -18
- package/dist/admin/AdminSessions-BhGJPI3z.js.map +1 -0
- package/dist/admin/{AdminUserLayout-CrBj4UuI.js → AdminUserLayout-BdC4Te8m.js} +112 -151
- package/dist/admin/AdminUserLayout-BdC4Te8m.js.map +1 -0
- package/dist/admin/AdminUserProfile-DAt23fqY.js +69 -0
- package/dist/admin/AdminUserProfile-DAt23fqY.js.map +1 -0
- package/dist/admin/AdminUserSessions-1uzcx02z.js +109 -0
- package/dist/admin/AdminUserSessions-1uzcx02z.js.map +1 -0
- package/dist/admin/AdminUsers-C85c3eiQ.js +121 -0
- package/dist/admin/AdminUsers-C85c3eiQ.js.map +1 -0
- package/dist/{auth/AuthLayout-CdJcrPs4.js → admin/AuthLayout-DFJvCvzw.js} +3 -3
- package/dist/{auth/AuthLayout-CdJcrPs4.js.map → admin/AuthLayout-DFJvCvzw.js.map} +1 -1
- package/dist/{auth/IconGoogle-Bm18QD2q.js → admin/IconGoogle-CSQLPYwX.js} +1 -1
- package/dist/{auth/IconGoogle-Bm18QD2q.js.map → admin/IconGoogle-CSQLPYwX.js.map} +1 -1
- package/dist/{demo/DemoLogin-DjJ9314c.js → admin/Login-BGheURrg.js} +15 -129
- package/dist/{auth/Login-BS_FYTy0.js.map → admin/Login-BGheURrg.js.map} +1 -1
- package/dist/{auth/Profile-CjDsW378.js → admin/Profile-B-c9pCPf.js} +5 -5
- package/dist/{auth/Profile-CjDsW378.js.map → admin/Profile-B-c9pCPf.js.map} +1 -1
- package/dist/{demo/DemoRegister-DzkJ5M83.js → admin/Register-Cs10l8vX.js} +20 -146
- package/dist/{auth/Register-C5eqzAaD.js.map → admin/Register-Cs10l8vX.js.map} +1 -1
- package/dist/{demo/DemoResetPassword-DWh4_BpQ.js → admin/ResetPassword-BwDdfkGH.js} +20 -82
- package/dist/{auth/ResetPassword-XifinVao.js.map → admin/ResetPassword-BwDdfkGH.js.map} +1 -1
- package/dist/{demo/DemoVerifyEmail-DbU_tCj8.js → admin/VerifyEmail-DfXHAiQl.js} +15 -32
- package/dist/{auth/VerifyEmail-DTgbeJOO.js.map → admin/VerifyEmail-DfXHAiQl.js.map} +1 -1
- package/dist/admin/auth-Dr0Cf8I7.js +319 -0
- package/dist/admin/auth-Dr0Cf8I7.js.map +1 -0
- package/dist/admin/core-2xoLiT0o.js +4031 -0
- package/dist/admin/core-2xoLiT0o.js.map +1 -0
- package/dist/admin/index.d.ts +739 -13
- package/dist/admin/index.d.ts.map +1 -1
- package/dist/admin/index.js +79 -111
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/rolldown-runtime-CjeV3_4I.js +18 -0
- package/dist/auth/AuthLayout-CAE1pX9s.js +22 -0
- package/dist/auth/AuthLayout-CAE1pX9s.js.map +1 -0
- package/dist/auth/{Login-BS_FYTy0.js → Login-Denw_UGy.js} +8 -8
- package/dist/auth/Login-Denw_UGy.js.map +1 -0
- package/dist/auth/Profile-BMX_Ar_s.js +155 -0
- package/dist/auth/Profile-BMX_Ar_s.js.map +1 -0
- package/dist/auth/{Register-C5eqzAaD.js → Register-6hi_cpfF.js} +8 -8
- package/dist/auth/Register-6hi_cpfF.js.map +1 -0
- package/dist/auth/{ResetPassword-XifinVao.js → ResetPassword-CqfTk1FI.js} +6 -6
- package/dist/auth/ResetPassword-CqfTk1FI.js.map +1 -0
- package/dist/auth/{VerifyEmail-DTgbeJOO.js → VerifyEmail-nWiSTMjF.js} +5 -5
- package/dist/auth/VerifyEmail-nWiSTMjF.js.map +1 -0
- package/dist/auth/core-niW0sFLv.js +2264 -0
- package/dist/auth/core-niW0sFLv.js.map +1 -0
- package/dist/auth/index.d.ts +336 -8
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +18 -22
- package/dist/auth/index.js.map +1 -1
- package/dist/core/index.d.ts +1033 -843
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1626 -1354
- package/dist/core/index.js.map +1 -1
- package/dist/demo/AuthLayout-jLa0aKsI.js +22 -0
- package/dist/demo/AuthLayout-jLa0aKsI.js.map +1 -0
- package/dist/demo/DemoButton-BmaWZVwf.js +178 -0
- package/dist/demo/DemoButton-BmaWZVwf.js.map +1 -0
- package/dist/demo/{DemoDataTable-lnBKWBf8.js → DemoDataTable-Z9xyV221.js} +18 -18
- package/dist/demo/DemoDataTable-Z9xyV221.js.map +1 -0
- package/dist/demo/DemoDialog-4ItHLf9t.js +101 -0
- package/dist/demo/DemoDialog-4ItHLf9t.js.map +1 -0
- package/dist/demo/DemoFlex-EtVq8QfX.js +105 -0
- package/dist/demo/DemoFlex-EtVq8QfX.js.map +1 -0
- package/dist/demo/DemoHeading-BS-vGfkI.js +18 -0
- package/dist/demo/DemoHeading-BS-vGfkI.js.map +1 -0
- package/dist/demo/{DemoHome-CUMZsYaH.js → DemoHome-Clbn8AmS.js} +9 -12
- package/dist/demo/DemoHome-Clbn8AmS.js.map +1 -0
- package/dist/demo/DemoJsonViewer-DkIX_ky2.js +109 -0
- package/dist/demo/DemoJsonViewer-DkIX_ky2.js.map +1 -0
- package/dist/demo/DemoLayout-C56xb5EE.js +73 -0
- package/dist/demo/DemoLayout-C56xb5EE.js.map +1 -0
- package/dist/demo/DemoLogin-BZwpicOS.js +128 -0
- package/dist/demo/DemoLogin-BZwpicOS.js.map +1 -0
- package/dist/demo/DemoRegister-C7_qc4MJ.js +140 -0
- package/dist/demo/DemoRegister-C7_qc4MJ.js.map +1 -0
- package/dist/demo/DemoResetPassword-BI1Ct4Dw.js +76 -0
- package/dist/demo/DemoResetPassword-BI1Ct4Dw.js.map +1 -0
- package/dist/demo/{DemoSidebar-C1csnGhX.js → DemoSidebar-CcBo4ltC.js} +6 -9
- package/dist/demo/DemoSidebar-CcBo4ltC.js.map +1 -0
- package/dist/demo/DemoText-CzXuUn3g.js +124 -0
- package/dist/demo/DemoText-CzXuUn3g.js.map +1 -0
- package/dist/demo/DemoToast-BgHDhWrX.js +95 -0
- package/dist/demo/DemoToast-BgHDhWrX.js.map +1 -0
- package/dist/demo/{DemoTypeForm-CWz6fJrJ.js → DemoTypeForm-DDzWoMSV.js} +4 -4
- package/dist/demo/{DemoTypeForm-CWz6fJrJ.js.map → DemoTypeForm-DDzWoMSV.js.map} +1 -1
- package/dist/demo/DemoVerifyEmail-C_Irdnov.js +30 -0
- package/dist/demo/DemoVerifyEmail-C_Irdnov.js.map +1 -0
- package/dist/demo/IconGoogle-CSQLPYwX.js +56 -0
- package/dist/demo/IconGoogle-CSQLPYwX.js.map +1 -0
- package/dist/demo/Login-hSOU3jZc.js +219 -0
- package/dist/demo/Login-hSOU3jZc.js.map +1 -0
- package/dist/demo/Profile-CWqti7FB.js +155 -0
- package/dist/demo/Profile-CWqti7FB.js.map +1 -0
- package/dist/demo/Register-a70LPgs2.js +375 -0
- package/dist/demo/Register-a70LPgs2.js.map +1 -0
- package/dist/demo/ResetPassword-DWN0lzr5.js +286 -0
- package/dist/demo/ResetPassword-DWN0lzr5.js.map +1 -0
- package/dist/demo/Showcase-Dq3MISpd.js +232 -0
- package/dist/demo/Showcase-Dq3MISpd.js.map +1 -0
- package/dist/demo/VerifyEmail-DZWL72K4.js +135 -0
- package/dist/demo/VerifyEmail-DZWL72K4.js.map +1 -0
- package/dist/demo/auth-d6n3xbug.js +257 -0
- package/dist/demo/auth-d6n3xbug.js.map +1 -0
- package/dist/demo/core-RCUw1Q-a.js +4217 -0
- package/dist/demo/core-RCUw1Q-a.js.map +1 -0
- package/dist/demo/index.d.ts +17 -6
- package/dist/demo/index.d.ts.map +1 -1
- package/dist/demo/index.js +92 -24
- package/dist/demo/index.js.map +1 -1
- package/dist/demo/rolldown-runtime-CjeV3_4I.js +18 -0
- package/package.json +16 -20
- package/src/admin/AdminRouter.ts +10 -39
- package/src/admin/components/AdminLayout.tsx +42 -10
- package/src/admin/components/audits/AdminAudits.tsx +10 -64
- package/src/admin/components/files/AdminFiles.tsx +2 -3
- package/src/admin/components/jobs/AdminJobDashboard.tsx +36 -142
- package/src/admin/components/jobs/AdminJobExecutions.tsx +117 -175
- package/src/admin/components/jobs/AdminJobRegistry.tsx +58 -73
- package/src/admin/components/keys/AdminApiKeys.tsx +21 -169
- package/src/admin/components/parameters/AdminParameters.tsx +4 -4
- package/src/admin/components/parameters/ParameterEmptyState.tsx +1 -2
- package/src/admin/components/parameters/ParameterHistory.tsx +3 -3
- package/src/admin/components/parameters/ParameterTree.tsx +2 -8
- package/src/admin/components/parameters/types.ts +3 -3
- package/src/admin/components/sessions/AdminSessions.tsx +8 -16
- package/src/admin/components/users/AdminUserLayout.tsx +113 -150
- package/src/admin/components/users/AdminUserProfile.tsx +50 -0
- package/src/admin/components/users/AdminUserSessions.tsx +106 -126
- package/src/admin/components/users/AdminUsers.tsx +46 -62
- package/src/admin/index.ts +0 -4
- package/src/auth/components/buttons/UserButton.tsx +1 -1
- package/src/auth/index.ts +0 -4
- package/src/core/UiRouter.ts +1 -1
- package/src/core/atoms/alephaSidebarAtom.ts +7 -31
- package/src/core/components/{layout/AlephaMantineProvider.tsx → AlephaMantineProvider.tsx} +3 -4
- package/src/core/components/Flex.tsx +63 -0
- package/src/core/components/Heading.tsx +19 -0
- package/src/core/components/Text.tsx +140 -0
- package/src/core/components/buttons/ActionButton.tsx +12 -1
- package/src/core/components/buttons/BurgerButton.tsx +3 -3
- package/src/core/components/buttons/LanguageButton.tsx +1 -1
- package/src/core/components/buttons/ToggleSidebarButton.tsx +1 -4
- package/src/core/components/data/DetailDrawer.tsx +144 -0
- package/src/core/components/data/DetailList.tsx +64 -0
- package/src/core/components/data/StatCards.tsx +50 -0
- package/src/core/components/layout/AppBar.tsx +11 -10
- package/src/core/components/layout/Breadcrumb.tsx +8 -8
- package/src/core/components/layout/Container.tsx +15 -0
- package/src/core/components/layout/DashboardShell.tsx +23 -238
- package/src/core/components/layout/Omnibar.tsx +1 -2
- package/src/core/components/layout/Sidebar.tsx +103 -71
- package/src/core/components/layout/index.ts +65 -0
- package/src/core/{components/form → form/components}/Control.tsx +32 -14
- package/src/core/{components/form → form/components}/ControlArray.tsx +2 -5
- package/src/core/{components/form → form/components}/ControlDate.tsx +1 -4
- package/src/core/{components/form → form/components}/ControlNumber.tsx +1 -4
- package/src/core/{components/form → form/components}/ControlObject.tsx +1 -4
- package/src/core/{components/form → form/components}/ControlQueryBuilder.tsx +7 -7
- package/src/core/{components/form → form/components}/ControlSelect.tsx +2 -4
- package/src/core/{components/form → form/components}/TypeForm.browser.spec.tsx +22 -64
- package/src/core/{components/form → form/components}/TypeForm.tsx +1 -3
- package/src/core/form/factories/dialogForm.tsx +31 -0
- package/src/core/form/index.ts +23 -0
- package/src/core/{utils → form/utils}/parseInput.ts +2 -4
- package/src/core/index.ts +43 -51
- package/src/core/interfaces/AlephaIntent.ts +6 -0
- package/src/core/interfaces/AlephaTheme.ts +0 -1
- package/src/core/json/factories/dialogJson.tsx +24 -0
- package/src/core/json/index.ts +2 -0
- package/src/core/primitives/$ui.ts +17 -0
- package/src/core/services/DialogService.tsx +1 -48
- package/src/core/styles.css +1 -8
- package/src/core/{components/table → table/components}/ColumnPicker.tsx +2 -3
- package/src/core/{components/table → table/components}/DataTable.tsx +8 -9
- package/src/core/{components/table → table/components}/DataTableFilters.tsx +6 -3
- package/src/core/{components/table → table/components}/DataTableToolbar.tsx +4 -5
- package/src/core/{components/table → table/components}/FilterPicker.tsx +2 -3
- package/src/core/table/index.ts +12 -0
- package/src/core/{components/table → table/interfaces}/types.ts +2 -2
- package/src/demo/DemoRouter.ts +87 -6
- package/src/demo/components/DemoHome.tsx +6 -10
- package/src/demo/components/DemoLayout.tsx +38 -8
- package/src/demo/components/auth/DemoLogin.tsx +1 -1
- package/src/demo/components/auth/DemoRegister.tsx +1 -1
- package/src/demo/components/auth/DemoResetPassword.tsx +1 -1
- package/src/demo/components/auth/DemoVerifyEmail.tsx +1 -1
- package/src/demo/components/core/DemoButton.tsx +160 -0
- package/src/demo/components/core/DemoFlex.tsx +101 -0
- package/src/demo/components/core/DemoHeading.tsx +13 -0
- package/src/demo/components/core/DemoText.tsx +110 -0
- package/src/demo/components/json/DemoJsonViewer.tsx +1 -1
- package/src/demo/components/layout/DemoDialog.tsx +103 -0
- package/src/demo/components/{core → layout}/DemoSidebar.tsx +0 -1
- package/src/demo/components/layout/DemoToast.tsx +96 -0
- package/src/demo/components/shared/MacWindow.tsx +149 -74
- package/src/demo/components/shared/Showcase.tsx +4 -8
- package/src/demo/index.ts +1 -4
- package/src/demo/primitives/$uiDemo.ts +10 -0
- package/dist/admin/AdminApiKeys-CF_qOO3u.js.map +0 -1
- package/dist/admin/AdminAudits-BQno3hZG.js.map +0 -1
- package/dist/admin/AdminFiles-kvuUaASF.js.map +0 -1
- package/dist/admin/AdminJobDashboard-CrPxp0W1.js.map +0 -1
- package/dist/admin/AdminJobExecutions-D-b4Zt7W.js.map +0 -1
- package/dist/admin/AdminJobRegistry-CNX5cpDx.js.map +0 -1
- package/dist/admin/AdminLayout-e-ZP5nWw.js +0 -37
- package/dist/admin/AdminLayout-e-ZP5nWw.js.map +0 -1
- package/dist/admin/AdminParameters-DCGbpt2c.js.map +0 -1
- package/dist/admin/AdminSessions-DyhW6RZv.js.map +0 -1
- package/dist/admin/AdminUserAudits-D1GcREEE.js +0 -177
- package/dist/admin/AdminUserAudits-D1GcREEE.js.map +0 -1
- package/dist/admin/AdminUserCreate-DR8LA0tv.js +0 -104
- package/dist/admin/AdminUserCreate-DR8LA0tv.js.map +0 -1
- package/dist/admin/AdminUserDetails-CDkZNHQD.js +0 -477
- package/dist/admin/AdminUserDetails-CDkZNHQD.js.map +0 -1
- package/dist/admin/AdminUserLayout-CrBj4UuI.js.map +0 -1
- package/dist/admin/AdminUserSessions-srgFHrqy.js +0 -129
- package/dist/admin/AdminUserSessions-srgFHrqy.js.map +0 -1
- package/dist/admin/AdminUserSettings-BFuxl-xT.js +0 -167
- package/dist/admin/AdminUserSettings-BFuxl-xT.js.map +0 -1
- package/dist/admin/AdminUsers-D1pDpiwK.js +0 -118
- package/dist/admin/AdminUsers-D1pDpiwK.js.map +0 -1
- package/dist/demo/DemoDataTable-lnBKWBf8.js.map +0 -1
- package/dist/demo/DemoHome-CUMZsYaH.js.map +0 -1
- package/dist/demo/DemoJsonViewer-_uokbGaW.js +0 -429
- package/dist/demo/DemoJsonViewer-_uokbGaW.js.map +0 -1
- package/dist/demo/DemoLayout-DHVoacE6.js +0 -46
- package/dist/demo/DemoLayout-DHVoacE6.js.map +0 -1
- package/dist/demo/DemoLogin-DjJ9314c.js.map +0 -1
- package/dist/demo/DemoRegister-DzkJ5M83.js.map +0 -1
- package/dist/demo/DemoResetPassword-DWh4_BpQ.js.map +0 -1
- package/dist/demo/DemoSidebar-C1csnGhX.js.map +0 -1
- package/dist/demo/DemoVerifyEmail-DbU_tCj8.js.map +0 -1
- package/dist/demo/Showcase-BzoXNlCn.js +0 -185
- package/dist/demo/Showcase-BzoXNlCn.js.map +0 -1
- package/dist/json/index.d.ts +0 -57
- package/dist/json/index.d.ts.map +0 -1
- package/dist/json/index.js +0 -325
- package/dist/json/index.js.map +0 -1
- package/src/admin/components/users/AdminUserAudits.tsx +0 -184
- package/src/admin/components/users/AdminUserCreate.tsx +0 -85
- package/src/admin/components/users/AdminUserDetails.tsx +0 -431
- package/src/admin/components/users/AdminUserSettings.tsx +0 -171
- package/src/core/components/data/ErrorViewer.tsx +0 -171
- package/src/json/extensions/DialogService.tsx +0 -31
- package/src/json/index.ts +0 -18
- package/src/json/styles.css +0 -1
- /package/dist/{demo → auth}/IconGoogle-Ch1m3Uzl.js +0 -0
- /package/dist/{demo → auth}/IconGoogle-Ch1m3Uzl.js.map +0 -0
- /package/src/{json → core/json}/components/JsonViewer.css +0 -0
- /package/src/{json → core/json}/components/JsonViewer.tsx +0 -0
- /package/src/core/{components/table → table/components}/DataTablePagination.tsx +0 -0
- /package/src/core/{components/table → table/components}/useTableSelection.ts +0 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Drawer,
|
|
3
|
+
type DrawerProps,
|
|
4
|
+
Flex,
|
|
5
|
+
Loader,
|
|
6
|
+
Tabs,
|
|
7
|
+
Text,
|
|
8
|
+
} from "@mantine/core";
|
|
9
|
+
import type { ComponentType, ReactNode } from "react";
|
|
10
|
+
import type { ActionMenuItem } from "../buttons/ActionButton.tsx";
|
|
11
|
+
import ActionButton from "../buttons/ActionButton.tsx";
|
|
12
|
+
|
|
13
|
+
export interface DetailDrawerTab {
|
|
14
|
+
value: string;
|
|
15
|
+
label: string;
|
|
16
|
+
icon?: ComponentType<{ size?: number }>;
|
|
17
|
+
content: ReactNode;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface DetailDrawerStatus {
|
|
21
|
+
label: string;
|
|
22
|
+
active: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface DetailDrawerProps {
|
|
26
|
+
opened: boolean;
|
|
27
|
+
onClose: () => void;
|
|
28
|
+
title: ReactNode;
|
|
29
|
+
subtitle?: ReactNode;
|
|
30
|
+
status?: DetailDrawerStatus;
|
|
31
|
+
actions?: ActionMenuItem[];
|
|
32
|
+
tabs?: DetailDrawerTab[];
|
|
33
|
+
children?: ReactNode;
|
|
34
|
+
loading?: boolean;
|
|
35
|
+
size?: DrawerProps["size"];
|
|
36
|
+
defaultTab?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const DetailDrawer = ({
|
|
40
|
+
opened,
|
|
41
|
+
onClose,
|
|
42
|
+
title,
|
|
43
|
+
subtitle,
|
|
44
|
+
status,
|
|
45
|
+
actions,
|
|
46
|
+
tabs,
|
|
47
|
+
children,
|
|
48
|
+
loading,
|
|
49
|
+
size = "xl",
|
|
50
|
+
defaultTab,
|
|
51
|
+
}: DetailDrawerProps) => (
|
|
52
|
+
<Drawer
|
|
53
|
+
opened={opened}
|
|
54
|
+
onClose={onClose}
|
|
55
|
+
position="right"
|
|
56
|
+
size={size}
|
|
57
|
+
withCloseButton={false}
|
|
58
|
+
padding={0}
|
|
59
|
+
>
|
|
60
|
+
{/* Header */}
|
|
61
|
+
<Flex
|
|
62
|
+
p="md"
|
|
63
|
+
justify="space-between"
|
|
64
|
+
align="flex-start"
|
|
65
|
+
style={{ borderBottom: "1px solid var(--mantine-color-default-border)" }}
|
|
66
|
+
>
|
|
67
|
+
<Flex direction="column" gap={2} style={{ minWidth: 0, flex: 1 }}>
|
|
68
|
+
<Flex gap="xs" align="center">
|
|
69
|
+
{status && (
|
|
70
|
+
<Flex
|
|
71
|
+
w={8}
|
|
72
|
+
h={8}
|
|
73
|
+
style={{
|
|
74
|
+
borderRadius: "50%",
|
|
75
|
+
backgroundColor: status.active
|
|
76
|
+
? "var(--mantine-color-green-6)"
|
|
77
|
+
: "var(--mantine-color-red-6)",
|
|
78
|
+
flexShrink: 0,
|
|
79
|
+
}}
|
|
80
|
+
/>
|
|
81
|
+
)}
|
|
82
|
+
<Text size="lg" fw={600} truncate>
|
|
83
|
+
{title}
|
|
84
|
+
</Text>
|
|
85
|
+
</Flex>
|
|
86
|
+
{subtitle && (
|
|
87
|
+
<Text size="sm" c="dimmed" truncate>
|
|
88
|
+
{subtitle}
|
|
89
|
+
</Text>
|
|
90
|
+
)}
|
|
91
|
+
</Flex>
|
|
92
|
+
<Flex gap="xs" align="center" style={{ flexShrink: 0 }}>
|
|
93
|
+
{actions && actions.length > 0 && (
|
|
94
|
+
<ActionButton
|
|
95
|
+
variant="default"
|
|
96
|
+
size="xs"
|
|
97
|
+
menu={{
|
|
98
|
+
items: actions,
|
|
99
|
+
position: "bottom-end",
|
|
100
|
+
width: 200,
|
|
101
|
+
}}
|
|
102
|
+
>
|
|
103
|
+
Actions
|
|
104
|
+
</ActionButton>
|
|
105
|
+
)}
|
|
106
|
+
<ActionButton variant="subtle" size="xs" c="dimmed" onClick={onClose}>
|
|
107
|
+
Close
|
|
108
|
+
</ActionButton>
|
|
109
|
+
</Flex>
|
|
110
|
+
</Flex>
|
|
111
|
+
|
|
112
|
+
{/* Content */}
|
|
113
|
+
{loading ? (
|
|
114
|
+
<Flex flex={1} justify="center" align="center" py="xl">
|
|
115
|
+
<Loader />
|
|
116
|
+
</Flex>
|
|
117
|
+
) : tabs && tabs.length > 0 ? (
|
|
118
|
+
<Tabs defaultValue={defaultTab || tabs[0].value}>
|
|
119
|
+
<Tabs.List px="md">
|
|
120
|
+
{tabs.map((tab) => (
|
|
121
|
+
<Tabs.Tab
|
|
122
|
+
key={tab.value}
|
|
123
|
+
value={tab.value}
|
|
124
|
+
leftSection={tab.icon ? <tab.icon size={14} /> : undefined}
|
|
125
|
+
>
|
|
126
|
+
{tab.label}
|
|
127
|
+
</Tabs.Tab>
|
|
128
|
+
))}
|
|
129
|
+
</Tabs.List>
|
|
130
|
+
{tabs.map((tab) => (
|
|
131
|
+
<Tabs.Panel key={tab.value} value={tab.value} p="md">
|
|
132
|
+
{tab.content}
|
|
133
|
+
</Tabs.Panel>
|
|
134
|
+
))}
|
|
135
|
+
</Tabs>
|
|
136
|
+
) : (
|
|
137
|
+
<Flex direction="column" p="md">
|
|
138
|
+
{children}
|
|
139
|
+
</Flex>
|
|
140
|
+
)}
|
|
141
|
+
</Drawer>
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
export default DetailDrawer;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Flex, Grid, Text } from "@mantine/core";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
import ClipboardButton from "../buttons/ClipboardButton.tsx";
|
|
4
|
+
|
|
5
|
+
export interface DetailListItem {
|
|
6
|
+
label: string;
|
|
7
|
+
value: ReactNode;
|
|
8
|
+
hidden?: boolean;
|
|
9
|
+
copyable?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface DetailListProps {
|
|
13
|
+
items: DetailListItem[];
|
|
14
|
+
columns?: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const DetailList = ({ items, columns = 1 }: DetailListProps) => {
|
|
18
|
+
const visibleItems = items.filter((item) => !item.hidden);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<Grid gutter="xs">
|
|
22
|
+
{visibleItems.map((item) => (
|
|
23
|
+
<Grid.Col key={item.label} span={12 / columns}>
|
|
24
|
+
<Flex
|
|
25
|
+
py={6}
|
|
26
|
+
justify="space-between"
|
|
27
|
+
align="center"
|
|
28
|
+
style={{
|
|
29
|
+
borderBottom: "1px solid var(--mantine-color-default-border)",
|
|
30
|
+
}}
|
|
31
|
+
>
|
|
32
|
+
<Text size="xs" c="dimmed" style={{ flexShrink: 0 }}>
|
|
33
|
+
{item.label}
|
|
34
|
+
</Text>
|
|
35
|
+
<Flex gap={4} align="center" style={{ minWidth: 0 }}>
|
|
36
|
+
{typeof item.value === "string" ||
|
|
37
|
+
typeof item.value === "number" ? (
|
|
38
|
+
<Text size="sm" fw={500} truncate>
|
|
39
|
+
{item.value || "\u2014"}
|
|
40
|
+
</Text>
|
|
41
|
+
) : (
|
|
42
|
+
(item.value ?? (
|
|
43
|
+
<Text size="sm" c="dimmed">
|
|
44
|
+
{"\u2014"}
|
|
45
|
+
</Text>
|
|
46
|
+
))
|
|
47
|
+
)}
|
|
48
|
+
{item.copyable && (
|
|
49
|
+
<ClipboardButton
|
|
50
|
+
value={item.copyable}
|
|
51
|
+
size="xs"
|
|
52
|
+
variant="subtle"
|
|
53
|
+
c="dimmed"
|
|
54
|
+
/>
|
|
55
|
+
)}
|
|
56
|
+
</Flex>
|
|
57
|
+
</Flex>
|
|
58
|
+
</Grid.Col>
|
|
59
|
+
))}
|
|
60
|
+
</Grid>
|
|
61
|
+
);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export default DetailList;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Flex, Paper, Text } from "@mantine/core";
|
|
2
|
+
import type { ComponentType, ReactNode } from "react";
|
|
3
|
+
import { ui } from "../../constants/ui.ts";
|
|
4
|
+
|
|
5
|
+
export interface StatCardItem {
|
|
6
|
+
label: string;
|
|
7
|
+
value: ReactNode;
|
|
8
|
+
icon?: ReactNode | ComponentType<{ size?: number }>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface StatCardsProps {
|
|
12
|
+
items: StatCardItem[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const StatCards = ({ items }: StatCardsProps) => (
|
|
16
|
+
<Flex gap="sm" wrap="wrap">
|
|
17
|
+
{items.map((item) => {
|
|
18
|
+
const IconComponent =
|
|
19
|
+
item.icon && typeof item.icon === "function" ? item.icon : null;
|
|
20
|
+
const iconNode = IconComponent ? (
|
|
21
|
+
<IconComponent size={ui.sizes.icon.md} />
|
|
22
|
+
) : (
|
|
23
|
+
(item.icon as ReactNode)
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<Paper
|
|
28
|
+
key={item.label}
|
|
29
|
+
p="md"
|
|
30
|
+
radius="md"
|
|
31
|
+
withBorder
|
|
32
|
+
style={{ flex: "1 1 0", minWidth: 120 }}
|
|
33
|
+
>
|
|
34
|
+
<Flex gap="sm" align="center">
|
|
35
|
+
<Flex direction="column">
|
|
36
|
+
<Text size="xl" fw={700} lh={1}>
|
|
37
|
+
{item.value}
|
|
38
|
+
</Text>
|
|
39
|
+
<Text size="xs" c="dimmed">
|
|
40
|
+
{item.label}
|
|
41
|
+
</Text>
|
|
42
|
+
</Flex>
|
|
43
|
+
</Flex>
|
|
44
|
+
</Paper>
|
|
45
|
+
);
|
|
46
|
+
})}
|
|
47
|
+
</Flex>
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
export default StatCards;
|
|
@@ -1,24 +1,25 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ActionButton,
|
|
3
|
+
type ActionProps,
|
|
4
|
+
BurgerButton,
|
|
5
|
+
DarkModeButton,
|
|
6
|
+
Flex,
|
|
7
|
+
LanguageButton,
|
|
8
|
+
OmnibarButton,
|
|
9
|
+
type OmnibarButtonProps,
|
|
10
|
+
Text,
|
|
11
|
+
} from "@alepha/ui";
|
|
1
12
|
import {
|
|
2
13
|
Anchor,
|
|
3
14
|
Container,
|
|
4
15
|
type ContainerProps,
|
|
5
16
|
Divider,
|
|
6
|
-
Flex,
|
|
7
17
|
type FlexProps,
|
|
8
18
|
Image,
|
|
9
|
-
Text,
|
|
10
19
|
} from "@mantine/core";
|
|
11
20
|
import { IconArrowLeft } from "@tabler/icons-react";
|
|
12
21
|
import { Link, useRouter } from "alepha/react/router";
|
|
13
22
|
import type { ComponentType, ReactNode } from "react";
|
|
14
|
-
import type { ActionProps } from "../buttons/ActionButton.tsx";
|
|
15
|
-
import ActionButton from "../buttons/ActionButton.tsx";
|
|
16
|
-
import BurgerButton from "../buttons/BurgerButton.tsx";
|
|
17
|
-
import DarkModeButton from "../buttons/DarkModeButton.tsx";
|
|
18
|
-
import LanguageButton from "../buttons/LanguageButton.tsx";
|
|
19
|
-
import OmnibarButton, {
|
|
20
|
-
type OmnibarButtonProps,
|
|
21
|
-
} from "../buttons/OmnibarButton.tsx";
|
|
22
23
|
|
|
23
24
|
export type AppBarItem =
|
|
24
25
|
| AppBarElement
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ActionButton, Flex, Text, toTitleCase } from "@alepha/ui";
|
|
2
|
+
import type { FlexProps } from "@mantine/core";
|
|
2
3
|
import { IconChevronRight } from "@tabler/icons-react";
|
|
3
|
-
import {
|
|
4
|
+
import { useRouter, useRouterState } from "alepha/react/router";
|
|
4
5
|
import type { ReactNode } from "react";
|
|
5
|
-
import { toTitleCase } from "../../utils/string.ts";
|
|
6
6
|
|
|
7
7
|
export interface BreadcrumbProps extends FlexProps {
|
|
8
8
|
/**
|
|
@@ -37,7 +37,7 @@ export interface BreadcrumbProps extends FlexProps {
|
|
|
37
37
|
const Breadcrumb = ({
|
|
38
38
|
home = "Home",
|
|
39
39
|
separator,
|
|
40
|
-
size = "
|
|
40
|
+
size = "sm",
|
|
41
41
|
...groupProps
|
|
42
42
|
}: BreadcrumbProps) => {
|
|
43
43
|
const state = useRouterState();
|
|
@@ -69,14 +69,14 @@ const Breadcrumb = ({
|
|
|
69
69
|
const sep = separator ?? <IconChevronRight size={12} color="#9ca3af" />;
|
|
70
70
|
|
|
71
71
|
return (
|
|
72
|
-
<Flex gap={
|
|
72
|
+
<Flex gap={"sm"} {...groupProps}>
|
|
73
73
|
{crumbs.map((crumb, i) => (
|
|
74
|
-
<Flex key={crumb.href} gap={
|
|
74
|
+
<Flex align={"center"} key={crumb.href} gap={"sm"}>
|
|
75
75
|
{i > 0 && sep}
|
|
76
76
|
{i < crumbs.length - 1 ? (
|
|
77
|
-
<
|
|
77
|
+
<ActionButton anchor href={crumb.href} size={size} c="dimmed">
|
|
78
78
|
{crumb.label}
|
|
79
|
-
</
|
|
79
|
+
</ActionButton>
|
|
80
80
|
) : (
|
|
81
81
|
<Text size={size} fw={500}>
|
|
82
82
|
{crumb.label}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Container as MantineContainer,
|
|
3
|
+
type ContainerProps as MantineContainerProps,
|
|
4
|
+
} from "@mantine/core";
|
|
5
|
+
import { forwardRef } from "react";
|
|
6
|
+
|
|
7
|
+
export interface ContainerProps extends MantineContainerProps {}
|
|
8
|
+
|
|
9
|
+
const Container = forwardRef<HTMLDivElement, ContainerProps>((props, ref) => {
|
|
10
|
+
return <MantineContainer ref={ref} {...props} />;
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
Container.displayName = "Container";
|
|
14
|
+
|
|
15
|
+
export default Container;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { alephaSidebarAtom, Flex } from "@alepha/ui";
|
|
1
2
|
import {
|
|
2
3
|
AppShell,
|
|
3
4
|
type AppShellFooterProps,
|
|
@@ -5,26 +6,14 @@ import {
|
|
|
5
6
|
type AppShellMainProps,
|
|
6
7
|
type AppShellNavbarProps,
|
|
7
8
|
type AppShellProps,
|
|
8
|
-
Container,
|
|
9
9
|
type ContainerProps,
|
|
10
|
-
Flex,
|
|
11
10
|
} from "@mantine/core";
|
|
12
11
|
import { useEvents, useStore } from "alepha/react";
|
|
13
12
|
import { NestedView, useRouter } from "alepha/react/router";
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
useCallback,
|
|
17
|
-
useEffect,
|
|
18
|
-
useRef,
|
|
19
|
-
useState,
|
|
20
|
-
} from "react";
|
|
21
|
-
import { alephaSidebarAtom } from "../../atoms/alephaSidebarAtom.ts";
|
|
13
|
+
import type { ReactNode } from "react";
|
|
14
|
+
import { useState } from "react";
|
|
22
15
|
import AppBar, { type AppBarProps } from "./AppBar.tsx";
|
|
23
|
-
import {
|
|
24
|
-
Sidebar,
|
|
25
|
-
type SidebarMenuItem,
|
|
26
|
-
type SidebarProps,
|
|
27
|
-
} from "./Sidebar.tsx";
|
|
16
|
+
import { Sidebar, type SidebarProps } from "./Sidebar.tsx";
|
|
28
17
|
|
|
29
18
|
export interface DashboardShellProps {
|
|
30
19
|
appShellProps?: Partial<AppShellProps>;
|
|
@@ -67,12 +56,6 @@ export interface DashboardShellProps {
|
|
|
67
56
|
*/
|
|
68
57
|
footerHeight?: number;
|
|
69
58
|
|
|
70
|
-
/**
|
|
71
|
-
* Enable drag-to-resize for the sidebar.
|
|
72
|
-
* Width and constraints are configured in alephaSidebarAtom.
|
|
73
|
-
*/
|
|
74
|
-
sidebarResizable?: boolean;
|
|
75
|
-
|
|
76
59
|
noSidebarWhen?: {
|
|
77
60
|
/**
|
|
78
61
|
* Paths where the sidebar should be hidden.
|
|
@@ -90,138 +73,12 @@ export interface DashboardShellProps {
|
|
|
90
73
|
const DashboardShell = (props: DashboardShellProps) => {
|
|
91
74
|
const router = useRouter();
|
|
92
75
|
const [sidebar, setSidebar] = useStore(alephaSidebarAtom);
|
|
93
|
-
const { opened } = sidebar;
|
|
94
76
|
const collapsed =
|
|
95
77
|
props.sidebarProps?.collapsed !== undefined
|
|
96
78
|
? props.sidebarProps.collapsed
|
|
97
79
|
: sidebar.collapsed;
|
|
98
80
|
|
|
99
|
-
|
|
100
|
-
const [isResizing, setIsResizing] = useState(false);
|
|
101
|
-
const [isHovering, setIsHovering] = useState(false);
|
|
102
|
-
const [collapseEffect, setCollapseEffect] = useState({
|
|
103
|
-
offset: 0,
|
|
104
|
-
opacity: 1,
|
|
105
|
-
});
|
|
106
|
-
const resizeRef = useRef<{ startX: number; startWidth: number } | null>(null);
|
|
107
|
-
|
|
108
|
-
// Use atom values for constraints
|
|
109
|
-
const {
|
|
110
|
-
collapsedWidth,
|
|
111
|
-
collapseThreshold,
|
|
112
|
-
maxWidth,
|
|
113
|
-
hoverDelay,
|
|
114
|
-
defaultWidth,
|
|
115
|
-
} = sidebar;
|
|
116
|
-
|
|
117
|
-
const handleResizeStart = useCallback(
|
|
118
|
-
(e: React.MouseEvent) => {
|
|
119
|
-
if (!props.sidebarResizable) return;
|
|
120
|
-
e.preventDefault();
|
|
121
|
-
|
|
122
|
-
// If collapsed and hovering, un-collapse first and start from defaultWidth
|
|
123
|
-
if (collapsed) {
|
|
124
|
-
setSidebar({ ...sidebar, collapsed: false, width: defaultWidth });
|
|
125
|
-
setIsResizing(true);
|
|
126
|
-
resizeRef.current = {
|
|
127
|
-
startX: e.clientX,
|
|
128
|
-
startWidth: defaultWidth,
|
|
129
|
-
};
|
|
130
|
-
} else {
|
|
131
|
-
setIsResizing(true);
|
|
132
|
-
resizeRef.current = {
|
|
133
|
-
startX: e.clientX,
|
|
134
|
-
startWidth: sidebar.width,
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
},
|
|
138
|
-
[props.sidebarResizable, collapsed, sidebar, setSidebar, defaultWidth],
|
|
139
|
-
);
|
|
140
|
-
|
|
141
|
-
useEffect(() => {
|
|
142
|
-
if (!isResizing) return;
|
|
143
|
-
|
|
144
|
-
const handleMouseMove = (e: MouseEvent) => {
|
|
145
|
-
if (!resizeRef.current) return;
|
|
146
|
-
const delta = e.clientX - resizeRef.current.startX;
|
|
147
|
-
const rawWidth = resizeRef.current.startWidth + delta;
|
|
148
|
-
const newWidth = Math.min(Math.max(rawWidth, collapsedWidth), maxWidth);
|
|
149
|
-
|
|
150
|
-
// Visual effect when below collapse threshold
|
|
151
|
-
if (rawWidth < collapseThreshold) {
|
|
152
|
-
const progress = Math.max(
|
|
153
|
-
0,
|
|
154
|
-
(collapseThreshold - rawWidth) / collapseThreshold,
|
|
155
|
-
);
|
|
156
|
-
setCollapseEffect({
|
|
157
|
-
offset: -progress * collapsedWidth,
|
|
158
|
-
opacity: 1 - progress * 0.7,
|
|
159
|
-
});
|
|
160
|
-
setSidebar({ ...sidebar, width: collapseThreshold, collapsed: false });
|
|
161
|
-
} else {
|
|
162
|
-
setCollapseEffect({ offset: 0, opacity: 1 });
|
|
163
|
-
setSidebar({ ...sidebar, width: newWidth, collapsed: false });
|
|
164
|
-
}
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
const handleMouseUp = () => {
|
|
168
|
-
// If we released while in collapse zone, actually collapse
|
|
169
|
-
if (collapseEffect.offset < 0) {
|
|
170
|
-
setSidebar({ ...sidebar, collapsed: true });
|
|
171
|
-
}
|
|
172
|
-
setCollapseEffect({ offset: 0, opacity: 1 });
|
|
173
|
-
setIsResizing(false);
|
|
174
|
-
resizeRef.current = null;
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
document.addEventListener("mousemove", handleMouseMove);
|
|
178
|
-
document.addEventListener("mouseup", handleMouseUp);
|
|
179
|
-
|
|
180
|
-
return () => {
|
|
181
|
-
document.removeEventListener("mousemove", handleMouseMove);
|
|
182
|
-
document.removeEventListener("mouseup", handleMouseUp);
|
|
183
|
-
};
|
|
184
|
-
}, [
|
|
185
|
-
isResizing,
|
|
186
|
-
sidebar,
|
|
187
|
-
setSidebar,
|
|
188
|
-
collapsedWidth,
|
|
189
|
-
maxWidth,
|
|
190
|
-
collapseThreshold,
|
|
191
|
-
collapseEffect.offset,
|
|
192
|
-
]);
|
|
193
|
-
|
|
194
|
-
// Hover to expand when collapsed (with delay)
|
|
195
|
-
const hoverTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
196
|
-
|
|
197
|
-
const expandOnHover = props.sidebarProps?.expandOnHover !== false;
|
|
198
|
-
|
|
199
|
-
const handleNavbarMouseEnter = useCallback(() => {
|
|
200
|
-
if (collapsed && expandOnHover) {
|
|
201
|
-
hoverTimeoutRef.current = setTimeout(() => {
|
|
202
|
-
setIsHovering(true);
|
|
203
|
-
}, hoverDelay);
|
|
204
|
-
}
|
|
205
|
-
}, [collapsed, expandOnHover, hoverDelay]);
|
|
206
|
-
|
|
207
|
-
const handleNavbarMouseLeave = useCallback(() => {
|
|
208
|
-
if (hoverTimeoutRef.current) {
|
|
209
|
-
clearTimeout(hoverTimeoutRef.current);
|
|
210
|
-
hoverTimeoutRef.current = null;
|
|
211
|
-
}
|
|
212
|
-
setIsHovering(false);
|
|
213
|
-
}, []);
|
|
214
|
-
|
|
215
|
-
// Reset hover state when collapsed changes (e.g., when toggle button is clicked)
|
|
216
|
-
useEffect(() => {
|
|
217
|
-
if (collapsed) {
|
|
218
|
-
setIsHovering(false);
|
|
219
|
-
if (hoverTimeoutRef.current) {
|
|
220
|
-
clearTimeout(hoverTimeoutRef.current);
|
|
221
|
-
hoverTimeoutRef.current = null;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}, [collapsed]);
|
|
81
|
+
const { collapsedWidth, expandedWidth } = sidebar;
|
|
225
82
|
|
|
226
83
|
const shouldShowSidebar = () => {
|
|
227
84
|
if (props.noSidebarWhen?.paths) {
|
|
@@ -246,7 +103,7 @@ const DashboardShell = (props: DashboardShellProps) => {
|
|
|
246
103
|
setShowSidebar(shouldShowSidebar());
|
|
247
104
|
},
|
|
248
105
|
"react:transition:begin": () => {
|
|
249
|
-
setSidebar({ ...sidebar,
|
|
106
|
+
setSidebar({ ...sidebar, closed: true });
|
|
250
107
|
},
|
|
251
108
|
},
|
|
252
109
|
[sidebar],
|
|
@@ -264,55 +121,33 @@ const DashboardShell = (props: DashboardShellProps) => {
|
|
|
264
121
|
const hasSidebar = showSidebar && props.sidebarProps !== undefined;
|
|
265
122
|
const hasAppBar = props.appBarProps || props.header;
|
|
266
123
|
|
|
124
|
+
let footerElement = props.footer;
|
|
125
|
+
if (props.footerHeight) {
|
|
126
|
+
footerElement ??= <Flex h={props.footerHeight} />;
|
|
127
|
+
}
|
|
128
|
+
|
|
267
129
|
const hHeight = props.headerHeight ?? 60;
|
|
268
130
|
const fHeight = props.footerHeight ?? 24;
|
|
269
131
|
const headerHeight = hasAppBar ? hHeight : 0;
|
|
270
|
-
const footerHeight =
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
// When collapsed but hovering, show defaultWidth (not current width)
|
|
274
|
-
const isExpandedByHover = collapsed && isHovering;
|
|
275
|
-
const effectiveCollapsed = collapsed && !isHovering;
|
|
276
|
-
|
|
277
|
-
// Wrap onItemClick to collapse sidebar when clicking during hover-expansion
|
|
278
|
-
const handleSidebarItemClick = useCallback(
|
|
279
|
-
(item: SidebarMenuItem) => {
|
|
280
|
-
if (isExpandedByHover) {
|
|
281
|
-
setIsHovering(false);
|
|
282
|
-
}
|
|
283
|
-
props.sidebarProps?.onItemClick?.(item);
|
|
284
|
-
},
|
|
285
|
-
[isExpandedByHover, props.sidebarProps?.onItemClick],
|
|
286
|
-
);
|
|
287
|
-
const hoverWidth = Math.max(defaultWidth, collapsedWidth);
|
|
288
|
-
// When hovering, keep main content at collapsed width (sidebar overlays)
|
|
289
|
-
const sidebarWidth = hasSidebar
|
|
290
|
-
? effectiveCollapsed || isExpandedByHover
|
|
291
|
-
? collapsedWidth
|
|
292
|
-
: expandedWidth
|
|
293
|
-
: 0;
|
|
294
|
-
const canResize = props.sidebarResizable && !collapsed;
|
|
132
|
+
const footerHeight = footerElement ? fHeight : 0;
|
|
133
|
+
const navbarWidth = collapsed ? collapsedWidth : expandedWidth;
|
|
295
134
|
|
|
296
135
|
return (
|
|
297
136
|
<AppShell
|
|
298
|
-
layout={
|
|
137
|
+
layout={"alt"}
|
|
299
138
|
w={"100%"}
|
|
300
139
|
flex={1}
|
|
301
140
|
header={hasAppBar ? { height: hHeight } : undefined}
|
|
302
141
|
navbar={
|
|
303
142
|
hasSidebar
|
|
304
143
|
? {
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
? { base: collapsedWidth }
|
|
309
|
-
: { base: expandedWidth },
|
|
310
|
-
breakpoint: "sm",
|
|
311
|
-
collapsed: { mobile: !opened },
|
|
144
|
+
width: { base: navbarWidth },
|
|
145
|
+
breakpoint: "md",
|
|
146
|
+
collapsed: { mobile: sidebar.closed },
|
|
312
147
|
}
|
|
313
148
|
: undefined
|
|
314
149
|
}
|
|
315
|
-
footer={
|
|
150
|
+
footer={footerElement ? { height: fHeight } : undefined}
|
|
316
151
|
{...props.appShellProps}
|
|
317
152
|
>
|
|
318
153
|
{hasAppBar && (
|
|
@@ -326,22 +161,6 @@ const DashboardShell = (props: DashboardShellProps) => {
|
|
|
326
161
|
{hasSidebar && (
|
|
327
162
|
<AppShell.Navbar
|
|
328
163
|
className="alepha-sidebar-navbar"
|
|
329
|
-
data-resizing={isResizing}
|
|
330
|
-
data-hover-expanded={isExpandedByHover}
|
|
331
|
-
onMouseEnter={handleNavbarMouseEnter}
|
|
332
|
-
onMouseLeave={handleNavbarMouseLeave}
|
|
333
|
-
style={{
|
|
334
|
-
transform: collapseEffect.offset
|
|
335
|
-
? `translateX(${collapseEffect.offset}px)`
|
|
336
|
-
: undefined,
|
|
337
|
-
opacity: collapseEffect.opacity,
|
|
338
|
-
// When hovering, expand width visually as overlay
|
|
339
|
-
...(isExpandedByHover && {
|
|
340
|
-
width: hoverWidth,
|
|
341
|
-
zIndex: 200,
|
|
342
|
-
boxShadow: "var(--mantine-shadow-xl)",
|
|
343
|
-
}),
|
|
344
|
-
}}
|
|
345
164
|
{...props.appShellNavbarProps}
|
|
346
165
|
>
|
|
347
166
|
{props.navbarHeader ? (
|
|
@@ -354,11 +173,7 @@ const DashboardShell = (props: DashboardShellProps) => {
|
|
|
354
173
|
{props.navbarHeader}
|
|
355
174
|
</Flex>
|
|
356
175
|
) : null}
|
|
357
|
-
<Sidebar
|
|
358
|
-
{...(props.sidebarProps ?? {})}
|
|
359
|
-
collapsed={effectiveCollapsed}
|
|
360
|
-
onItemClick={handleSidebarItemClick}
|
|
361
|
-
/>
|
|
176
|
+
<Sidebar {...(props.sidebarProps ?? {})} collapsed={collapsed} />
|
|
362
177
|
{props.navbarFooter ? (
|
|
363
178
|
<Flex
|
|
364
179
|
style={{
|
|
@@ -369,46 +184,16 @@ const DashboardShell = (props: DashboardShellProps) => {
|
|
|
369
184
|
{props.navbarFooter}
|
|
370
185
|
</Flex>
|
|
371
186
|
) : null}
|
|
372
|
-
{(canResize || isExpandedByHover) && (
|
|
373
|
-
<Flex
|
|
374
|
-
pos="absolute"
|
|
375
|
-
right={-6}
|
|
376
|
-
top={0}
|
|
377
|
-
bottom={0}
|
|
378
|
-
w={12}
|
|
379
|
-
style={{
|
|
380
|
-
cursor: "col-resize",
|
|
381
|
-
userSelect: "none",
|
|
382
|
-
}}
|
|
383
|
-
onMouseDown={handleResizeStart}
|
|
384
|
-
/>
|
|
385
|
-
)}
|
|
386
187
|
</AppShell.Navbar>
|
|
387
188
|
)}
|
|
388
189
|
|
|
389
|
-
<AppShell.Main
|
|
390
|
-
|
|
391
|
-
data-resizing={isResizing}
|
|
392
|
-
{...props.appShellMainProps}
|
|
393
|
-
>
|
|
394
|
-
{props.container ? (
|
|
395
|
-
<Container
|
|
396
|
-
w={"100%"}
|
|
397
|
-
flex={1}
|
|
398
|
-
display="flex"
|
|
399
|
-
style={{ flexDirection: "column" }}
|
|
400
|
-
{...(typeof props.container === "boolean" ? {} : props.container)}
|
|
401
|
-
>
|
|
402
|
-
{props.children ?? <NestedView />}
|
|
403
|
-
</Container>
|
|
404
|
-
) : (
|
|
405
|
-
(props.children ?? <NestedView />)
|
|
406
|
-
)}
|
|
190
|
+
<AppShell.Main pos={"relative"} {...props.appShellMainProps}>
|
|
191
|
+
{props.children ?? <NestedView />}
|
|
407
192
|
</AppShell.Main>
|
|
408
193
|
|
|
409
|
-
{
|
|
194
|
+
{footerElement && (
|
|
410
195
|
<AppShell.Footer {...props.appShellFooterProps}>
|
|
411
|
-
{
|
|
196
|
+
{footerElement}
|
|
412
197
|
</AppShell.Footer>
|
|
413
198
|
)}
|
|
414
199
|
</AppShell>
|