@eintrek/erp-shell 0.1.45 → 0.1.46
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 +3 -0
- package/dist/index.esm.js +132 -39
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +133 -36
- package/dist/index.js.map +1 -1
- package/dist/navigation/app-layout-shell.d.ts +14 -1
- package/dist/navigation/app-sidebar.d.ts +10 -1
- package/dist/navigation/chrome.d.ts +24 -0
- package/dist/navigation/nav-main.d.ts +4 -1
- package/dist/navigation/nav-user.d.ts +6 -1
- package/dist/navigation/navigation-types.d.ts +8 -0
- package/dist/navigation/organization-switcher.d.ts +7 -1
- package/dist/navigation/sidebar-help-card.d.ts +22 -0
- package/dist/navigation/workspace-brand.d.ts +19 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -21,6 +21,9 @@ 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";
|
|
25
|
+
export { WorkspaceBrand, type WorkspaceBrandProps } from "./navigation/workspace-brand";
|
|
26
|
+
export { SidebarHelpCard, SidebarHelpLink, type SidebarHelpCardProps, type SidebarHelpLinkProps, } from "./navigation/sidebar-help-card";
|
|
24
27
|
export { AccessDenied, type AccessDeniedProps } from "./auth/access-denied";
|
|
25
28
|
export { EmployeeRequiredGate, EMPLOYEE_RECORD_REQUIRED, EMPLOYEE_RECORD_REQUIRED_EVENT, EMPLOYEE_RECORD_OK_EVENT, } from "./auth/employee-required-gate";
|
|
26
29
|
export { PermissionGateShell, type PermissionGateShellProps, type PermissionGateSkeletonVariant, } from "./auth/permission-gate-shell";
|
package/dist/index.esm.js
CHANGED
|
@@ -4,8 +4,8 @@ import React__default, { useRef, useEffect, useMemo, useState, useCallback, crea
|
|
|
4
4
|
import { useSession, signOut } from 'next-auth/react';
|
|
5
5
|
import { useQueryClient, MutationCache, QueryCache, QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
6
6
|
import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
|
|
7
|
-
import { cn, Button, Breadcrumb, BreadcrumbList, BreadcrumbItem, BreadcrumbLink, BreadcrumbSeparator, BreadcrumbPage, Avatar, AvatarImage, AvatarFallback, Collapsible, CollapsibleTrigger, CollapsibleContent, Badge,
|
|
8
|
-
import { PanelLeftClose, Menu, ChevronRight, Building2, Palette, ChevronUp, Sun, Moon, Monitor, Globe, User, LayoutGrid, ExternalLink, Loader2, LogOut, Calculator, Warehouse, FolderKanban, Users, ChevronDown,
|
|
7
|
+
import { cn, Button, Breadcrumb, BreadcrumbList, BreadcrumbItem, BreadcrumbLink, BreadcrumbSeparator, BreadcrumbPage, Avatar, AvatarImage, AvatarFallback, Collapsible, CollapsibleTrigger, CollapsibleContent, Badge, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuItem, DropdownMenuSeparator, Skeleton, Card, CardHeader, CardContent } from '@eintrek/erp-theme';
|
|
8
|
+
import { PanelLeftClose, Menu, ChevronRight, Building2, Palette, ChevronUp, Sun, Moon, Monitor, Globe, User, LayoutGrid, ExternalLink, Loader2, LogOut, ChevronsUpDown, Calculator, Warehouse, FolderKanban, Users, ChevronDown, Plus, ArrowRight, Compass, ArrowUpRight, Ban, Home, Headset, ContactRound, UserPlus } from 'lucide-react';
|
|
9
9
|
import { create } from 'zustand';
|
|
10
10
|
import { persist, createJSONStorage } from 'zustand/middleware';
|
|
11
11
|
import { useRouter, usePathname, useParams } from 'next/navigation';
|
|
@@ -776,14 +776,14 @@ function AppBreadcrumb({ labels = {}, homeLabel = "แดชบอร์ด", ro
|
|
|
776
776
|
if (segments.length === 0) {
|
|
777
777
|
return jsx("h1", { className: "text-xl font-semibold", children: homeLabel });
|
|
778
778
|
}
|
|
779
|
-
return (jsx(Breadcrumb, { children: jsxs(BreadcrumbList, { children: [jsx(BreadcrumbItem, { children: jsx(BreadcrumbLink, { asChild: true, children: jsx(Link, { href: "/", className: "font-thai text-[14px] font-normal text-
|
|
779
|
+
return (jsx(Breadcrumb, { children: jsxs(BreadcrumbList, { children: [jsx(BreadcrumbItem, { children: jsx(BreadcrumbLink, { asChild: true, children: jsx(Link, { href: "/", className: "font-thai text-[14px] font-normal text-[var(--header-fg-muted,rgb(255_255_255/0.8))] hover:text-[var(--header-fg,white)] transition-colors", children: rootLabel }) }) }), segments.map((segment, index) => {
|
|
780
780
|
const href = "/" + segments.slice(0, index + 1).join("/");
|
|
781
781
|
const isLast = index === segments.length - 1;
|
|
782
782
|
// A record id is not a place. Falling back to the raw segment put a
|
|
783
783
|
// 36-character uuid in the trail, which pushed everything before it
|
|
784
784
|
// off a phone and told the reader nothing they could use.
|
|
785
785
|
const label = labels[segment] ?? (isRecordID(segment) ? "รายละเอียด" : segment);
|
|
786
|
-
return (jsxs(Fragment, { children: [jsx(BreadcrumbSeparator, { className: "text-
|
|
786
|
+
return (jsxs(Fragment, { children: [jsx(BreadcrumbSeparator, { className: "text-[var(--header-fg-muted,rgb(255_255_255/0.8))]", children: jsx(ChevronRight, { strokeWidth: 2, className: "h-4 w-4" }) }), jsx(BreadcrumbItem, { children: isLast ? (jsx(BreadcrumbPage, { className: "font-thai text-[14px] font-normal text-[var(--header-fg,rgb(255_255_255/0.95))] leading-none", children: decodeURIComponent(label) })) : (jsx(BreadcrumbLink, { asChild: true, children: jsx(Link, { href: href, className: "font-thai text-[14px] font-normal text-[var(--header-fg-muted,rgb(255_255_255/0.8))] hover:text-[var(--header-fg,white)] transition-colors leading-none", children: decodeURIComponent(label) }) })) })] }, `${segment}-${index}`));
|
|
787
787
|
})] }) }));
|
|
788
788
|
}
|
|
789
789
|
/**
|
|
@@ -801,7 +801,7 @@ function isRecordID(segment) {
|
|
|
801
801
|
function isExternalHref(href) {
|
|
802
802
|
return /^https?:\/\//i.test(href) || href.startsWith("//");
|
|
803
803
|
}
|
|
804
|
-
function NavUser({ organization, avatarSrc, profileHref, selectOrganizationHref = "/select-organization", signInRedirectHref = "/auth/signin", systemLinks, showSelectOrganization = true, showLanguageSwitch = true, } = {}) {
|
|
804
|
+
function NavUser({ organization, avatarSrc, profileHref, selectOrganizationHref = "/select-organization", signInRedirectHref = "/auth/signin", systemLinks, showSelectOrganization = true, showLanguageSwitch = true, variant = "brand", } = {}) {
|
|
805
805
|
const { data: session, status } = useSession();
|
|
806
806
|
const router = useRouter();
|
|
807
807
|
const { theme, setTheme } = useTheme();
|
|
@@ -924,6 +924,10 @@ function NavUser({ organization, avatarSrc, profileHref, selectOrganizationHref
|
|
|
924
924
|
setShowThemeMenu(false);
|
|
925
925
|
setShowLanguageMenu(false);
|
|
926
926
|
}, className: "flex w-full items-center gap-3 px-3 py-2.5 text-sm text-sidebar-foreground hover:bg-sidebar-accent rounded-md transition-colors", children: [jsx(LayoutGrid, { className: "h-4 w-4" }), jsx("span", { className: "flex-1 text-left", children: "\u0E41\u0E2D\u0E1B\u0E1E\u0E25\u0E34\u0E40\u0E04\u0E0A\u0E31\u0E19" }), jsx(ChevronUp, { className: `h-4 w-4 transition-transform ${showAppsMenu ? "rotate-180" : ""}` })] }), showAppsMenu && (jsx("div", { className: "mt-1 ml-4 space-y-1", children: visibleSystemLinks.map(link => (jsxs("button", { type: "button", onClick: () => handleSystemLink(link.href), className: "flex w-full items-center gap-3 px-3 py-2 text-sm text-sidebar-foreground hover:bg-sidebar-accent rounded-md transition-colors", children: [link.icon ?? jsx(ExternalLink, { className: "h-4 w-4" }), jsx("span", { className: "flex-1 text-left", children: link.label }), link.active && (jsx("div", { className: "h-2 w-2 rounded-full bg-primary" }))] }, `${link.label}:${link.href}`))) }))] })), jsx("button", { onClick: handleSignOut, disabled: isSigningOut, className: "flex w-full items-center gap-3 px-3 py-2.5 text-sm text-sidebar-foreground hover:bg-sidebar-accent rounded-md transition-colors disabled:opacity-50 disabled:cursor-not-allowed mt-1", children: isSigningOut ? (jsxs(Fragment$1, { children: [jsx(Loader2, { className: "h-4 w-4 animate-spin" }), jsx("span", { className: "flex-1 text-left", children: "\u0E01\u0E33\u0E25\u0E31\u0E07\u0E2D\u0E2D\u0E01\u0E08\u0E32\u0E01\u0E23\u0E30\u0E1A\u0E1A..." })] })) : (jsxs(Fragment$1, { children: [jsx(LogOut, { className: "h-4 w-4" }), jsx("span", { className: "flex-1 text-left", children: "\u0E2D\u0E2D\u0E01\u0E08\u0E32\u0E01\u0E23\u0E30\u0E1A\u0E1A" })] })) })] })] })) : null;
|
|
927
|
+
if (variant === "workspace") {
|
|
928
|
+
return (jsx("div", { className: "mt-3.5 border-t border-sidebar-border pt-3", children: jsxs("div", { className: "relative", children: [jsxs("button", { ref: buttonRef, onClick: () => setIsOpen(!isOpen), "aria-expanded": isOpen, className: "flex w-full items-center gap-[11px] rounded-lg px-3 py-1.5 text-left transition-colors hover:bg-sidebar-accent/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sidebar-ring", children: [jsxs(Avatar, { className: "size-[34px] shrink-0 rounded-full border-[3px] border-sidebar-accent", children: [user.avatar ? (jsx(AvatarImage, { src: user.avatar, alt: user.name })) : null, jsx(AvatarFallback, { className: "rounded-full bg-sidebar-accent text-sm font-medium text-sidebar-accent-foreground", children: getInitials(user.name) })] }), jsxs("span", { className: "grid min-w-0 flex-1 leading-tight", children: [jsx("strong", { className: "truncate text-[13px] font-semibold", title: user.name, children: user.name }), jsx("small", { className: "truncate text-[11px] text-muted-foreground", title: user.email, children: user.email })] }), jsx(ChevronsUpDown, { className: "size-3.5 shrink-0 text-muted-foreground" })] }), typeof window !== "undefined" &&
|
|
929
|
+
createPortal(dropdownContent, document.body)] }) }));
|
|
930
|
+
}
|
|
927
931
|
return (jsx("div", { className: "p-2", children: jsxs("div", { className: "relative", children: [jsxs("button", { ref: buttonRef, onClick: () => setIsOpen(!isOpen), className: "flex w-full items-center gap-2 p-2 rounded-md transition-colors", children: [jsxs(Avatar, { className: "h-8 w-8 rounded-lg", children: [user.avatar ? (jsx(AvatarImage, { src: user.avatar, alt: user.name })) : null, jsx(AvatarFallback, { className: "rounded-lg bg-primary text-primary-foreground w-8 h-8", children: getInitials(user.name) })] }), jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [jsx("span", { className: "truncate font-medium", title: user.name, children: user.name }), jsx("span", { className: "truncate text-xs text-sidebar-foreground/70", title: user.email, children: user.email })] }), jsx(ChevronUp, { className: `ml-auto size-4 transition-transform ${isOpen ? "rotate-180" : ""}` })] }), typeof window !== "undefined" &&
|
|
928
932
|
createPortal(dropdownContent, document.body)] }) }));
|
|
929
933
|
}
|
|
@@ -1055,7 +1059,15 @@ function isPathActive(pathname, url) {
|
|
|
1055
1059
|
return false;
|
|
1056
1060
|
}
|
|
1057
1061
|
|
|
1058
|
-
|
|
1062
|
+
/** "/O1/" and "/O1" are the same page; a query string never is. */
|
|
1063
|
+
function samePage(pathname, url) {
|
|
1064
|
+
if (url.includes("?"))
|
|
1065
|
+
return false;
|
|
1066
|
+
const strip = (p) => (p.length > 1 ? p.replace(/\/+$/, "") : p);
|
|
1067
|
+
return strip(pathname) === strip(url);
|
|
1068
|
+
}
|
|
1069
|
+
function NavMain({ items, orgCode, closeOnNavigation = false, approvalCounts, chrome = "brand", }) {
|
|
1070
|
+
const workspace = chrome === "workspace";
|
|
1059
1071
|
const params = useParams();
|
|
1060
1072
|
const pathname = usePathname();
|
|
1061
1073
|
const { setOpen } = useSidebar();
|
|
@@ -1064,7 +1076,11 @@ function NavMain({ items, orgCode, closeOnNavigation = false, approvalCounts, })
|
|
|
1064
1076
|
setOpen(false);
|
|
1065
1077
|
};
|
|
1066
1078
|
const code = orgCode ?? params?.code;
|
|
1067
|
-
return (jsx(SidebarGroup, { "data-sidebar": true, children: jsx(SidebarMenu, { children: items.map(item => {
|
|
1079
|
+
return (jsx(SidebarGroup, { "data-sidebar": true, className: workspace ? "p-0" : undefined, children: jsx(SidebarMenu, { className: workspace ? "gap-[3px]" : undefined, children: items.map((item, index) => {
|
|
1080
|
+
const groupHeading = workspace &&
|
|
1081
|
+
item.group &&
|
|
1082
|
+
item.group !== items[index - 1]?.group ? (jsx("li", { className: "list-none px-[15px] pb-2.5 text-xs text-muted-foreground" +
|
|
1083
|
+
(index > 0 ? " pt-8" : ""), children: item.group }, `group-${item.id}`)) : null;
|
|
1068
1084
|
const itemUrl = buildUrlWithCode(code, item.url);
|
|
1069
1085
|
// Most specific (longest) matching sub-item URL so only one link is active.
|
|
1070
1086
|
const activeSubItemUrl = item.subModules?.reduce((best, subItem) => {
|
|
@@ -1085,30 +1101,43 @@ function NavMain({ items, orgCode, closeOnNavigation = false, approvalCounts, })
|
|
|
1085
1101
|
isPathActive(pathname, subPage.url)));
|
|
1086
1102
|
// Parent only active when path matches its URL exactly AND no child
|
|
1087
1103
|
// is active (so parent+child don't both light up).
|
|
1088
|
-
const isItemActive = pathname === itemUrl &&
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1104
|
+
const isItemActive = (workspace ? samePage(pathname, itemUrl) : pathname === itemUrl) &&
|
|
1105
|
+
!hasActiveSubItem;
|
|
1106
|
+
const IconComp = item.icon;
|
|
1107
|
+
const workspaceButton = workspace
|
|
1108
|
+
? "h-auto gap-3 rounded-[10px] px-3.5 py-[11px] text-sm " +
|
|
1109
|
+
(isItemActive
|
|
1110
|
+
? "bg-sidebar-accent font-bold text-sidebar-accent-foreground"
|
|
1111
|
+
: "font-medium text-sidebar-foreground/70")
|
|
1112
|
+
: "";
|
|
1113
|
+
const icon = workspace && IconComp ? (jsx(IconComp, { className: "size-[18px] shrink-0" })) : null;
|
|
1114
|
+
const badge = workspace && item.badge !== undefined && item.badge !== "" ? (jsx("span", { className: "ml-auto min-w-5 rounded-[5px] bg-primary/15 px-1 text-center text-[10px] leading-5 font-bold tabular-nums text-primary", children: item.badge })) : null;
|
|
1115
|
+
return (jsxs(React.Fragment, { children: [groupHeading, jsx(Collapsible, { asChild: true, defaultOpen: isItemActive || hasActiveSubItem, className: "group/collapsible", children: jsxs(SidebarMenuItem, { children: [jsx(CollapsibleTrigger, { asChild: true, children: jsx(SidebarMenuButton, { asChild: !item.subModules || item.subModules.length === 0, isActive: isItemActive, className: "data-[state=open]:text-sidebar-accent-foreground " +
|
|
1116
|
+
workspaceButton, children: item.subModules && item.subModules.length > 0 ? (jsxs(Fragment$1, { children: [icon, jsx("span", { id: item.id, children: item.titleTh }), jsx(ChevronRight, { className: "ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" })] })) : (jsxs(Link, { href: itemUrl, prefetch: false, className: "flex items-center w-full min-w-0 flex-1 " +
|
|
1117
|
+
(workspace ? "gap-3" : "gap-2"), onClick: handleNavLinkClick, "aria-current": isItemActive ? "page" : undefined, children: [icon, jsx("span", { id: item.id, className: "flex-1 truncate", title: item.titleTh, children: item.titleTh }), badge] })) }) }), item.subModules && item.subModules.length > 0 && (jsx(CollapsibleContent, { children: jsx(SidebarMenuSub, { className: workspace
|
|
1118
|
+
? "mx-0 ml-[23px] mt-1 border-l border-sidebar-border pl-2.5 [&_a]:text-[13px] [&_svg]:!size-4"
|
|
1119
|
+
: undefined, children: item.subModules.map(subItem => {
|
|
1120
|
+
const subItemUrl = buildUrlWithCode(code, subItem.url);
|
|
1121
|
+
const isSubItemActive = subItemUrl === activeSubItemUrl;
|
|
1122
|
+
const SubIcon = subItem.icon;
|
|
1123
|
+
const approvalCount = approvalCounts && subItem.approvalCountKey
|
|
1124
|
+
? approvalCounts[subItem.approvalCountKey] ?? 0
|
|
1125
|
+
: 0;
|
|
1126
|
+
if (subItem.isCollapsible &&
|
|
1127
|
+
subItem.subPages &&
|
|
1128
|
+
subItem.subPages.length > 0) {
|
|
1129
|
+
const hasActiveSubPage = subItem.subPages.some(subPage => isPathActive(pathname, buildUrlWithCode(code, subPage.url)));
|
|
1130
|
+
return (jsx(Collapsible, { asChild: true, defaultOpen: isSubItemActive || hasActiveSubPage, className: "group/sub-collapsible", children: jsxs(SidebarMenuSubItem, { children: [jsx(CollapsibleTrigger, { asChild: true, children: jsxs(SidebarMenuSubButton, { className: "w-full", isActive: isSubItemActive || hasActiveSubPage, children: [SubIcon && (jsx(SubIcon, { className: "sidebar-submodule-icon flex-shrink-0" })), jsx("span", { className: "flex-1 truncate", title: subItem.titleTh, children: subItem.titleTh }), jsx(ChevronDown, { className: "ml-auto size-4 transition-transform duration-200 group-data-[state=open]/sub-collapsible:rotate-180" })] }) }), jsx(CollapsibleContent, { children: jsx(SidebarMenuSub, { className: "ml-4", children: subItem.subPages.map(subPage => {
|
|
1131
|
+
const subPageUrl = buildUrlWithCode(code, subPage.url);
|
|
1132
|
+
const isSubPageActive = isPathActive(pathname, subPageUrl);
|
|
1133
|
+
const SubPageIcon = subPage.icon;
|
|
1134
|
+
return (jsx(SidebarMenuSubItem, { children: jsx(SidebarMenuSubButton, { asChild: true, className: `font-thai w-full text-sm ${isSubPageActive
|
|
1135
|
+
? "text-sidebar-accent-foreground font-medium"
|
|
1136
|
+
: "text-sidebar-foreground"}`, isActive: false, children: jsxs(Link, { href: subPageUrl, prefetch: false, className: "w-full flex items-center", onClick: handleNavLinkClick, children: [SubPageIcon && (jsx(SubPageIcon, { className: "sidebar-subpage-icon flex-shrink-0" })), jsx("span", { className: "flex-1 truncate", title: subPage.titleTh, children: subPage.titleTh })] }) }) }, subPage.id));
|
|
1137
|
+
}) }) })] }) }, subItem.id));
|
|
1138
|
+
}
|
|
1139
|
+
return (jsx(SidebarMenuSubItem, { children: jsx(SidebarMenuSubButton, { asChild: true, className: "w-full", isActive: isSubItemActive, children: jsxs(Link, { href: subItemUrl, prefetch: false, className: "w-full flex items-center", onClick: handleNavLinkClick, children: [SubIcon && (jsx(SubIcon, { className: "sidebar-submodule-icon flex-shrink-0" })), jsx("span", { className: "flex-1 truncate", title: subItem.titleTh, children: subItem.titleTh }), approvalCount > 0 && (jsx(Badge, { variant: "destructive", className: "ml-auto h-5 min-w-5 px-1.5 text-xs font-medium tabular-nums", children: approvalCount > 99 ? "99+" : approvalCount }))] }) }) }, subItem.id));
|
|
1140
|
+
}) }) }))] }) })] }, item.id));
|
|
1112
1141
|
}) }) }));
|
|
1113
1142
|
}
|
|
1114
1143
|
|
|
@@ -1116,14 +1145,16 @@ function OrgMark({ logoUrl, size = "md", }) {
|
|
|
1116
1145
|
const [failed, setFailed] = useState(false);
|
|
1117
1146
|
const box = size === "sm"
|
|
1118
1147
|
? "flex size-6 items-center justify-center rounded-md border overflow-hidden bg-background"
|
|
1119
|
-
:
|
|
1148
|
+
: size === "header"
|
|
1149
|
+
? "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"
|
|
1150
|
+
: "flex aspect-square size-8 shrink-0 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground overflow-hidden";
|
|
1120
1151
|
const icon = size === "sm" ? "size-3.5 shrink-0" : "size-4";
|
|
1121
1152
|
if (logoUrl && !failed) {
|
|
1122
1153
|
return (jsx("div", { className: cn(box, size === "md" && "bg-white"), children: jsx("img", { src: logoUrl, alt: "", className: "size-full object-contain p-0.5", onError: () => setFailed(true) }) }));
|
|
1123
1154
|
}
|
|
1124
1155
|
return (jsx("div", { className: box, children: jsx(Building2, { className: icon }) }));
|
|
1125
1156
|
}
|
|
1126
|
-
function OrganizationSwitcher({ activeOrganization, isContextLoading = false, organizations, isLoadingOrgs = false, setOrganizationCookie, registerOrganizationHref = "/register-organization", className, }) {
|
|
1157
|
+
function OrganizationSwitcher({ activeOrganization, isContextLoading = false, organizations, isLoadingOrgs = false, setOrganizationCookie, registerOrganizationHref = "/register-organization", placement = "sidebar", className, }) {
|
|
1127
1158
|
const { isMobile } = useSidebarToggle();
|
|
1128
1159
|
const router = useRouter();
|
|
1129
1160
|
const params = useParams();
|
|
@@ -1164,6 +1195,14 @@ function OrganizationSwitcher({ activeOrganization, isContextLoading = false, or
|
|
|
1164
1195
|
});
|
|
1165
1196
|
};
|
|
1166
1197
|
const isLoading = isLoadingOrgs || isContextLoading;
|
|
1198
|
+
if (placement === "header") {
|
|
1199
|
+
const face = (interactive) => (jsxs(Fragment$1, { children: [jsx(OrgMark, { logoUrl: activeOrganization?.logoUrl, size: "header" }), jsxs("span", { className: "min-w-0 text-left", children: [jsx("small", { className: "block text-[10px] leading-tight text-[var(--header-fg-muted,currentColor)] max-sm:text-[9px]", children: "\u0E2D\u0E07\u0E04\u0E4C\u0E01\u0E23\u0E17\u0E35\u0E48\u0E01\u0E33\u0E25\u0E31\u0E07\u0E43\u0E0A\u0E49\u0E07\u0E32\u0E19" }), isLoading ? (jsx(Skeleton, { className: "mt-1 h-3.5 w-28" })) : (jsx("strong", { className: "block max-w-[220px] truncate text-xs font-semibold text-[var(--header-fg,currentColor)] max-sm:max-w-[140px] max-sm:text-[11px]", children: activeOrganization?.name || "เลือกองค์กร" }))] }), interactive ? (isPending ? (jsx(Loader2, { className: "ml-1 size-3.5 shrink-0 animate-spin text-[var(--header-fg-muted,currentColor)]" })) : (jsx(ChevronsUpDown, { className: "ml-1 size-3.5 shrink-0 text-[var(--header-fg-muted,currentColor)]" }))) : null] }));
|
|
1200
|
+
const faceClass = cn("flex items-center gap-2.5 rounded-lg py-1.5 max-sm:gap-2", className);
|
|
1201
|
+
if (isLoading || organizations.length <= 1) {
|
|
1202
|
+
return jsx("div", { className: faceClass, children: face(false) });
|
|
1203
|
+
}
|
|
1204
|
+
return (jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { className: cn(faceClass, "px-1.5 outline-none transition-colors hover:bg-[var(--header-hover,var(--accent))] focus-visible:ring-2 focus-visible:ring-[var(--header-fg-muted,var(--ring))] data-[state=open]:bg-[var(--header-hover,var(--accent))]"), "aria-label": "\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E2D\u0E07\u0E04\u0E4C\u0E01\u0E23", children: face(true) }), jsxs(DropdownMenuContent, { className: "min-w-64 rounded-lg", align: "end", side: "bottom", sideOffset: 6, children: [jsx(DropdownMenuLabel, { className: "text-xs text-muted-foreground", children: "\u0E2D\u0E07\u0E04\u0E4C\u0E01\u0E23" }), organizations.map(org => (jsxs(DropdownMenuItem, { onClick: () => handleOrganizationChange(org), disabled: isPending, className: cn("gap-2 p-2 cursor-pointer", String(activeOrganization?.id) === String(org.id) && "bg-accent"), children: [jsx(OrgMark, { logoUrl: org.logoUrl, size: "sm" }), jsx("span", { className: "truncate", children: org.name })] }, org.id))), jsx(DropdownMenuSeparator, {}), jsxs(DropdownMenuItem, { className: "gap-2 p-2 cursor-pointer", onClick: () => router.push(registerOrganizationHref), children: [jsx("div", { className: "flex size-6 items-center justify-center rounded-md border bg-transparent", children: jsx(Plus, { className: "size-4" }) }), jsx("span", { className: "text-muted-foreground font-medium", children: "\u0E40\u0E1E\u0E34\u0E48\u0E21\u0E2D\u0E07\u0E04\u0E4C\u0E01\u0E23" })] })] })] }));
|
|
1205
|
+
}
|
|
1167
1206
|
if (isLoading) {
|
|
1168
1207
|
return (jsx(SidebarMenu, { className: className, children: jsx(SidebarMenuItem, { children: jsxs("div", { className: "flex items-center gap-2 p-2", children: [jsx(Skeleton, { className: "size-8 rounded-lg" }), jsx(Skeleton, { className: "h-4 w-24" })] }) }) }));
|
|
1169
1208
|
}
|
|
@@ -1178,7 +1217,7 @@ function SidebarHeader({ children, className }) {
|
|
|
1178
1217
|
return jsx("div", { className: cn("px-2 py-3", className), children: children });
|
|
1179
1218
|
}
|
|
1180
1219
|
|
|
1181
|
-
function AppSidebar({ modules, tools, activeModule, orgCode, approvalCounts, closeOnNavigation = false, header, footer, className, }) {
|
|
1220
|
+
function AppSidebar({ modules, tools, activeModule, orgCode, approvalCounts, closeOnNavigation = false, header, footer, bottom, chrome = "brand", className, }) {
|
|
1182
1221
|
const { open } = useSidebar();
|
|
1183
1222
|
const modulesWithActiveState = React.useMemo(() => modules.map(m => ({
|
|
1184
1223
|
...m,
|
|
@@ -1186,9 +1225,27 @@ function AppSidebar({ modules, tools, activeModule, orgCode, approvalCounts, clo
|
|
|
1186
1225
|
})), [modules, activeModule]);
|
|
1187
1226
|
if (!open)
|
|
1188
1227
|
return null;
|
|
1228
|
+
if (chrome === "workspace") {
|
|
1229
|
+
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",
|
|
1230
|
+
// As a drawer (≤1024px) it floats over the page and needs the lift.
|
|
1231
|
+
"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 })] }));
|
|
1232
|
+
}
|
|
1189
1233
|
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 })] }));
|
|
1190
1234
|
}
|
|
1191
1235
|
|
|
1236
|
+
/**
|
|
1237
|
+
* Header ink as CSS variables. Header-borne pieces — breadcrumb, sidebar
|
|
1238
|
+
* trigger, the org switcher, the app's own page title — read these, with
|
|
1239
|
+
* white as the fallback, so the brand chrome looks exactly as before.
|
|
1240
|
+
*/
|
|
1241
|
+
const WORKSPACE_HEADER_VARS = {
|
|
1242
|
+
"--header-fg": "#fff",
|
|
1243
|
+
"--header-fg-muted": "rgb(255 255 255 / 0.78)",
|
|
1244
|
+
"--header-hover": "rgb(255 255 255 / 0.12)",
|
|
1245
|
+
"--header-title-px": "0px",
|
|
1246
|
+
"--header-title-py": "0px",
|
|
1247
|
+
};
|
|
1248
|
+
|
|
1192
1249
|
/**
|
|
1193
1250
|
* Top-level app chrome: sticky header, sidebar slot, content gutter and the
|
|
1194
1251
|
* session/org-context plumbing that both Accounting and HR need. Apps wrap
|
|
@@ -1201,7 +1258,7 @@ function AppSidebar({ modules, tools, activeModule, orgCode, approvalCounts, clo
|
|
|
1201
1258
|
* an erp-shell bump — domain components must NOT add their own root padding
|
|
1202
1259
|
* or content gets indented twice.
|
|
1203
1260
|
*/
|
|
1204
|
-
function AppLayoutShell({ children, sidebar, loadingComponent, breadcrumb, permissionProvider, organizationId, setOrganizationId, organizations, signInUrl, selectOrganizationUrl, }) {
|
|
1261
|
+
function AppLayoutShell({ children, sidebar, loadingComponent, breadcrumb, permissionProvider, organizationId, setOrganizationId, organizations, signInUrl, selectOrganizationUrl, chrome = "brand", headerEnd, mobileBrand, }) {
|
|
1205
1262
|
const { data: session, status } = useSession();
|
|
1206
1263
|
const { open, setOpen } = useSidebar();
|
|
1207
1264
|
const router = useRouter();
|
|
@@ -1324,10 +1381,15 @@ function AppLayoutShell({ children, sidebar, loadingComponent, breadcrumb, permi
|
|
|
1324
1381
|
}
|
|
1325
1382
|
// When the sidebar is docked-open it consumes 21.5rem on the left; otherwise
|
|
1326
1383
|
// the content takes the full width and we add a left gutter inside.
|
|
1327
|
-
const
|
|
1328
|
-
const
|
|
1384
|
+
const workspace = chrome === "workspace";
|
|
1385
|
+
const contentMargin = open && !isSidebarModalLayout
|
|
1386
|
+
? workspace
|
|
1387
|
+
? "ml-[244px]"
|
|
1388
|
+
: "ml-[21.5rem]"
|
|
1389
|
+
: "";
|
|
1390
|
+
const needsLeftGutter = workspace || !(open && !isSidebarModalLayout);
|
|
1329
1391
|
const wrap = permissionProvider ?? ((c) => c);
|
|
1330
|
-
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: "flex flex-1 flex-col min-h-screen gap-4", children: [jsxs("div", { className: "sticky top-0 z-30 shrink-0 w-full", children: [jsx(HeaderBackground, {}), jsxs("header", { className: "relative shrink-0 gap-2 py-4 h-auto min-h-[123.5px] w-full z-10", children: [jsxs("div", { className: "flex w-full items-center gap-2 px-3 sm:px-4 lg:px-6", children: [jsx(SidebarTrigger, { className: "shrink-0 text-white hover:bg-white/10" }), jsx("div", { className: "flex-1 min-w-0", children: breadcrumb })] }), jsx("div", { id: "header-title" })] })] }), jsx(Suspense, { fallback: jsx("div", { className: "relative z-10 min-h-[calc(100vh-8rem)]", children: jsx("div", { className: "flex h-full items-center justify-center", children: jsxs("div", { className: "space-y-4 text-center", children: [jsx("div", { className: "mx-auto h-8 w-8 animate-spin rounded-full border-b-2 border-primary" }), jsx("p", { className: "text-sm text-muted-foreground", children: "\u0E01\u0E33\u0E25\u0E31\u0E07\u0E42\u0E2B\u0E25\u0E14..." })] }) }) }), children: jsx("div", { className: cx("relative z-10 pr-6", needsLeftGutter && "pl-6"), children: orgContextIsStale ? loadingComponent : wrap(children) }, `org-${contentOrgKey}`) })] }) })] }));
|
|
1392
|
+
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-4 py-3 text-[var(--header-fg)] sm:px-6 lg:min-h-[88px] lg:px-10", children: [jsx(SidebarTrigger, { className: "shrink-0 text-[var(--header-fg-muted)] hover:bg-[var(--header-hover)] hover:text-[var(--header-fg)] [&_svg]:!text-current" }), isSidebarModalLayout && mobileBrand ? (jsx("div", { className: "shrink-0", children: mobileBrand })) : null, jsxs("div", { className: "flex min-w-0 flex-1 flex-col justify-center gap-0.5", children: [jsx("div", { className: "hidden min-w-0 sm:block", children: breadcrumb }), jsx("div", { id: "header-title", className: "min-w-0" })] }), headerEnd ? (jsx("div", { className: "flex shrink-0 items-center gap-3 sm:gap-5", children: headerEnd })) : null] })] })) : (jsxs("div", { className: "sticky top-0 z-30 shrink-0 w-full", children: [jsx(HeaderBackground, {}), jsxs("header", { className: "relative shrink-0 gap-2 py-4 h-auto min-h-[123.5px] w-full z-10", children: [jsxs("div", { className: "flex w-full items-center gap-2 px-3 sm:px-4 lg:px-6", children: [jsx(SidebarTrigger, { className: "shrink-0 text-white hover:bg-white/10" }), jsx("div", { className: "flex-1 min-w-0", children: breadcrumb }), headerEnd ? (jsx("div", { className: "flex shrink-0 items-center gap-3", children: headerEnd })) : null] }), jsx("div", { id: "header-title" })] })] })), jsx(Suspense, { fallback: jsx("div", { className: "relative z-10 min-h-[calc(100vh-8rem)]", children: jsx("div", { className: "flex h-full items-center justify-center", children: jsxs("div", { className: "space-y-4 text-center", children: [jsx("div", { className: "mx-auto h-8 w-8 animate-spin rounded-full border-b-2 border-primary" }), jsx("p", { className: "text-sm text-muted-foreground", children: "\u0E01\u0E33\u0E25\u0E31\u0E07\u0E42\u0E2B\u0E25\u0E14..." })] }) }) }), children: jsx("div", { className: cx("relative z-10 pr-6", needsLeftGutter && "pl-6", workspace && "pt-4 sm:pr-6 lg:pt-6 lg:pr-10 lg:pl-10"), children: orgContextIsStale ? loadingComponent : wrap(children) }, `org-${contentOrgKey}`) })] }) })] }));
|
|
1331
1393
|
}
|
|
1332
1394
|
/** Local tiny classnames helper — avoids pulling clsx/tailwind-merge into
|
|
1333
1395
|
* the shell just for the layout file. Falsy values are skipped. */
|
|
@@ -1335,6 +1397,37 @@ function cx(...parts) {
|
|
|
1335
1397
|
return parts.filter(Boolean).join(" ");
|
|
1336
1398
|
}
|
|
1337
1399
|
|
|
1400
|
+
/**
|
|
1401
|
+
* The product mark at the top of the workspace sidebar: the app icon, the
|
|
1402
|
+
* name, and a spaced caption beneath it.
|
|
1403
|
+
*/
|
|
1404
|
+
function WorkspaceBrand({ name, caption, mark, href, compact = false, className, }) {
|
|
1405
|
+
const body = (jsxs(Fragment$1, { children: [jsx("span", { className: cn("grid shrink-0 place-items-center overflow-hidden rounded-[14px] [&>img]:size-full [&>img]:object-cover", compact ? "size-9 rounded-[11px]" : "size-11"), children: mark }), compact ? (jsx("span", { className: "sr-only", children: name })) : (jsxs("span", { className: "min-w-0", children: [jsx("span", { className: "block truncate text-[25px] leading-tight font-extrabold tracking-[-0.05em]", children: name }), caption ? (jsx("small", { className: "-mt-0.5 block truncate text-[9px] font-semibold tracking-[0.29em] text-muted-foreground", children: caption })) : null] }))] }));
|
|
1406
|
+
const cls = cn("flex items-center gap-[11px] rounded-lg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", !compact && "px-4", className);
|
|
1407
|
+
return href ? (jsx(Link, { href: href, className: cls, "aria-label": compact ? name : undefined, children: body })) : (jsx("div", { className: cls, children: body }));
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1410
|
+
function isExternal(href) {
|
|
1411
|
+
return /^https?:\/\//i.test(href);
|
|
1412
|
+
}
|
|
1413
|
+
/**
|
|
1414
|
+
* The card at the foot of the workspace sidebar that points someone who
|
|
1415
|
+
* does not know where to start at the place that will tell them.
|
|
1416
|
+
*/
|
|
1417
|
+
function SidebarHelpCard({ title, description, actionLabel, href, icon, className, }) {
|
|
1418
|
+
const external = isExternal(href);
|
|
1419
|
+
const action = (jsxs(Fragment$1, { children: [actionLabel, jsx(ArrowRight, { className: "size-[15px]" })] }));
|
|
1420
|
+
const actionClass = "mt-3 flex w-full items-center justify-between text-xs font-semibold text-primary hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring rounded";
|
|
1421
|
+
return (jsxs("div", { className: cn("mx-1.5 mb-5 rounded-[13px] border border-primary/10 bg-gradient-to-br from-primary/[0.06] to-primary/[0.02] px-3.5 py-4", className), children: [jsx("span", { className: "mb-[7px] block text-primary/70", children: icon ?? jsx(Compass, { className: "size-6", strokeWidth: 1.6 }) }), jsx("strong", { className: "block text-xs font-semibold", children: title }), description ? (jsx("p", { className: "mt-[7px] text-xs leading-[1.7] text-muted-foreground", children: description })) : null, external ? (jsx("a", { href: href, target: "_blank", rel: "noopener noreferrer", className: actionClass, children: action })) : (jsx(Link, { href: href, className: actionClass, children: action }))] }));
|
|
1422
|
+
}
|
|
1423
|
+
/** A quiet row under the help card — the manual, the support chat. */
|
|
1424
|
+
function SidebarHelpLink({ label, href, icon, className }) {
|
|
1425
|
+
const external = isExternal(href);
|
|
1426
|
+
const cls = cn("flex w-full items-center gap-3 rounded-[10px] px-3.5 py-[11px] text-xs font-medium text-sidebar-foreground/70 transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", className);
|
|
1427
|
+
const body = (jsxs(Fragment$1, { children: [icon ? jsx("span", { className: "shrink-0 [&>svg]:size-[18px]", children: icon }) : null, jsx("span", { className: "flex-1 truncate", children: label }), external ? jsx(ArrowUpRight, { className: "size-4 shrink-0" }) : null] }));
|
|
1428
|
+
return external ? (jsx("a", { href: href, target: "_blank", rel: "noopener noreferrer", className: cls, children: body })) : (jsx(Link, { href: href, className: cls, children: body }));
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1338
1431
|
/**
|
|
1339
1432
|
* Central "no access" screen shared by every policy check (route-level
|
|
1340
1433
|
* PermissionProvider and page-level PermissionGateShell). One look everywhere:
|
|
@@ -2145,5 +2238,5 @@ const getAxiosErrorMessage = (error) => {
|
|
|
2145
2238
|
return String(error);
|
|
2146
2239
|
};
|
|
2147
2240
|
|
|
2148
|
-
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, SidebarProvider, SidebarTrigger, TapMenu, ThemeProvider, 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 };
|
|
2241
|
+
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 };
|
|
2149
2242
|
//# sourceMappingURL=index.esm.js.map
|