@mohasinac/appkit 4.7.2 → 4.7.3

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.
@@ -22,8 +22,9 @@ import { normalizeError } from "../../../../errors/normalize";
22
22
  * the underlying *Sidebar components.
23
23
  */
24
24
  import { useCallback, useEffect, useState, startTransition } from "react";
25
- import { usePathname } from "next/navigation";
25
+ import { usePathname, useRouter } from "next/navigation";
26
26
  import Link from "next/link";
27
+ import { useQueryClient } from "@tanstack/react-query";
27
28
  import { useDashboardNav } from "../../../../features/layout/DashboardNavContext";
28
29
  import { AdminSidebar } from "../../../../features/admin/components/AdminSidebar";
29
30
  import { StoreSidebar } from "../../../../features/seller/components/SellerSidebar";
@@ -33,7 +34,10 @@ import { filterNavItems } from "./filterNavItems";
33
34
  import { useSiteSettings } from "../../../../core/hooks/useSiteSettings";
34
35
  import { useTheme } from "../../theme";
35
36
  import { BackgroundRenderer, Div, Nav, Span } from "../../../../ui";
37
+ import { useToast } from "../../../../ui/components/Toast";
36
38
  import { useVisualViewportInset } from "../../../../react/hooks/useVisualViewportInset";
39
+ import { useSession } from "../../../../react/contexts/SessionContext";
40
+ import { ROUTES } from "../../../../next/routing/route-map";
37
41
  /**
38
42
  * Hoisted drawer-state hook — the matchMedia-aware open/close logic that was
39
43
  * triplicated across admin/store/user layouts. Used internally by
@@ -153,6 +157,24 @@ export function DashboardLayoutClient({ variant, groups, permissions, activeHref
153
157
  const storageKey = `appkit:sidebar-open:${variant}`;
154
158
  const { desktopOpen, mobileOpen, close, closeMobile, toggle } = useResponsiveDrawer(storageKey);
155
159
  useEffect(() => { closeMobile(); }, [pathname, closeMobile]);
160
+ const router = useRouter();
161
+ const { signOut } = useSession();
162
+ const { showToast } = useToast();
163
+ const queryClient = useQueryClient();
164
+ const handleLogout = useCallback(async () => {
165
+ try {
166
+ await signOut();
167
+ void queryClient.invalidateQueries({ queryKey: ["wishlist"] });
168
+ void queryClient.invalidateQueries({ queryKey: ["cart"] });
169
+ void queryClient.invalidateQueries({ queryKey: ["notifications"] });
170
+ showToast("Signed out successfully", "info");
171
+ }
172
+ catch (_err) {
173
+ void normalizeError(_err);
174
+ showToast("Signed out", "info");
175
+ }
176
+ router.push(String(ROUTES.AUTH.LOGIN));
177
+ }, [signOut, queryClient, router, showToast]);
156
178
  const { data: settings } = useSiteSettings();
157
179
  const navConfig = settings?.navConfig;
158
180
  const { theme } = useTheme();
@@ -166,10 +188,8 @@ export function DashboardLayoutClient({ variant, groups, permissions, activeHref
166
188
  ? filteredGroups
167
189
  : groups;
168
190
  const crossNavLinkClass = "flex items-center gap-[var(--appkit-space-2)] rounded-lg px-[var(--appkit-space-3)] py-[var(--appkit-space-2)] text-[0.8125rem] font-medium text-[var(--appkit-color-text-muted)] hover:bg-[var(--appkit-color-surface-elevated)]/60 hover:text-[var(--appkit-color-text)] transition-colors";
169
- const hasCrossNav = Boolean(crossNav?.profileHref || crossNav?.storeHref || crossNav?.adminHref);
170
- const renderCrossNavFooter = hasCrossNav
171
- ? () => (_jsxs(Nav, { "aria-label": "Cross-dashboard links", padding: "y-xs", children: [crossNav?.storeHref && (_jsx(Link, { href: crossNav.storeHref, onClick: closeMobile, className: crossNavLinkClass, children: "Go to my Store" })), crossNav?.adminHref && (_jsx(Link, { href: crossNav.adminHref, onClick: closeMobile, className: crossNavLinkClass, children: "Back to Admin" })), crossNav?.profileHref && (_jsx(Link, { href: crossNav.profileHref, onClick: closeMobile, className: crossNavLinkClass, children: "My Profile" }))] }))
172
- : undefined;
191
+ const logoutBtnClass = "flex w-full items-center gap-[var(--appkit-space-2)] rounded-lg px-[var(--appkit-space-3)] py-[var(--appkit-space-2)] text-[0.8125rem] font-medium text-error transition-colors hover:bg-error-surface hover:text-error";
192
+ const renderCrossNavFooter = () => (_jsxs(Nav, { "aria-label": "Cross-dashboard links", padding: "y-xs", children: [crossNav?.storeHref && (_jsx(Link, { href: crossNav.storeHref, onClick: closeMobile, className: crossNavLinkClass, children: "Go to my Store" })), crossNav?.adminHref && (_jsx(Link, { href: crossNav.adminHref, onClick: closeMobile, className: crossNavLinkClass, children: "Back to Admin" })), crossNav?.profileHref && (_jsx(Link, { href: crossNav.profileHref, onClick: closeMobile, className: crossNavLinkClass, children: "My Profile" })), _jsx("button", { type: "button", onClick: () => { closeMobile(); void handleLogout(); }, className: logoutBtnClass, children: "Log out" })] }));
173
193
  return (_jsxs(_Fragment, { children: [hasBackground && (_jsx(BackgroundRenderer, { mode: theme === "dark" ? "dark" : "light", lightMode: resolvedLightBackground ?? { type: "color", value: "" }, darkMode: resolvedDarkBackground ?? { type: "color", value: "" } })), variant === "admin" && (_jsx(AdminSidebar, { variant: "sidebar", desktopOpen: desktopOpen, mobileOpen: mobileOpen, activePath: activeHref, groups: adminGroups, onCloseMobile: close, onToggle: toggle, className: className, renderFooter: renderCrossNavFooter })), variant === "store" && (_jsx(StoreSidebar, { variant: "sidebar", desktopOpen: desktopOpen, mobileOpen: mobileOpen, activeHref: activeHref, items: [], groups: filteredGroups, onCloseMobile: close, onToggle: toggle, className: className, renderFooter: renderCrossNavFooter })), variant === "user" && (_jsx(UserSidebar, { variant: "sidebar", desktopOpen: desktopOpen, mobileOpen: mobileOpen, items: filteredGroups.flatMap((g) => g.items), groups: filteredGroups, onCloseMobile: close, onToggle: toggle, className: className, renderFooter: renderCrossNavFooter })), _jsx(Div, { className: [
174
194
  "w-full flex-1 flex flex-col min-h-[calc(100dvh-var(--header-height,3.5rem))]",
175
195
  "pb-[var(--appkit-space-16)] lg:pb-[0]", // clears the fixed mobile bottom-nav
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mohasinac/appkit",
3
- "version": "4.7.2",
3
+ "version": "4.7.3",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public"