@eintrek/erp-shell 0.1.16 → 0.1.18
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.esm.js +23 -5
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +23 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -980,6 +980,16 @@ function AppLayoutShell({ children, sidebar, loadingComponent, breadcrumb, permi
|
|
|
980
980
|
const params = useParams();
|
|
981
981
|
const code = params?.code;
|
|
982
982
|
const extendedSession = session;
|
|
983
|
+
// Track once-authenticated so a transient accessToken drop during the
|
|
984
|
+
// periodic session refresh (SessionRefreshTrigger every 4 min) doesn't
|
|
985
|
+
// blank the whole page. The initial-load gate below still handles cold
|
|
986
|
+
// start; once we've seen a real token we render children optimistically
|
|
987
|
+
// and let the API layer surface a real 401 if the token actually died.
|
|
988
|
+
const hasSeenAccessTokenRef = useRef(false);
|
|
989
|
+
useEffect(() => {
|
|
990
|
+
if (extendedSession?.accessToken)
|
|
991
|
+
hasSeenAccessTokenRef.current = true;
|
|
992
|
+
}, [extendedSession?.accessToken]);
|
|
983
993
|
// Find the org from the URL `[code]` so we can detect a context mismatch
|
|
984
994
|
// (the user bookmarked a different org than the cookie remembers).
|
|
985
995
|
const orgFromCode = React.useMemo(() => {
|
|
@@ -1022,9 +1032,15 @@ function AppLayoutShell({ children, sidebar, loadingComponent, breadcrumb, permi
|
|
|
1022
1032
|
if (status === "loading" && !session) {
|
|
1023
1033
|
return jsx(Fragment$1, { children: loadingComponent });
|
|
1024
1034
|
}
|
|
1025
|
-
// Session loaded but no accessToken
|
|
1026
|
-
//
|
|
1027
|
-
|
|
1035
|
+
// Session loaded but no accessToken AND we've never seen one → real auth
|
|
1036
|
+
// failure (token refresh gave nothing back on cold start), bounce through
|
|
1037
|
+
// signin. If we HAVE seen one before, the drop is almost certainly the
|
|
1038
|
+
// in-flight periodic refresh (SessionRefreshTrigger). Don't redirect on
|
|
1039
|
+
// that transient — the JWT callback will settle in a moment and API
|
|
1040
|
+
// calls will keep working with the still-valid cookie.
|
|
1041
|
+
if (status === "authenticated" &&
|
|
1042
|
+
!extendedSession?.accessToken &&
|
|
1043
|
+
!hasSeenAccessTokenRef.current) {
|
|
1028
1044
|
if (typeof window !== "undefined") {
|
|
1029
1045
|
const url = new URL(signInUrl, window.location.origin);
|
|
1030
1046
|
url.searchParams.set("error", "NoAccessToken");
|
|
@@ -1033,7 +1049,9 @@ function AppLayoutShell({ children, sidebar, loadingComponent, breadcrumb, permi
|
|
|
1033
1049
|
}
|
|
1034
1050
|
return jsx(Fragment$1, { children: loadingComponent });
|
|
1035
1051
|
}
|
|
1036
|
-
|
|
1052
|
+
// Only blank the page when we've never seen a token — otherwise the
|
|
1053
|
+
// periodic session refresh would visibly flash the loader every 4 min.
|
|
1054
|
+
if (!extendedSession?.accessToken && !hasSeenAccessTokenRef.current) {
|
|
1037
1055
|
return jsx(Fragment$1, { children: loadingComponent });
|
|
1038
1056
|
}
|
|
1039
1057
|
if (!code) {
|
|
@@ -1045,7 +1063,7 @@ function AppLayoutShell({ children, sidebar, loadingComponent, breadcrumb, permi
|
|
|
1045
1063
|
const contentMargin = open && !isSidebarModalLayout ? "ml-[21.5rem]" : "";
|
|
1046
1064
|
const needsLeftGutter = !(open && !isSidebarModalLayout);
|
|
1047
1065
|
const wrap = permissionProvider ?? ((c) => c);
|
|
1048
|
-
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
|
|
1066
|
+
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: wrap(children) }, `org-${organizationId ?? "no-org"}`) })] }) })] }));
|
|
1049
1067
|
}
|
|
1050
1068
|
/** Local tiny classnames helper — avoids pulling clsx/tailwind-merge into
|
|
1051
1069
|
* the shell just for the layout file. Falsy values are skipped. */
|