@eintrek/erp-shell 0.1.48 → 0.1.50

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/index.d.ts CHANGED
@@ -21,7 +21,7 @@ export { OrganizationSwitcher, type OrganizationSwitcherProps, type Organization
21
21
  export { SidebarHeader } from "./navigation/sidebar-header";
22
22
  export { AppSidebar, type AppSidebarProps } from "./navigation/app-sidebar";
23
23
  export { AppLayoutShell, type AppLayoutShellProps, type AppLayoutShellOrganization, } from "./navigation/app-layout-shell";
24
- export { type ShellChrome, WORKSPACE_HEADER_VARS } from "./navigation/chrome";
24
+ export { type ShellChrome, type WorkspaceHeaderTone, WORKSPACE_HEADER_VARS, WORKSPACE_LIGHT_HEADER_VARS, } from "./navigation/chrome";
25
25
  export { WorkspaceBrand, type WorkspaceBrandProps } from "./navigation/workspace-brand";
26
26
  export { SidebarHelpCard, SidebarHelpLink, type SidebarHelpCardProps, type SidebarHelpLinkProps, } from "./navigation/sidebar-help-card";
27
27
  export { AccessDenied, type AccessDeniedProps } from "./auth/access-denied";
package/dist/index.esm.js CHANGED
@@ -1071,7 +1071,7 @@ function samePage(pathname, url) {
1071
1071
  const strip = (p) => (p.length > 1 ? p.replace(/\/+$/, "") : p);
1072
1072
  return strip(pathname) === strip(url);
1073
1073
  }
1074
- function NavMain({ items, orgCode, closeOnNavigation = false, approvalCounts, chrome = "brand", }) {
1074
+ function NavMain({ items, orgCode, closeOnNavigation = false, approvalCounts, chrome = "brand", highlightActiveModule = false, }) {
1075
1075
  const workspace = chrome === "workspace";
1076
1076
  const params = useParams();
1077
1077
  const pathname = usePathname();
@@ -1103,8 +1103,9 @@ function NavMain({ items, orgCode, closeOnNavigation = false, approvalCounts, ch
1103
1103
  isPathActive(pathname, subPage.url)));
1104
1104
  // Parent only active when path matches its URL exactly AND no child
1105
1105
  // is active (so parent+child don't both light up).
1106
- const isItemActive = (workspace ? samePage(pathname, itemUrl) : pathname === itemUrl) &&
1107
- !hasActiveSubItem;
1106
+ const isItemActive = (highlightActiveModule && !item.subModules?.length && !!item.isActive) ||
1107
+ ((workspace ? samePage(pathname, itemUrl) : pathname === itemUrl) &&
1108
+ !hasActiveSubItem);
1108
1109
  return { itemUrl, activeSubItemUrl, hasActiveSubItem, isItemActive };
1109
1110
  });
1110
1111
  // A group opens when its page becomes current and otherwise stays as the
@@ -1192,7 +1193,7 @@ function OrgMark({ logoUrl, size = "md", }) {
1192
1193
  const box = size === "sm"
1193
1194
  ? "flex size-6 items-center justify-center rounded-md border overflow-hidden bg-background"
1194
1195
  : size === "header"
1195
- ? "flex aspect-square size-8 shrink-0 items-center justify-center rounded-[9px] border border-[color:color-mix(in_oklab,var(--header-fg,currentColor)_28%,transparent)] bg-[color-mix(in_oklab,var(--header-fg,currentColor)_10%,transparent)] text-[var(--header-fg,currentColor)] overflow-hidden max-sm:size-7"
1196
+ ? "flex aspect-square size-8 shrink-0 items-center justify-center rounded-[9px] border border-[color:var(--header-mark-border,color-mix(in_oklab,var(--header-fg,currentColor)_28%,transparent))] bg-[var(--header-mark-bg,color-mix(in_oklab,var(--header-fg,currentColor)_10%,transparent))] text-[var(--header-mark-fg,var(--header-fg,currentColor))] overflow-hidden max-sm:size-7"
1196
1197
  : "flex aspect-square size-8 shrink-0 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground overflow-hidden";
1197
1198
  const icon = size === "sm" ? "size-3.5 shrink-0" : "size-4";
1198
1199
  if (logoUrl && !failed) {
@@ -1263,7 +1264,7 @@ function SidebarHeader({ children, className }) {
1263
1264
  return jsx("div", { className: cn("px-2 py-3", className), children: children });
1264
1265
  }
1265
1266
 
1266
- function AppSidebar({ modules, tools, activeModule, orgCode, approvalCounts, closeOnNavigation = false, header, footer, bottom, chrome = "brand", className, }) {
1267
+ function AppSidebar({ modules, tools, activeModule, orgCode, approvalCounts, closeOnNavigation = false, highlightActiveModule = false, header, footer, bottom, chrome = "brand", className, }) {
1267
1268
  const { open } = useSidebar();
1268
1269
  const modulesWithActiveState = React.useMemo(() => modules.map(m => ({
1269
1270
  ...m,
@@ -1274,7 +1275,7 @@ function AppSidebar({ modules, tools, activeModule, orgCode, approvalCounts, clo
1274
1275
  if (chrome === "workspace") {
1275
1276
  return (jsxs("div", { className: cn("flex h-screen w-[244px] shrink-0 flex-col overflow-hidden border-r border-sidebar-border bg-sidebar text-sidebar-foreground",
1276
1277
  // As a drawer (≤1024px) it floats over the page and needs the lift.
1277
- "max-[1024px]:shadow-2xl", className), children: [header ? jsx("div", { className: "shrink-0 px-[18px] pt-8 pb-6", children: header }) : null, jsxs(SidebarContent, { className: "flex-1 overflow-y-auto px-[18px]", children: [jsx(NavMain, { items: modulesWithActiveState, orgCode: orgCode, approvalCounts: approvalCounts, closeOnNavigation: closeOnNavigation, chrome: "workspace" }), jsx(NavTools, { tools: tools, closeOnNavigation: closeOnNavigation })] }), bottom ? jsx("div", { className: "shrink-0 px-[18px] pt-6", children: bottom }) : null, jsx("div", { className: "shrink-0 px-[18px] pb-3", children: footer })] }));
1278
+ "max-[1024px]:shadow-2xl", className), children: [header ? jsx("div", { className: "shrink-0 px-[18px] pt-8 pb-6", children: header }) : null, jsxs(SidebarContent, { className: "flex-1 overflow-y-auto px-[18px]", children: [jsx(NavMain, { items: modulesWithActiveState, orgCode: orgCode, approvalCounts: approvalCounts, closeOnNavigation: closeOnNavigation, chrome: "workspace", highlightActiveModule: highlightActiveModule }), jsx(NavTools, { tools: tools, closeOnNavigation: closeOnNavigation })] }), bottom ? jsx("div", { className: "shrink-0 px-[18px] pt-6", children: bottom }) : null, jsx("div", { className: "shrink-0 px-[18px] pb-3", children: footer })] }));
1278
1279
  }
1279
1280
  return (jsxs("div", { className: cn("bg-sidebar shrink-0 flex flex-col overflow-hidden shadow-2xl h-screen w-[var(--sidebar-width-mobile)]", "!w-76 xl:rounded-b-4xl xl:rounded-tl-4xl xl:m-5 xl:h-[calc(100vh-2.5rem)]", className), children: [jsx(SidebarHeader, { children: header }), jsxs(SidebarContent, { className: "pl-2 pr-2 flex-1 overflow-y-auto", children: [jsx(NavMain, { items: modulesWithActiveState, orgCode: orgCode, approvalCounts: approvalCounts, closeOnNavigation: closeOnNavigation }), jsx(NavTools, { tools: tools, closeOnNavigation: closeOnNavigation })] }), jsx(SidebarFooter, { className: "pl-2 pr-2", children: footer })] }));
1280
1281
  }
@@ -1291,6 +1292,16 @@ const WORKSPACE_HEADER_VARS = {
1291
1292
  "--header-title-px": "0px",
1292
1293
  "--header-title-py": "0px",
1293
1294
  };
1295
+ const WORKSPACE_LIGHT_HEADER_VARS = {
1296
+ "--header-fg": "var(--foreground)",
1297
+ "--header-fg-muted": "var(--muted-foreground)",
1298
+ "--header-hover": "var(--accent)",
1299
+ "--header-mark-bg": "var(--accent)",
1300
+ "--header-mark-fg": "var(--primary)",
1301
+ "--header-mark-border": "transparent",
1302
+ "--header-title-px": "0px",
1303
+ "--header-title-py": "0px",
1304
+ };
1294
1305
 
1295
1306
  /**
1296
1307
  * Top-level app chrome: sticky header, sidebar slot, content gutter and the
@@ -1304,7 +1315,7 @@ const WORKSPACE_HEADER_VARS = {
1304
1315
  * an erp-shell bump — domain components must NOT add their own root padding
1305
1316
  * or content gets indented twice.
1306
1317
  */
1307
- function AppLayoutShell({ children, sidebar, loadingComponent, breadcrumb, permissionProvider, organizationId, setOrganizationId, organizations, signInUrl, selectOrganizationUrl, chrome = "brand", headerEnd, mobileBrand, }) {
1318
+ function AppLayoutShell({ children, sidebar, loadingComponent, breadcrumb, permissionProvider, organizationId, setOrganizationId, organizations, signInUrl, selectOrganizationUrl, chrome = "brand", workspaceHeader = "brand", headerEnd, mobileBrand, }) {
1308
1319
  const { data: session, status } = useSession();
1309
1320
  const { open, setOpen } = useSidebar();
1310
1321
  const router = useRouter();
@@ -1435,7 +1446,12 @@ function AppLayoutShell({ children, sidebar, loadingComponent, breadcrumb, permi
1435
1446
  : "";
1436
1447
  const needsLeftGutter = workspace || !(open && !isSidebarModalLayout);
1437
1448
  const wrap = permissionProvider ?? ((c) => c);
1438
- return (jsxs("div", { className: "flex min-h-screen w-full bg-background", children: [open && (jsx("div", { className: "fixed left-0 top-0 z-50 h-screen", children: sidebar })), open && isSidebarModalLayout && (jsx("button", { type: "button", "aria-label": "\u0E1B\u0E34\u0E14\u0E40\u0E21\u0E19\u0E39", className: "fixed inset-0 z-40 bg-black/50", onClick: () => setOpen(false) })), jsx("div", { className: cx("relative flex min-w-0 flex-1 flex-col transition-all", contentMargin), children: jsxs("main", { className: cx("flex flex-1 flex-col min-h-screen", workspace ? "gap-0" : "gap-4"), children: [workspace ? (jsxs("div", { className: "sticky top-0 z-30 shrink-0 w-full", style: WORKSPACE_HEADER_VARS, children: [jsx(HeaderBackground, { className: "rounded-none" }), jsxs("header", { className: "relative z-10 flex min-h-[72px] w-full items-center gap-3 px-[18px] py-3 text-[var(--header-fg)] sm:px-6 lg:min-h-[88px] lg:px-10", children: [isSidebarModalLayout ? (
1449
+ return (jsxs("div", { className: "flex min-h-screen w-full bg-background", children: [open && (jsx("div", { className: "fixed left-0 top-0 z-50 h-screen", children: sidebar })), open && isSidebarModalLayout && (jsx("button", { type: "button", "aria-label": "\u0E1B\u0E34\u0E14\u0E40\u0E21\u0E19\u0E39", className: "fixed inset-0 z-40 bg-black/50", onClick: () => setOpen(false) })), jsx("div", { className: cx("relative flex min-w-0 flex-1 flex-col transition-all", contentMargin), children: jsxs("main", { className: cx("flex flex-1 flex-col min-h-screen", workspace ? "gap-0" : "gap-4"), children: [workspace ? (jsxs("div", { className: cx("sticky top-0 z-30 shrink-0 w-full", workspaceHeader === "light" &&
1450
+ "border-b border-border bg-card/85 backdrop-blur-sm"), style: workspaceHeader === "light"
1451
+ ? WORKSPACE_LIGHT_HEADER_VARS
1452
+ : WORKSPACE_HEADER_VARS, children: [workspaceHeader === "light" ? null : (jsx(HeaderBackground, { className: "rounded-none" })), jsxs("header", { className: cx("relative z-10 flex w-full items-center gap-3 text-[var(--header-fg)]", workspaceHeader === "light"
1453
+ ? "min-h-[66px] px-3 py-2 sm:min-h-[72px] sm:px-[22px] lg:min-h-[82px] lg:px-8"
1454
+ : "min-h-[72px] px-[18px] py-3 sm:px-6 lg:min-h-[88px] lg:px-10"), children: [isSidebarModalLayout ? (
1439
1455
  // As in the design: the mark, then a menu button, and the
1440
1456
  // organisation on the right — no trail, no title, so the
1441
1457
  // organisation's name has the room it needs on a phone.
@@ -2290,5 +2306,5 @@ const getAxiosErrorMessage = (error) => {
2290
2306
  return String(error);
2291
2307
  };
2292
2308
 
2293
- export { AccessDenied, ApiError, AppBreadcrumb, AppLayoutShell, AppSidebar, EMPLOYEE_RECORD_OK_EVENT, EMPLOYEE_RECORD_REQUIRED, EMPLOYEE_RECORD_REQUIRED_EVENT, EmployeeRequiredGate, FeatureFlagsProvider, HeaderBackground, NavMain, NavTools, NavUser, OrganizationSwitcher, PLAN_FEATURES, PermissionGateShell, PermissionProvider, PermissionRulesProvider, ReactQueryProvider, SessionBackedProfileCacheSeeder, SessionRefreshTrigger, SidebarContent, SidebarFooter, SidebarHeader, SidebarHelpCard, SidebarHelpLink, SidebarProvider, SidebarTrigger, TapMenu, ThemeProvider, WORKSPACE_HEADER_VARS, WorkspaceBrand, instance as axiosInstance, buildSystemLinks, buildUrlWithCode, canAccessNavPermissionRoute, clearAccessTokenCache, clearOrganizationId, decodeJWT, filterNavigationModulesByPermission, filterNavigationToolsByPermission, getAccessToken, getActiveModule, getActiveSubModule, getAxiosErrorMessage, getOrganizationId, getQueryClientConfig, getRequiredChildGroups, hasPlanFeature, isLikelyTransientNetworkError, isPathActive, normalizePathnameForPermissionRules, resolveUiRoutePermission, runGlobalRequestPrecheck, runWithTransientRetry, setOrganizationId, toApiError, unwrapApiResponse, updateOrganizationId, useClearOrgOnUserChange, useFeatureFlag, useFeatureFlags, useInvalidateQueriesOnOrgChange, useKeycloakRoles, useOrganizationIdState, usePermissionRules, useSessionRefresh, useSidebar, useSidebarToggle };
2309
+ export { AccessDenied, ApiError, AppBreadcrumb, AppLayoutShell, AppSidebar, EMPLOYEE_RECORD_OK_EVENT, EMPLOYEE_RECORD_REQUIRED, EMPLOYEE_RECORD_REQUIRED_EVENT, EmployeeRequiredGate, FeatureFlagsProvider, HeaderBackground, NavMain, NavTools, NavUser, OrganizationSwitcher, PLAN_FEATURES, PermissionGateShell, PermissionProvider, PermissionRulesProvider, ReactQueryProvider, SessionBackedProfileCacheSeeder, SessionRefreshTrigger, SidebarContent, SidebarFooter, SidebarHeader, SidebarHelpCard, SidebarHelpLink, SidebarProvider, SidebarTrigger, TapMenu, ThemeProvider, WORKSPACE_HEADER_VARS, WORKSPACE_LIGHT_HEADER_VARS, WorkspaceBrand, instance as axiosInstance, buildSystemLinks, buildUrlWithCode, canAccessNavPermissionRoute, clearAccessTokenCache, clearOrganizationId, decodeJWT, filterNavigationModulesByPermission, filterNavigationToolsByPermission, getAccessToken, getActiveModule, getActiveSubModule, getAxiosErrorMessage, getOrganizationId, getQueryClientConfig, getRequiredChildGroups, hasPlanFeature, isLikelyTransientNetworkError, isPathActive, normalizePathnameForPermissionRules, resolveUiRoutePermission, runGlobalRequestPrecheck, runWithTransientRetry, setOrganizationId, toApiError, unwrapApiResponse, updateOrganizationId, useClearOrgOnUserChange, useFeatureFlag, useFeatureFlags, useInvalidateQueriesOnOrgChange, useKeycloakRoles, useOrganizationIdState, usePermissionRules, useSessionRefresh, useSidebar, useSidebarToggle };
2294
2310
  //# sourceMappingURL=index.esm.js.map