@pablo2410/shared-ui 0.4.1 → 0.5.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/chunk-LTUYIBMA.js +5649 -0
- package/dist/chunk-LTUYIBMA.js.map +1 -0
- package/dist/layout/index.d.ts +35 -31
- package/dist/layout/index.js +205 -247
- package/dist/layout/index.js.map +1 -1
- package/dist/primitives/index.js +294 -5363
- package/dist/primitives/index.js.map +1 -1
- package/package.json +1 -1
package/dist/layout/index.d.ts
CHANGED
|
@@ -106,52 +106,56 @@ declare function useSidebarResize(config: {
|
|
|
106
106
|
};
|
|
107
107
|
|
|
108
108
|
interface DashboardLayoutUser {
|
|
109
|
-
name
|
|
109
|
+
name?: string;
|
|
110
110
|
email?: string;
|
|
111
111
|
role?: string;
|
|
112
112
|
avatarUrl?: string;
|
|
113
113
|
}
|
|
114
|
+
interface DashboardLayoutEnterprise {
|
|
115
|
+
name: string;
|
|
116
|
+
code?: string;
|
|
117
|
+
}
|
|
114
118
|
interface DashboardLayoutProps {
|
|
115
|
-
/** Service/module name
|
|
119
|
+
/** Service/module name shown in the sidebar brand header (e.g. "OEE Manager"). */
|
|
116
120
|
serviceName: string;
|
|
117
|
-
/**
|
|
121
|
+
/** Service icon (a lucide icon element), shown in the sidebar brand + header. */
|
|
118
122
|
serviceIcon?: ReactNode;
|
|
119
|
-
/**
|
|
123
|
+
/** Primary navigation sections. */
|
|
120
124
|
menuSections: MenuSection[];
|
|
121
|
-
/**
|
|
125
|
+
/** Admin-only navigation sections, rendered when `isAdmin` is true. */
|
|
126
|
+
adminSections?: MenuSection[];
|
|
127
|
+
/** Whether the current user may see `adminSections`. */
|
|
128
|
+
isAdmin?: boolean;
|
|
129
|
+
/** Current route (the app's router supplies this). */
|
|
122
130
|
activePath: string;
|
|
123
|
-
/**
|
|
131
|
+
/** Navigate handler (the app's router supplies this). */
|
|
124
132
|
onNavigate: (path: string) => void;
|
|
125
|
-
/**
|
|
133
|
+
/** Optional override for active-item detection. */
|
|
134
|
+
isActive?: (itemPath: string, activePath: string) => boolean;
|
|
135
|
+
/** URL for the "← Service Hub" link at the top of the nav (full-page nav). */
|
|
136
|
+
serviceHubUrl?: string;
|
|
137
|
+
/** Footer "Settings" route. Omit to hide the footer. */
|
|
138
|
+
settingsPath?: string;
|
|
139
|
+
/** Authenticated user (drives the header user menu). */
|
|
126
140
|
user?: DashboardLayoutUser | null;
|
|
127
|
-
/**
|
|
128
|
-
isAuthenticated?: boolean;
|
|
129
|
-
/** Whether auth state is loading */
|
|
130
|
-
isLoading?: boolean;
|
|
131
|
-
/** Logout handler */
|
|
141
|
+
/** Sign-out handler invoked from the user menu. */
|
|
132
142
|
onLogout?: () => void;
|
|
133
|
-
/**
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
showBackToPortal?: boolean;
|
|
137
|
-
/** Portal URL for "Back to Portal" link */
|
|
138
|
-
portalUrl?: string;
|
|
139
|
-
/** Whether user has admin role */
|
|
140
|
-
isAdmin?: boolean;
|
|
141
|
-
/** Admin menu sections (shown only for admins) */
|
|
142
|
-
adminSections?: MenuSection[];
|
|
143
|
-
/** Optional hierarchy navigator to render in the sidebar */
|
|
143
|
+
/** "User Settings" target in the user menu (full-page nav). */
|
|
144
|
+
userSettingsUrl?: string;
|
|
145
|
+
/** App-provided hierarchy navigator rendered in the header breadcrumb slot. */
|
|
144
146
|
hierarchyNavigator?: ReactNode;
|
|
145
|
-
/**
|
|
147
|
+
/** Selected enterprise — drives the header enterprise badge. */
|
|
148
|
+
enterprise?: DashboardLayoutEnterprise | null;
|
|
149
|
+
/** App-provided reporting toolbar rendered on the right of the header. */
|
|
146
150
|
reportingToolbar?: ReactNode;
|
|
147
|
-
/**
|
|
148
|
-
|
|
149
|
-
/**
|
|
151
|
+
/** Whether the sidebar starts expanded. Defaults to `!isMobile`. */
|
|
152
|
+
defaultOpen?: boolean;
|
|
153
|
+
/** Extra footer rendered fixed at the bottom (e.g. a debug/health bar). */
|
|
154
|
+
footer?: ReactNode;
|
|
155
|
+
/** Main content. */
|
|
150
156
|
children: ReactNode;
|
|
151
|
-
/** Additional CSS class for the outer container */
|
|
152
|
-
className?: string;
|
|
153
157
|
}
|
|
154
|
-
declare function DashboardLayout(
|
|
158
|
+
declare function DashboardLayout(props: DashboardLayoutProps): react_jsx_runtime.JSX.Element;
|
|
155
159
|
|
|
156
160
|
interface DashboardLayoutSkeletonProps {
|
|
157
161
|
className?: string;
|
|
@@ -353,4 +357,4 @@ declare const SERVICE_CONFIGS: {
|
|
|
353
357
|
};
|
|
354
358
|
type ServiceKey = keyof typeof SERVICE_CONFIGS;
|
|
355
359
|
|
|
356
|
-
export { DashboardLayout, type DashboardLayoutProps, DashboardLayoutSkeleton, type DashboardLayoutSkeletonProps, type DashboardLayoutUser, FOOTER_SERVICES, type FooterService, type MenuItem, type MenuItemConfig, type MenuSection, type MenuSectionConfig, SERVICE_CONFIGS, type ServiceConfig, ServiceFooter, type ServiceFooterProps, type ServiceKey, type ServiceLayoutConfig, SharedFooter, type SharedFooterProps, SharedPageHeader, type SharedPageHeaderProps, type SharedSidebarConfig, type SharedSidebarProps, type SharedSidebarConfig as SidebarConfig, actionManagerConfig, businessHubConfig, defineServiceLayout, getInitials, isAdminRole, isMenuItemActive, oeeManagerConfig, policyDeploymentConfig, sqdcpConfig, useSidebarResize };
|
|
360
|
+
export { DashboardLayout, type DashboardLayoutEnterprise, type DashboardLayoutProps, DashboardLayoutSkeleton, type DashboardLayoutSkeletonProps, type DashboardLayoutUser, FOOTER_SERVICES, type FooterService, type MenuItem, type MenuItemConfig, type MenuSection, type MenuSectionConfig, SERVICE_CONFIGS, type ServiceConfig, ServiceFooter, type ServiceFooterProps, type ServiceKey, type ServiceLayoutConfig, SharedFooter, type SharedFooterProps, SharedPageHeader, type SharedPageHeaderProps, type SharedSidebarConfig, type SharedSidebarProps, type SharedSidebarConfig as SidebarConfig, actionManagerConfig, businessHubConfig, defineServiceLayout, getInitials, isAdminRole, isMenuItemActive, oeeManagerConfig, policyDeploymentConfig, sqdcpConfig, useSidebarResize };
|
package/dist/layout/index.js
CHANGED
|
@@ -1,6 +1,27 @@
|
|
|
1
1
|
import {
|
|
2
2
|
cn
|
|
3
3
|
} from "../chunk-JT3XLKKD.js";
|
|
4
|
+
import {
|
|
5
|
+
Avatar,
|
|
6
|
+
AvatarFallback,
|
|
7
|
+
DropdownMenu,
|
|
8
|
+
DropdownMenuContent,
|
|
9
|
+
DropdownMenuItem,
|
|
10
|
+
DropdownMenuSeparator,
|
|
11
|
+
DropdownMenuTrigger,
|
|
12
|
+
Sidebar,
|
|
13
|
+
SidebarContent,
|
|
14
|
+
SidebarFooter,
|
|
15
|
+
SidebarHeader,
|
|
16
|
+
SidebarInset,
|
|
17
|
+
SidebarMenu,
|
|
18
|
+
SidebarMenuButton,
|
|
19
|
+
SidebarMenuItem,
|
|
20
|
+
SidebarProvider,
|
|
21
|
+
SidebarTrigger,
|
|
22
|
+
useIsMobile,
|
|
23
|
+
useSidebar
|
|
24
|
+
} from "../chunk-LTUYIBMA.js";
|
|
4
25
|
|
|
5
26
|
// src/layout/SharedSidebar.tsx
|
|
6
27
|
import { useEffect, useRef, useState } from "react";
|
|
@@ -64,278 +85,215 @@ function useSidebarResize(config) {
|
|
|
64
85
|
}
|
|
65
86
|
|
|
66
87
|
// src/layout/DashboardLayout.tsx
|
|
67
|
-
import {
|
|
68
|
-
ChevronLeft,
|
|
69
|
-
ChevronRight,
|
|
70
|
-
LogOut,
|
|
71
|
-
Menu,
|
|
72
|
-
X,
|
|
73
|
-
ExternalLink
|
|
74
|
-
} from "lucide-react";
|
|
75
|
-
import {
|
|
76
|
-
useState as useState2,
|
|
77
|
-
useCallback
|
|
78
|
-
} from "react";
|
|
88
|
+
import { ArrowLeft, LogOut, PanelLeft, Settings } from "lucide-react";
|
|
79
89
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
90
|
+
var DEFAULT_SERVICE_HUB_URL = "https://portal.oplytics.digital/app";
|
|
91
|
+
var DEFAULT_USER_SETTINGS_URL = "https://portal.oplytics.digital/account";
|
|
92
|
+
function UserMenu({
|
|
93
|
+
user,
|
|
94
|
+
onLogout,
|
|
95
|
+
userSettingsUrl = DEFAULT_USER_SETTINGS_URL
|
|
85
96
|
}) {
|
|
86
|
-
const
|
|
87
|
-
return /* @__PURE__ */ jsxs(
|
|
88
|
-
"button",
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
"
|
|
95
|
-
|
|
96
|
-
|
|
97
|
+
const initials = (user.name || "U").split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2);
|
|
98
|
+
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
99
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs("button", { className: "flex items-center gap-2 rounded-md px-2 py-1 hover:bg-[#1E2738] transition-colors outline-none focus-visible:ring-1 focus-visible:ring-[#8C34E9]", children: [
|
|
100
|
+
/* @__PURE__ */ jsx(Avatar, { className: "h-7 w-7 border border-[#2A2A3E]", children: /* @__PURE__ */ jsx(AvatarFallback, { className: "text-[10px] font-medium bg-[#8C34E9]/20 text-[#C084FC]", children: initials }) }),
|
|
101
|
+
/* @__PURE__ */ jsx("span", { className: "hidden md:block text-xs text-[#E2E8F0] truncate max-w-[100px]", children: user.name || "User" })
|
|
102
|
+
] }) }),
|
|
103
|
+
/* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", className: "w-48 bg-[#0D1220] border-[#1E2738]", children: [
|
|
104
|
+
/* @__PURE__ */ jsxs("div", { className: "px-3 py-2 border-b border-[#1E2738]", children: [
|
|
105
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-[#E2E8F0] truncate", children: user.name }),
|
|
106
|
+
/* @__PURE__ */ jsx("p", { className: "text-[10px] text-[#596475] truncate", children: user.role })
|
|
107
|
+
] }),
|
|
108
|
+
/* @__PURE__ */ jsxs(
|
|
109
|
+
DropdownMenuItem,
|
|
110
|
+
{
|
|
111
|
+
onClick: () => {
|
|
112
|
+
window.location.href = userSettingsUrl;
|
|
113
|
+
},
|
|
114
|
+
className: "text-xs text-[#E2E8F0] hover:bg-[#1E2738] cursor-pointer focus:bg-[#1E2738]",
|
|
115
|
+
children: [
|
|
116
|
+
/* @__PURE__ */ jsx(Settings, { className: "h-3.5 w-3.5 mr-2 text-[#8890A0]" }),
|
|
117
|
+
"User Settings"
|
|
118
|
+
]
|
|
119
|
+
}
|
|
97
120
|
),
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
121
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, { className: "bg-[#1E2738]" }),
|
|
122
|
+
/* @__PURE__ */ jsxs(
|
|
123
|
+
DropdownMenuItem,
|
|
124
|
+
{
|
|
125
|
+
onClick: () => onLogout?.(),
|
|
126
|
+
className: "text-xs text-[#EF4444] hover:bg-[#EF4444]/10 cursor-pointer focus:bg-[#EF4444]/10 focus:text-[#EF4444]",
|
|
127
|
+
children: [
|
|
128
|
+
/* @__PURE__ */ jsx(LogOut, { className: "h-3.5 w-3.5 mr-2" }),
|
|
129
|
+
"Sign Out"
|
|
130
|
+
]
|
|
131
|
+
}
|
|
132
|
+
)
|
|
133
|
+
] })
|
|
134
|
+
] });
|
|
135
|
+
}
|
|
136
|
+
function EnterpriseBadge({ enterprise }) {
|
|
137
|
+
if (!enterprise) return null;
|
|
138
|
+
return /* @__PURE__ */ jsxs("div", { className: "hidden lg:flex items-center gap-1.5 px-2 py-1 rounded-md bg-[#8C34E9]/10 border border-[#8C34E9]/20", children: [
|
|
139
|
+
/* @__PURE__ */ jsx("div", { className: "h-4 w-4 rounded-sm bg-[#8C34E9]/30 flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "text-[8px] font-bold text-[#C084FC]", children: enterprise.name.charAt(0).toUpperCase() }) }),
|
|
140
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium text-[#C084FC] truncate max-w-[80px]", children: enterprise.code || enterprise.name })
|
|
141
|
+
] });
|
|
106
142
|
}
|
|
107
|
-
function
|
|
143
|
+
function NavSection({
|
|
108
144
|
section,
|
|
109
|
-
|
|
110
|
-
|
|
145
|
+
marginTop,
|
|
146
|
+
isCollapsed,
|
|
147
|
+
resolveActive,
|
|
111
148
|
onNavigate
|
|
112
149
|
}) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
section.items.map((item) =>
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
150
|
+
const label = section.title ?? section.label;
|
|
151
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
152
|
+
label && /* @__PURE__ */ jsx("div", { className: cn("px-4 py-2", marginTop && "mt-2"), children: !isCollapsed && /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wider", children: label }) }),
|
|
153
|
+
/* @__PURE__ */ jsx(SidebarMenu, { className: "px-2 py-1", children: section.items.map((item) => {
|
|
154
|
+
const active = resolveActive(item.path);
|
|
155
|
+
const Icon = item.icon;
|
|
156
|
+
return /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(
|
|
157
|
+
SidebarMenuButton,
|
|
158
|
+
{
|
|
159
|
+
isActive: active,
|
|
160
|
+
onClick: () => onNavigate(item.path),
|
|
161
|
+
tooltip: item.label,
|
|
162
|
+
className: "h-10 transition-all font-normal",
|
|
163
|
+
children: [
|
|
164
|
+
Icon && /* @__PURE__ */ jsx(Icon, { className: cn("h-4 w-4", active && "text-primary") }),
|
|
165
|
+
/* @__PURE__ */ jsx("span", { children: item.label })
|
|
166
|
+
]
|
|
167
|
+
}
|
|
168
|
+
) }, item.path);
|
|
169
|
+
}) })
|
|
126
170
|
] });
|
|
127
171
|
}
|
|
128
|
-
function
|
|
129
|
-
user,
|
|
130
|
-
collapsed,
|
|
131
|
-
onLogout
|
|
132
|
-
}) {
|
|
133
|
-
const initials = getInitials(user.name);
|
|
134
|
-
return /* @__PURE__ */ jsxs(
|
|
135
|
-
"div",
|
|
136
|
-
{
|
|
137
|
-
className: cn(
|
|
138
|
-
"border-t border-[#1E2738] p-3",
|
|
139
|
-
collapsed ? "flex flex-col items-center gap-2" : "flex items-center gap-3"
|
|
140
|
-
),
|
|
141
|
-
children: [
|
|
142
|
-
user.avatarUrl ? /* @__PURE__ */ jsx(
|
|
143
|
-
"img",
|
|
144
|
-
{
|
|
145
|
-
src: user.avatarUrl,
|
|
146
|
-
alt: user.name,
|
|
147
|
-
className: "h-8 w-8 rounded-full shrink-0 object-cover"
|
|
148
|
-
}
|
|
149
|
-
) : /* @__PURE__ */ jsx("div", { className: "h-8 w-8 rounded-full shrink-0 bg-[#8C34E9]/20 flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-[#A855F7]", children: initials }) }),
|
|
150
|
-
!collapsed && /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
151
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-[#E2E8F0] truncate", children: user.name }),
|
|
152
|
-
user.email && /* @__PURE__ */ jsx("p", { className: "text-[10px] text-[#596475] truncate", children: user.email }),
|
|
153
|
-
user.role && /* @__PURE__ */ jsx("p", { className: "text-[10px] text-[#8C34E9] capitalize", children: user.role })
|
|
154
|
-
] }),
|
|
155
|
-
onLogout && /* @__PURE__ */ jsx(
|
|
156
|
-
"button",
|
|
157
|
-
{
|
|
158
|
-
onClick: onLogout,
|
|
159
|
-
className: cn(
|
|
160
|
-
"shrink-0 p-1.5 rounded-md",
|
|
161
|
-
"text-[#596475] hover:text-[#E2E8F0] hover:bg-[#1E2738]",
|
|
162
|
-
"transition-colors cursor-pointer",
|
|
163
|
-
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-[#8C34E9]"
|
|
164
|
-
),
|
|
165
|
-
title: "Sign out",
|
|
166
|
-
children: /* @__PURE__ */ jsx(LogOut, { className: "h-4 w-4" })
|
|
167
|
-
}
|
|
168
|
-
)
|
|
169
|
-
]
|
|
170
|
-
}
|
|
171
|
-
);
|
|
172
|
-
}
|
|
173
|
-
function DashboardLayout({
|
|
172
|
+
function DashboardShell({
|
|
174
173
|
serviceName,
|
|
175
174
|
serviceIcon,
|
|
176
175
|
menuSections,
|
|
176
|
+
adminSections,
|
|
177
|
+
isAdmin = false,
|
|
177
178
|
activePath,
|
|
178
179
|
onNavigate,
|
|
180
|
+
isActive,
|
|
181
|
+
serviceHubUrl = DEFAULT_SERVICE_HUB_URL,
|
|
182
|
+
settingsPath,
|
|
179
183
|
user,
|
|
180
|
-
isAuthenticated = true,
|
|
181
|
-
isLoading = false,
|
|
182
184
|
onLogout,
|
|
183
|
-
|
|
184
|
-
showBackToPortal = false,
|
|
185
|
-
portalUrl = "https://portal.oplytics.digital",
|
|
186
|
-
isAdmin = false,
|
|
187
|
-
adminSections,
|
|
185
|
+
userSettingsUrl,
|
|
188
186
|
hierarchyNavigator,
|
|
187
|
+
enterprise,
|
|
189
188
|
reportingToolbar,
|
|
190
|
-
|
|
191
|
-
children
|
|
192
|
-
className
|
|
189
|
+
footer,
|
|
190
|
+
children
|
|
193
191
|
}) {
|
|
194
|
-
const
|
|
195
|
-
const
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
});
|
|
202
|
-
const toggleCollapse = useCallback(() => setCollapsed((c) => !c), []);
|
|
203
|
-
const toggleMobile = useCallback(() => setMobileOpen((o) => !o), []);
|
|
204
|
-
const closeMobile = useCallback(() => setMobileOpen(false), []);
|
|
205
|
-
const handleNavigate = useCallback(
|
|
206
|
-
(path) => {
|
|
207
|
-
onNavigate(path);
|
|
208
|
-
closeMobile();
|
|
209
|
-
},
|
|
210
|
-
[onNavigate, closeMobile]
|
|
211
|
-
);
|
|
212
|
-
if (isLoading && loadingSkeleton) {
|
|
213
|
-
return /* @__PURE__ */ jsx(Fragment, { children: loadingSkeleton });
|
|
214
|
-
}
|
|
215
|
-
if (!isLoading && !isAuthenticated && onLogin) {
|
|
216
|
-
onLogin();
|
|
217
|
-
return loadingSkeleton ? /* @__PURE__ */ jsx(Fragment, { children: loadingSkeleton }) : null;
|
|
218
|
-
}
|
|
219
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("min-h-screen flex", "bg-[#0A0E1A]", className), children: [
|
|
220
|
-
mobileOpen && /* @__PURE__ */ jsx(
|
|
221
|
-
"div",
|
|
222
|
-
{
|
|
223
|
-
className: "fixed inset-0 z-40 bg-black/60 lg:hidden",
|
|
224
|
-
onClick: closeMobile
|
|
225
|
-
}
|
|
226
|
-
),
|
|
227
|
-
/* @__PURE__ */ jsxs(
|
|
228
|
-
"aside",
|
|
229
|
-
{
|
|
230
|
-
className: cn(
|
|
231
|
-
"fixed top-0 left-0 h-full z-50 flex flex-col",
|
|
232
|
-
"bg-[#0D1220] border-r border-[#1E2738]",
|
|
233
|
-
"transition-all duration-300",
|
|
234
|
-
// Mobile: slide in/out
|
|
235
|
-
"lg:relative lg:translate-x-0",
|
|
236
|
-
mobileOpen ? "translate-x-0" : "-translate-x-full"
|
|
237
|
-
),
|
|
238
|
-
style: { width: sidebarWidth },
|
|
239
|
-
children: [
|
|
240
|
-
/* @__PURE__ */ jsxs("div", { className: cn(
|
|
241
|
-
"flex items-center gap-2 p-4 border-b border-[#1E2738]",
|
|
242
|
-
collapsed && "justify-center px-2"
|
|
243
|
-
), children: [
|
|
244
|
-
serviceIcon && /* @__PURE__ */ jsx("div", { className: "shrink-0 text-[#8C34E9]", children: serviceIcon }),
|
|
245
|
-
!collapsed && /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-[#E2E8F0] truncate font-[Montserrat,sans-serif]", children: serviceName }),
|
|
246
|
-
/* @__PURE__ */ jsx(
|
|
247
|
-
"button",
|
|
248
|
-
{
|
|
249
|
-
onClick: toggleCollapse,
|
|
250
|
-
className: cn(
|
|
251
|
-
"hidden lg:flex shrink-0 p-1 rounded-md ml-auto",
|
|
252
|
-
"text-[#596475] hover:text-[#E2E8F0] hover:bg-[#1E2738]",
|
|
253
|
-
"transition-colors cursor-pointer",
|
|
254
|
-
collapsed && "ml-0"
|
|
255
|
-
),
|
|
256
|
-
children: collapsed ? /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" })
|
|
257
|
-
}
|
|
258
|
-
),
|
|
259
|
-
/* @__PURE__ */ jsx(
|
|
260
|
-
"button",
|
|
261
|
-
{
|
|
262
|
-
onClick: closeMobile,
|
|
263
|
-
className: "lg:hidden shrink-0 p-1 rounded-md ml-auto text-[#596475] hover:text-[#E2E8F0]",
|
|
264
|
-
children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
|
|
265
|
-
}
|
|
266
|
-
)
|
|
267
|
-
] }),
|
|
268
|
-
hierarchyNavigator && !collapsed && /* @__PURE__ */ jsx("div", { className: "px-3 py-2 border-b border-[#1E2738]", children: hierarchyNavigator }),
|
|
269
|
-
showBackToPortal && /* @__PURE__ */ jsx("div", { className: cn("px-3 py-2", collapsed && "px-2"), children: /* @__PURE__ */ jsxs(
|
|
270
|
-
"a",
|
|
271
|
-
{
|
|
272
|
-
href: portalUrl,
|
|
273
|
-
className: cn(
|
|
274
|
-
"flex items-center gap-2 px-3 py-1.5 rounded-md text-xs",
|
|
275
|
-
"text-[#596475] hover:text-[#8890A0] hover:bg-[#1E2738]",
|
|
276
|
-
"transition-colors",
|
|
277
|
-
collapsed && "justify-center px-2"
|
|
278
|
-
),
|
|
279
|
-
children: [
|
|
280
|
-
/* @__PURE__ */ jsx(ExternalLink, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
281
|
-
!collapsed && /* @__PURE__ */ jsx("span", { children: "Back to Portal" })
|
|
282
|
-
]
|
|
283
|
-
}
|
|
284
|
-
) }),
|
|
285
|
-
/* @__PURE__ */ jsxs("nav", { className: "flex-1 overflow-y-auto px-3 py-3 space-y-4", children: [
|
|
286
|
-
menuSections.map((section, idx) => /* @__PURE__ */ jsx(
|
|
287
|
-
SidebarSection,
|
|
288
|
-
{
|
|
289
|
-
section,
|
|
290
|
-
activePath,
|
|
291
|
-
collapsed,
|
|
292
|
-
onNavigate: handleNavigate
|
|
293
|
-
},
|
|
294
|
-
section.title || `section-${idx}`
|
|
295
|
-
)),
|
|
296
|
-
isAdmin && adminSections && adminSections.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
297
|
-
!collapsed && /* @__PURE__ */ jsx("div", { className: "mx-3 border-t border-[#1E2738] my-2" }),
|
|
298
|
-
adminSections.map((section, idx) => /* @__PURE__ */ jsx(
|
|
299
|
-
SidebarSection,
|
|
300
|
-
{
|
|
301
|
-
section,
|
|
302
|
-
activePath,
|
|
303
|
-
collapsed,
|
|
304
|
-
onNavigate: handleNavigate
|
|
305
|
-
},
|
|
306
|
-
section.title || `admin-${idx}`
|
|
307
|
-
))
|
|
308
|
-
] })
|
|
309
|
-
] }),
|
|
310
|
-
user && /* @__PURE__ */ jsx(
|
|
311
|
-
UserProfile,
|
|
312
|
-
{
|
|
313
|
-
user,
|
|
314
|
-
collapsed,
|
|
315
|
-
onLogout
|
|
316
|
-
}
|
|
317
|
-
)
|
|
318
|
-
]
|
|
319
|
-
}
|
|
320
|
-
),
|
|
321
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col min-w-0", children: [
|
|
322
|
-
/* @__PURE__ */ jsxs("header", { className: "lg:hidden flex items-center gap-3 px-4 py-2.5 border-b border-[#1E2738] bg-[#0D1220]", children: [
|
|
192
|
+
const { toggleSidebar, state } = useSidebar();
|
|
193
|
+
const isCollapsed = state === "collapsed";
|
|
194
|
+
const navigate = onNavigate;
|
|
195
|
+
const resolveActive = (path) => isActive ? isActive(path, activePath) : isMenuItemActive(path, activePath);
|
|
196
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
197
|
+
/* @__PURE__ */ jsxs(Sidebar, { collapsible: "icon", className: "border-r-0", children: [
|
|
198
|
+
/* @__PURE__ */ jsx(SidebarHeader, { className: "h-16 justify-center", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 px-2 transition-all w-full", children: [
|
|
323
199
|
/* @__PURE__ */ jsx(
|
|
324
200
|
"button",
|
|
325
201
|
{
|
|
326
|
-
onClick:
|
|
327
|
-
className: "
|
|
328
|
-
|
|
202
|
+
onClick: toggleSidebar,
|
|
203
|
+
className: "h-8 w-8 flex items-center justify-center hover:bg-accent rounded-lg transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-ring shrink-0",
|
|
204
|
+
"aria-label": "Toggle navigation",
|
|
205
|
+
children: /* @__PURE__ */ jsx(PanelLeft, { className: "h-4 w-4 text-muted-foreground" })
|
|
329
206
|
}
|
|
330
207
|
),
|
|
331
|
-
/* @__PURE__ */
|
|
332
|
-
|
|
208
|
+
!isCollapsed ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [
|
|
209
|
+
serviceIcon && /* @__PURE__ */ jsx("span", { className: "text-[#8C34E9] shrink-0", children: serviceIcon }),
|
|
210
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold tracking-tight truncate", children: serviceName })
|
|
211
|
+
] }) : null
|
|
212
|
+
] }) }),
|
|
213
|
+
/* @__PURE__ */ jsxs(SidebarContent, { className: "gap-0", children: [
|
|
214
|
+
serviceHubUrl && /* @__PURE__ */ jsx(SidebarMenu, { className: "px-2 pt-2 pb-1", children: /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(
|
|
215
|
+
SidebarMenuButton,
|
|
216
|
+
{
|
|
217
|
+
onClick: () => {
|
|
218
|
+
window.location.href = serviceHubUrl;
|
|
219
|
+
},
|
|
220
|
+
tooltip: "Back to Service Hub",
|
|
221
|
+
className: "h-10 transition-all font-normal text-muted-foreground hover:text-foreground",
|
|
222
|
+
children: [
|
|
223
|
+
/* @__PURE__ */ jsx(ArrowLeft, { className: "h-4 w-4" }),
|
|
224
|
+
/* @__PURE__ */ jsx("span", { children: "Service Hub" })
|
|
225
|
+
]
|
|
226
|
+
}
|
|
227
|
+
) }) }),
|
|
228
|
+
menuSections.map((section, i) => /* @__PURE__ */ jsx(
|
|
229
|
+
NavSection,
|
|
230
|
+
{
|
|
231
|
+
section,
|
|
232
|
+
isCollapsed,
|
|
233
|
+
resolveActive,
|
|
234
|
+
onNavigate: navigate
|
|
235
|
+
},
|
|
236
|
+
section.title ?? section.label ?? `section-${i}`
|
|
237
|
+
)),
|
|
238
|
+
isAdmin && adminSections?.map((section, i) => /* @__PURE__ */ jsx(
|
|
239
|
+
NavSection,
|
|
240
|
+
{
|
|
241
|
+
section,
|
|
242
|
+
marginTop: true,
|
|
243
|
+
isCollapsed,
|
|
244
|
+
resolveActive,
|
|
245
|
+
onNavigate: navigate
|
|
246
|
+
},
|
|
247
|
+
section.title ?? section.label ?? `admin-${i}`
|
|
248
|
+
))
|
|
333
249
|
] }),
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
250
|
+
settingsPath && /* @__PURE__ */ jsx(SidebarFooter, { className: "p-2", children: /* @__PURE__ */ jsx(SidebarMenu, { children: /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(
|
|
251
|
+
SidebarMenuButton,
|
|
252
|
+
{
|
|
253
|
+
onClick: () => navigate(settingsPath),
|
|
254
|
+
tooltip: "Settings",
|
|
255
|
+
className: "h-10 transition-all font-normal text-muted-foreground hover:text-foreground",
|
|
256
|
+
children: [
|
|
257
|
+
/* @__PURE__ */ jsx(Settings, { className: "h-4 w-4" }),
|
|
258
|
+
/* @__PURE__ */ jsx("span", { children: "Settings" })
|
|
259
|
+
]
|
|
260
|
+
}
|
|
261
|
+
) }) }) })
|
|
262
|
+
] }),
|
|
263
|
+
/* @__PURE__ */ jsxs(SidebarInset, { children: [
|
|
264
|
+
/* @__PURE__ */ jsxs(
|
|
265
|
+
"header",
|
|
266
|
+
{
|
|
267
|
+
className: cn(
|
|
268
|
+
"flex items-center justify-between h-14 px-4",
|
|
269
|
+
"bg-[#0D1220]/95 border-b border-[#1E2738]",
|
|
270
|
+
"backdrop-blur supports-[backdrop-filter]:backdrop-blur",
|
|
271
|
+
"sticky top-0 z-40"
|
|
272
|
+
),
|
|
273
|
+
children: [
|
|
274
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: [
|
|
275
|
+
/* @__PURE__ */ jsx(SidebarTrigger, { className: "h-9 w-9 rounded-lg bg-background shrink-0 md:hidden" }),
|
|
276
|
+
serviceIcon && /* @__PURE__ */ jsx("span", { className: "text-[#8C34E9] shrink-0 hidden sm:block", children: serviceIcon }),
|
|
277
|
+
hierarchyNavigator && /* @__PURE__ */ jsx("div", { className: "min-w-0 overflow-x-auto scrollbar-none", children: hierarchyNavigator })
|
|
278
|
+
] }),
|
|
279
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [
|
|
280
|
+
reportingToolbar,
|
|
281
|
+
/* @__PURE__ */ jsx(EnterpriseBadge, { enterprise }),
|
|
282
|
+
/* @__PURE__ */ jsx("div", { className: "w-px h-6 bg-[#1E2738] hidden md:block" }),
|
|
283
|
+
user && /* @__PURE__ */ jsx(UserMenu, { user, onLogout, userSettingsUrl })
|
|
284
|
+
] })
|
|
285
|
+
]
|
|
286
|
+
}
|
|
287
|
+
),
|
|
288
|
+
/* @__PURE__ */ jsx("main", { className: "flex-1 p-4 md:p-6 pb-14", children })
|
|
289
|
+
] }),
|
|
290
|
+
footer
|
|
337
291
|
] });
|
|
338
292
|
}
|
|
293
|
+
function DashboardLayout(props) {
|
|
294
|
+
const isMobile = useIsMobile();
|
|
295
|
+
return /* @__PURE__ */ jsx(SidebarProvider, { defaultOpen: props.defaultOpen ?? !isMobile, children: /* @__PURE__ */ jsx(DashboardShell, { ...props }) });
|
|
296
|
+
}
|
|
339
297
|
|
|
340
298
|
// src/layout/DashboardLayoutSkeleton.tsx
|
|
341
299
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
@@ -398,7 +356,7 @@ function DashboardLayoutSkeleton({ className }) {
|
|
|
398
356
|
}
|
|
399
357
|
|
|
400
358
|
// src/layout/SharedPageHeader.tsx
|
|
401
|
-
import { ChevronLeft
|
|
359
|
+
import { ChevronLeft } from "lucide-react";
|
|
402
360
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
403
361
|
function SharedPageHeader({
|
|
404
362
|
title,
|
|
@@ -436,7 +394,7 @@ function SharedPageHeader({
|
|
|
436
394
|
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-[#8C34E9]"
|
|
437
395
|
),
|
|
438
396
|
"aria-label": "Go back",
|
|
439
|
-
children: /* @__PURE__ */ jsx3(
|
|
397
|
+
children: /* @__PURE__ */ jsx3(ChevronLeft, { className: compact ? "h-4 w-4" : "h-5 w-5" })
|
|
440
398
|
}
|
|
441
399
|
),
|
|
442
400
|
icon && /* @__PURE__ */ jsx3("div", { className: "shrink-0 text-[#8C34E9]", children: icon }),
|