@eintrek/erp-shell 0.1.12 → 0.1.14

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.
@@ -1,7 +1,13 @@
1
1
  /**
2
- * Invalidate ALL React Query queries when `organizationId` changes
3
- * (skips the initial mount). Use inside the ERP provider so org-scoped
4
- * data is refetched cleanly when the user switches org.
2
+ * Invalidate ALL React Query queries when `organizationId` changes between
3
+ * two real orgs (e.g. the user switches org in the picker). Skips the
4
+ * initial mount and the first-resolve transition (undefined/null/"" x)
5
+ * — that's the URL `[code]` segment finally syncing into the ERP context,
6
+ * not a real switch, and invalidating there triggers a cascade of refetches
7
+ * on top of the queries that already just fired.
8
+ *
9
+ * Use inside the ERP provider so org-scoped data is wiped cleanly when the
10
+ * user really does switch between two orgs.
5
11
  */
6
12
  export declare function useInvalidateQueriesOnOrgChange(organizationId: number | string | null | undefined): void;
7
13
  /**
package/dist/index.esm.js CHANGED
@@ -332,9 +332,15 @@ function useOrganizationIdState(initialOrganizationId, actions) {
332
332
  }
333
333
 
334
334
  /**
335
- * Invalidate ALL React Query queries when `organizationId` changes
336
- * (skips the initial mount). Use inside the ERP provider so org-scoped
337
- * data is refetched cleanly when the user switches org.
335
+ * Invalidate ALL React Query queries when `organizationId` changes between
336
+ * two real orgs (e.g. the user switches org in the picker). Skips the
337
+ * initial mount and the first-resolve transition (undefined/null/"" x)
338
+ * — that's the URL `[code]` segment finally syncing into the ERP context,
339
+ * not a real switch, and invalidating there triggers a cascade of refetches
340
+ * on top of the queries that already just fired.
341
+ *
342
+ * Use inside the ERP provider so org-scoped data is wiped cleanly when the
343
+ * user really does switch between two orgs.
338
344
  */
339
345
  function useInvalidateQueriesOnOrgChange(organizationId) {
340
346
  const queryClient = useQueryClient();
@@ -348,7 +354,15 @@ function useInvalidateQueriesOnOrgChange(organizationId) {
348
354
  }
349
355
  if (previousRef.current === organizationId)
350
356
  return;
357
+ const wasEmpty = previousRef.current === undefined ||
358
+ previousRef.current === null ||
359
+ previousRef.current === "";
351
360
  previousRef.current = organizationId;
361
+ // First-resolve: nothing to invalidate yet (queries either haven't run
362
+ // or are running with the right key already). Real org switches (a → b)
363
+ // still hit the invalidate path below.
364
+ if (wasEmpty)
365
+ return;
352
366
  queryClient.invalidateQueries();
353
367
  }, [organizationId, queryClient]);
354
368
  }
@@ -454,7 +468,7 @@ function SidebarTrigger({ className }) {
454
468
  * Provides a beautiful gradient background that can be customized.
455
469
  */
456
470
  function HeaderBackground({ className }) {
457
- return (jsx("div", { className: cn("absolute top-0 left-0 w-full h-[144px] rounded-br-xl", "bg-gradient-to-r from-[#E4535E] to-[#831015]", className) }));
471
+ return (jsx("div", { className: cn("absolute inset-0 rounded-br-xl", "bg-gradient-to-r from-[#E4535E] to-[#831015]", className) }));
458
472
  }
459
473
 
460
474
  const useSidebarToggle = create(persist((set, get) => ({
@@ -697,11 +711,11 @@ function AppBreadcrumb({ labels = {}, homeLabel = "แดชบอร์ด", ro
697
711
  if (segments.length === 0) {
698
712
  return jsx("h1", { className: "text-xl font-semibold", children: homeLabel });
699
713
  }
700
- return (jsx(Breadcrumb, { children: jsxs(BreadcrumbList, { children: [jsx(BreadcrumbItem, { className: "hidden md:block", children: jsx(BreadcrumbLink, { asChild: true, children: jsx(Link, { href: "/", className: "font-thai text-12[px] xl:text-base font-normal text-white/80 hover:text-white transition-colors", children: rootLabel }) }) }), segments.map((segment, index) => {
714
+ return (jsx(Breadcrumb, { children: jsxs(BreadcrumbList, { children: [jsx(BreadcrumbItem, { className: "hidden md:block", children: jsx(BreadcrumbLink, { asChild: true, children: jsx(Link, { href: "/", className: "font-thai text-[14px] font-normal text-white/80 hover:text-white transition-colors", children: rootLabel }) }) }), segments.map((segment, index) => {
701
715
  const href = "/" + segments.slice(0, index + 1).join("/");
702
716
  const isLast = index === segments.length - 1;
703
717
  const label = labels[segment] || segment;
704
- return (jsxs(Fragment, { children: [jsx(BreadcrumbSeparator, { className: "hidden md:block text-white/80", children: jsx(ChevronRight, { strokeWidth: 2, className: "h-4 w-4" }) }), jsx(BreadcrumbItem, { children: isLast ? (jsx(BreadcrumbPage, { className: "font-thai text-[12px] md:text-[10px] lg:text-base font-bold text-white leading-none", children: decodeURIComponent(label) })) : (jsx(BreadcrumbLink, { asChild: true, children: jsx(Link, { href: href, className: "font-thai text-[11px] md:text-[11px] lg:text-base font-normal text-white/80 hover:text-white transition-colors leading-none", children: decodeURIComponent(label) }) })) })] }, `${segment}-${index}`));
718
+ return (jsxs(Fragment, { children: [jsx(BreadcrumbSeparator, { className: "hidden md:block text-white/80", children: jsx(ChevronRight, { strokeWidth: 2, className: "h-4 w-4" }) }), jsx(BreadcrumbItem, { children: isLast ? (jsx(BreadcrumbPage, { className: "font-thai text-[14px] font-bold text-white/95 leading-none", children: decodeURIComponent(label) })) : (jsx(BreadcrumbLink, { asChild: true, children: jsx(Link, { href: href, className: "font-thai text-[14px] font-normal text-white/80 hover:text-white transition-colors leading-none", children: decodeURIComponent(label) }) })) })] }, `${segment}-${index}`));
705
719
  })] }) }));
706
720
  }
707
721
 
@@ -1031,7 +1045,7 @@ function AppLayoutShell({ children, sidebar, loadingComponent, breadcrumb, permi
1031
1045
  const contentMargin = open && !isSidebarModalLayout ? "ml-[21.5rem]" : "";
1032
1046
  const needsLeftGutter = !(open && !isSidebarModalLayout);
1033
1047
  const wrap = permissionProvider ?? ((c) => c);
1034
- 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-6", 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-[100px] sm:h-[144px] 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 pb-12", needsLeftGutter && "pl-6"), children: wrap(children) }, `org-${organizationId ?? "no-org"}`) })] }) })] }));
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 pb-12", needsLeftGutter && "pl-6"), children: wrap(children) }, `org-${organizationId ?? "no-org"}`) })] }) })] }));
1035
1049
  }
1036
1050
  /** Local tiny classnames helper — avoids pulling clsx/tailwind-merge into
1037
1051
  * the shell just for the layout file. Falsy values are skipped. */