@rqdhw3n/react-admin-layout 1.0.0 → 1.0.2

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 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/utils/storage.ts","../src/context/LayoutContext.tsx","../src/hooks/useSidebar.ts","../src/utils/breadcrumbs.ts","../node_modules/clsx/dist/clsx.mjs","../src/utils/cn.ts","../src/components/AdminLayoutRouterSync.tsx","../src/components/Footer.tsx","../src/utils/permissions.ts","../src/components/SidebarGroup.tsx","../src/components/SidebarItem.tsx","../src/components/MobileSidebar.tsx","../src/components/Breadcrumbs.tsx","../src/components/NavbarSearch.tsx","../src/components/NotificationMenu.tsx","../src/hooks/useDarkMode.ts","../src/components/ThemeToggle.tsx","../src/components/UserMenu.tsx","../src/components/Navbar.tsx","../src/components/Sidebar.tsx","../src/components/AdminLayout.tsx","../src/components/RouterLink.tsx","../src/hooks/useLayoutState.ts","../src/hooks/useBreadcrumbs.ts"],"sourcesContent":["import type { LayoutState } from '../types'\r\n\r\nexport type PersistedLayout = Pick<LayoutState, 'sidebarCollapsed' | 'darkMode'>\r\n\r\nexport function loadLayoutState(key: string): Partial<PersistedLayout> {\r\n if (typeof window === 'undefined') return {}\r\n try {\r\n const raw = localStorage.getItem(key)\r\n return raw ? (JSON.parse(raw) as Partial<PersistedLayout>) : {}\r\n } catch {\r\n return {}\r\n }\r\n}\r\n\r\nexport function saveLayoutState(key: string, state: PersistedLayout): void {\r\n if (typeof window === 'undefined') return\r\n try {\r\n localStorage.setItem(key, JSON.stringify(state))\r\n } catch {\r\n /* ignore quota errors */\r\n }\r\n}\r\n","import {\r\n createContext,\r\n useCallback,\r\n useContext,\r\n useEffect,\r\n useMemo,\r\n useState,\r\n type ReactNode,\r\n} from 'react'\r\nimport type { BreadcrumbItem, LayoutContextValue, PermissionsMap } from '../types'\r\nimport { loadLayoutState, saveLayoutState } from '../utils/storage'\r\n\r\nconst LayoutContext = createContext<LayoutContextValue | null>(null)\r\n\r\nexport type LayoutProviderProps = {\r\n children: ReactNode\r\n storageKey?: string\r\n defaultCollapsed?: boolean\r\n permissions?: PermissionsMap\r\n initialBreadcrumbs?: BreadcrumbItem[]\r\n initialActivePath?: string\r\n initialDarkMode?: boolean\r\n}\r\n\r\nexport function LayoutProvider({\r\n children,\r\n storageKey = 'rqdhw3n-admin-layout',\r\n defaultCollapsed = false,\r\n permissions = {},\r\n initialBreadcrumbs = [],\r\n initialActivePath = '/',\r\n initialDarkMode,\r\n}: LayoutProviderProps) {\r\n const persisted = loadLayoutState(storageKey)\r\n\r\n const [sidebarCollapsed, setSidebarCollapsed] = useState(\r\n persisted.sidebarCollapsed ?? defaultCollapsed,\r\n )\r\n const [mobileOpen, setMobileOpen] = useState(false)\r\n const [darkMode, setDarkMode] = useState(\r\n persisted.darkMode ?? initialDarkMode ?? false,\r\n )\r\n const [breadcrumbs, setBreadcrumbs] = useState<BreadcrumbItem[]>(initialBreadcrumbs)\r\n const [activePath, setActivePath] = useState(initialActivePath)\r\n\r\n useEffect(() => {\r\n saveLayoutState(storageKey, { sidebarCollapsed, darkMode })\r\n }, [storageKey, sidebarCollapsed, darkMode])\r\n\r\n useEffect(() => {\r\n const root = document.documentElement\r\n if (darkMode) root.classList.add('dark')\r\n else root.classList.remove('dark')\r\n }, [darkMode])\r\n\r\n const toggleSidebar = useCallback(() => setSidebarCollapsed((v) => !v), [])\r\n const toggleMobile = useCallback(() => setMobileOpen((v) => !v), [])\r\n const toggleDarkMode = useCallback(() => setDarkMode((v) => !v), [])\r\n\r\n const value = useMemo<LayoutContextValue>(\r\n () => ({\r\n sidebarCollapsed,\r\n mobileOpen,\r\n darkMode,\r\n toggleSidebar,\r\n setSidebarCollapsed,\r\n toggleMobile,\r\n setMobileOpen,\r\n toggleDarkMode,\r\n setDarkMode,\r\n permissions,\r\n breadcrumbs,\r\n setBreadcrumbs,\r\n activePath,\r\n setActivePath,\r\n }),\r\n [\r\n sidebarCollapsed,\r\n mobileOpen,\r\n darkMode,\r\n toggleSidebar,\r\n toggleMobile,\r\n toggleDarkMode,\r\n permissions,\r\n breadcrumbs,\r\n activePath,\r\n ],\r\n )\r\n\r\n return <LayoutContext.Provider value={value}>{children}</LayoutContext.Provider>\r\n}\r\n\r\nexport function useLayoutContext(): LayoutContextValue {\r\n const ctx = useContext(LayoutContext)\r\n if (!ctx) {\r\n throw new Error('useLayoutContext must be used within LayoutProvider / AdminLayout')\r\n }\r\n return ctx\r\n}\r\n","import { useLayoutContext } from '../context/LayoutContext'\r\n\r\nexport function useSidebar() {\r\n const {\r\n sidebarCollapsed,\r\n mobileOpen,\r\n toggleSidebar,\r\n setSidebarCollapsed,\r\n toggleMobile,\r\n setMobileOpen,\r\n } = useLayoutContext()\r\n\r\n return {\r\n collapsed: sidebarCollapsed,\r\n mobileOpen,\r\n toggle: toggleSidebar,\r\n setCollapsed: setSidebarCollapsed,\r\n toggleMobile,\r\n setMobileOpen,\r\n closeMobile: () => setMobileOpen(false),\r\n }\r\n}\r\n","import type { BreadcrumbItem } from '../types'\r\n\r\nexport function generateBreadcrumbsFromPath(pathname: string): BreadcrumbItem[] {\r\n const segments = pathname.split('/').filter(Boolean)\r\n if (!segments.length) return [{ label: 'Home', path: '/' }]\r\n\r\n return segments.map((seg, i) => {\r\n const path = '/' + segments.slice(0, i + 1).join('/')\r\n const label = seg\r\n .replace(/-/g, ' ')\r\n .replace(/\\b\\w/g, (c) => c.toUpperCase())\r\n return { label, path: i < segments.length - 1 ? path : undefined }\r\n })\r\n}\r\n","function r(e){var t,f,n=\"\";if(\"string\"==typeof e||\"number\"==typeof e)n+=e;else if(\"object\"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=\" \"),n+=f)}else for(f in e)e[f]&&(n&&(n+=\" \"),n+=f);return n}export function clsx(){for(var e,t,f=0,n=\"\",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=\" \"),n+=t);return n}export default clsx;","import clsx, { type ClassValue } from 'clsx'\r\n\r\nexport function cn(...inputs: ClassValue[]): string {\r\n return clsx(inputs)\r\n}\r\n","import { useEffect, type ReactNode } from 'react'\r\nimport { useLocation } from 'react-router-dom'\r\nimport { useLayoutContext } from '../context/LayoutContext'\r\nimport { generateBreadcrumbsFromPath } from '../utils/breadcrumbs'\r\n\r\nexport type AdminLayoutRouterSyncProps = {\r\n children: ReactNode\r\n}\r\n\r\nexport function AdminLayoutRouterSync({ children }: AdminLayoutRouterSyncProps) {\r\n const { pathname } = useLocation()\r\n const { setActivePath, setBreadcrumbs, breadcrumbs: manualBreadcrumbs } = useLayoutContext()\r\n\r\n useEffect(() => {\r\n setActivePath(pathname)\r\n if (!manualBreadcrumbs.length) {\r\n setBreadcrumbs(generateBreadcrumbsFromPath(pathname))\r\n }\r\n }, [pathname, setActivePath, setBreadcrumbs, manualBreadcrumbs.length])\r\n\r\n return <>{children}</>\r\n}\r\n","import { cn } from '../utils/cn'\r\n\r\nexport type FooterProps = {\r\n children?: React.ReactNode\r\n className?: string\r\n}\r\n\r\nexport function Footer({ children, className }: FooterProps) {\r\n return (\r\n <footer\r\n className={cn(\r\n 'mt-auto border-t border-admin-border bg-admin-surface px-6 py-4 text-sm text-admin-muted',\r\n className,\r\n )}\r\n >\r\n {children ?? (\r\n <p className='text-center'>\r\n © {new Date().getFullYear()} Admin Layout · Built with @rqdhw3n/react-admin-layout\r\n </p>\r\n )}\r\n </footer>\r\n )\r\n}\r\n","import type { PermissionsMap, SidebarItemType } from '../types'\r\n\r\nexport function parsePermission(permission: string): { resource: string; action: string } {\r\n const dot = permission.indexOf('.')\r\n if (dot === -1) return { resource: permission, action: 'view' }\r\n return {\r\n resource: permission.slice(0, dot),\r\n action: permission.slice(dot + 1),\r\n }\r\n}\r\n\r\nexport function hasPermission(\r\n permissions: PermissionsMap,\r\n permission?: string,\r\n): boolean {\r\n if (!permission) return true\r\n const { resource, action } = parsePermission(permission)\r\n const allowed = permissions[resource]\r\n if (!allowed?.length) return false\r\n return allowed.includes(action) || allowed.includes('*')\r\n}\r\n\r\nexport function filterSidebarByPermissions(\r\n items: SidebarItemType[],\r\n permissions: PermissionsMap,\r\n): SidebarItemType[] {\r\n return items\r\n .filter((item) => hasPermission(permissions, item.permission))\r\n .map((item) => ({\r\n ...item,\r\n children: item.children\r\n ? filterSidebarByPermissions(item.children, permissions)\r\n : undefined,\r\n }))\r\n .filter((item) => !item.children?.length || item.children.length > 0 || item.path)\r\n}\r\n","import type { ReactNode } from 'react'\r\nimport { cn } from '../utils/cn'\r\n\r\nexport type SidebarGroupProps = {\r\n label?: string\r\n children: ReactNode\r\n collapsed?: boolean\r\n className?: string\r\n}\r\n\r\nexport function SidebarGroup({ label, children, collapsed, className }: SidebarGroupProps) {\r\n return (\r\n <div className={cn('mb-4', className)}>\r\n {label && !collapsed && (\r\n <p className='mb-2 px-3 text-[11px] font-semibold uppercase tracking-wider text-admin-muted'>\r\n {label}\r\n </p>\r\n )}\r\n <ul className='space-y-0.5'>{children}</ul>\r\n </div>\r\n )\r\n}\r\n","import { ChevronDown } from 'lucide-react'\r\nimport { useState } from 'react'\r\nimport type { SidebarItemType } from '../types'\r\nimport { cn } from '../utils/cn'\r\n\r\nexport type SidebarItemProps = {\r\n item: SidebarItemType\r\n collapsed?: boolean\r\n depth?: number\r\n activePath?: string\r\n onNavigate?: (path: string) => void\r\n LinkComponent?: React.ComponentType<{\r\n to: string\r\n className?: string\r\n children: React.ReactNode\r\n onClick?: () => void\r\n }>\r\n onItemClick?: () => void\r\n}\r\n\r\nfunction isActive(path: string | undefined, activePath: string): boolean {\r\n if (!path) return false\r\n return activePath === path || activePath.startsWith(`${path}/`)\r\n}\r\n\r\nexport function SidebarItem({\r\n item,\r\n collapsed = false,\r\n depth = 0,\r\n activePath = '/',\r\n onNavigate,\r\n LinkComponent,\r\n onItemClick,\r\n}: SidebarItemProps) {\r\n const hasChildren = Boolean(item.children?.length)\r\n const active = item.path ? isActive(item.path, activePath) : false\r\n const childActive = item.children?.some((c) => c.path && isActive(c.path, activePath))\r\n const [open, setOpen] = useState(active || childActive)\r\n\r\n const Icon = item.icon\r\n\r\n const baseClass = cn(\r\n 'group flex w-full items-center gap-3 rounded-lg px-3 py-2.5 text-sm font-medium transition-all duration-200',\r\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-admin-primary',\r\n active || childActive\r\n ? 'bg-admin-primary text-white shadow-sm'\r\n : 'text-admin-muted hover:bg-admin-bg hover:text-admin-text',\r\n item.disabled && 'pointer-events-none opacity-50',\r\n depth > 0 && 'text-[13px] py-2',\r\n )\r\n\r\n const content = (\r\n <>\r\n {Icon && (\r\n <Icon\r\n className={cn('h-[18px] w-[18px] shrink-0', active || childActive ? 'text-white' : '')}\r\n aria-hidden\r\n />\r\n )}\r\n {!collapsed && (\r\n <>\r\n <span className='flex-1 truncate text-left'>{item.label}</span>\r\n {item.badge != null && (\r\n <span\r\n className={cn(\r\n 'rounded-full px-2 py-0.5 text-[11px] font-semibold',\r\n active ? 'bg-white/20 text-white' : 'bg-admin-primary/10 text-admin-primary',\r\n )}\r\n >\r\n {item.badge}\r\n </span>\r\n )}\r\n {hasChildren && (\r\n <ChevronDown\r\n className={cn('h-4 w-4 shrink-0 transition-transform', open && 'rotate-180')}\r\n aria-hidden\r\n />\r\n )}\r\n </>\r\n )}\r\n </>\r\n )\r\n\r\n const handleClick = () => {\r\n if (hasChildren) {\r\n setOpen((v) => !v)\r\n return\r\n }\r\n if (item.path) {\r\n onNavigate?.(item.path)\r\n onItemClick?.()\r\n }\r\n }\r\n\r\n const row =\r\n item.path && !hasChildren && LinkComponent ? (\r\n <LinkComponent\r\n to={item.path}\r\n className={baseClass}\r\n onClick={() => {\r\n onItemClick?.()\r\n }}\r\n >\r\n {content}\r\n </LinkComponent>\r\n ) : (\r\n <button type='button' className={baseClass} onClick={handleClick} disabled={item.disabled}>\r\n {content}\r\n </button>\r\n )\r\n\r\n return (\r\n <li>\r\n {row}\r\n {hasChildren && open && !collapsed && (\r\n <ul className='mt-1 space-y-0.5 border-l border-admin-border ml-5 pl-2'>\r\n {item.children!.map((child) => (\r\n <SidebarItem\r\n key={child.label + (child.path ?? '')}\r\n item={child}\r\n collapsed={collapsed}\r\n depth={depth + 1}\r\n activePath={activePath}\r\n onNavigate={onNavigate}\r\n LinkComponent={LinkComponent}\r\n onItemClick={onItemClick}\r\n />\r\n ))}\r\n </ul>\r\n )}\r\n </li>\r\n )\r\n}\r\n","import { X } from 'lucide-react'\r\nimport { useEffect } from 'react'\r\nimport { useSidebar } from '../hooks/useSidebar'\r\nimport { useLayoutContext } from '../context/LayoutContext'\r\nimport type { SidebarProps } from '../types'\r\nimport { filterSidebarByPermissions } from '../utils/permissions'\r\nimport { cn } from '../utils/cn'\r\nimport { SidebarGroup } from './SidebarGroup'\r\nimport { SidebarItem } from './SidebarItem'\r\n\r\nexport type MobileSidebarProps = SidebarProps\r\n\r\nexport function MobileSidebar({\r\n items,\r\n appName = 'Admin',\r\n appLogo,\r\n onNavigate,\r\n activePath: activePathProp,\r\n LinkComponent,\r\n}: MobileSidebarProps) {\r\n const { mobileOpen, closeMobile } = useSidebar()\r\n const { permissions, activePath: ctxPath } = useLayoutContext()\r\n const activePath = activePathProp ?? ctxPath\r\n const filtered = filterSidebarByPermissions(items, permissions)\r\n\r\n useEffect(() => {\r\n if (!mobileOpen) return\r\n const onKey = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') closeMobile()\r\n }\r\n document.addEventListener('keydown', onKey)\r\n document.body.style.overflow = 'hidden'\r\n return () => {\r\n document.removeEventListener('keydown', onKey)\r\n document.body.style.overflow = ''\r\n }\r\n }, [mobileOpen, closeMobile])\r\n\r\n if (!mobileOpen) return null\r\n\r\n const handleNavigate = (path: string) => {\r\n onNavigate?.(path)\r\n closeMobile()\r\n }\r\n\r\n return (\r\n <div className='fixed inset-0 z-50 lg:hidden' role='dialog' aria-modal='true'>\r\n <button\r\n type='button'\r\n className='absolute inset-0 bg-slate-900/50 backdrop-blur-sm animate-fade-in'\r\n aria-label='Close menu'\r\n onClick={closeMobile}\r\n />\r\n <aside\r\n className={cn(\r\n 'absolute left-0 top-0 flex h-full w-[min(280px,85vw)] flex-col',\r\n 'border-r border-admin-border bg-admin-surface shadow-admin-lg animate-slide-in',\r\n )}\r\n >\r\n <div className='flex h-16 items-center justify-between border-b border-admin-border px-4'>\r\n <div className='flex items-center gap-3'>\r\n {appLogo ?? (\r\n <div className='flex h-9 w-9 items-center justify-center rounded-xl bg-admin-primary text-sm font-bold text-white'>\r\n {appName.charAt(0)}\r\n </div>\r\n )}\r\n <span className='font-semibold text-admin-text'>{appName}</span>\r\n </div>\r\n <button\r\n type='button'\r\n onClick={closeMobile}\r\n className='rounded-lg p-2 text-admin-muted hover:bg-admin-bg'\r\n aria-label='Close sidebar'\r\n >\r\n <X className='h-5 w-5' />\r\n </button>\r\n </div>\r\n <nav className='flex-1 overflow-y-auto p-3'>\r\n <SidebarGroup>\r\n {filtered.map((item) => (\r\n <SidebarItem\r\n key={item.label + (item.path ?? '')}\r\n item={item}\r\n activePath={activePath}\r\n onNavigate={handleNavigate}\r\n LinkComponent={LinkComponent}\r\n onItemClick={closeMobile}\r\n />\r\n ))}\r\n </SidebarGroup>\r\n </nav>\r\n </aside>\r\n </div>\r\n )\r\n}\r\n","import { ChevronRight, Home } from 'lucide-react'\r\nimport type { BreadcrumbItem } from '../types'\r\nimport { cn } from '../utils/cn'\r\n\r\nexport type BreadcrumbsProps = {\r\n items: BreadcrumbItem[]\r\n className?: string\r\n LinkComponent?: React.ComponentType<{\r\n to: string\r\n className?: string\r\n children: React.ReactNode\r\n }>\r\n onNavigate?: (path: string) => void\r\n}\r\n\r\nexport function Breadcrumbs({\r\n items,\r\n className,\r\n LinkComponent,\r\n onNavigate,\r\n}: BreadcrumbsProps) {\r\n if (!items.length) return null\r\n\r\n const renderLink = (item: BreadcrumbItem, isLast: boolean) => {\r\n const classNames = cn(\r\n 'text-sm transition-colors',\r\n isLast ? 'font-medium text-admin-text' : 'text-admin-muted hover:text-admin-text',\r\n )\r\n\r\n if (!item.path || isLast) {\r\n return <span className={classNames}>{item.label}</span>\r\n }\r\n\r\n if (LinkComponent) {\r\n return (\r\n <LinkComponent to={item.path} className={classNames}>\r\n {item.label}\r\n </LinkComponent>\r\n )\r\n }\r\n\r\n return (\r\n <button type='button' className={classNames} onClick={() => onNavigate?.(item.path!)}>\r\n {item.label}\r\n </button>\r\n )\r\n }\r\n\r\n return (\r\n <nav aria-label='Breadcrumb' className={cn('flex items-center gap-1.5', className)}>\r\n <Home className='h-4 w-4 text-admin-muted shrink-0' aria-hidden />\r\n {items.map((item, index) => {\r\n const isLast = index === items.length - 1\r\n return (\r\n <span key={`${item.label}-${index}`} className='flex items-center gap-1.5'>\r\n <ChevronRight className='h-3.5 w-3.5 text-admin-muted' aria-hidden />\r\n {renderLink(item, isLast)}\r\n </span>\r\n )\r\n })}\r\n </nav>\r\n )\r\n}\r\n","import { Search } from 'lucide-react'\r\nimport { useState, type FormEvent } from 'react'\r\nimport { cn } from '../utils/cn'\r\n\r\nexport type NavbarSearchProps = {\r\n placeholder?: string\r\n onSearch?: (query: string) => void\r\n className?: string\r\n}\r\n\r\nexport function NavbarSearch({\r\n placeholder = 'Search...',\r\n onSearch,\r\n className,\r\n}: NavbarSearchProps) {\r\n const [query, setQuery] = useState('')\r\n\r\n const handleSubmit = (e: FormEvent) => {\r\n e.preventDefault()\r\n onSearch?.(query.trim())\r\n }\r\n\r\n return (\r\n <form onSubmit={handleSubmit} className={cn('relative w-full max-w-md', className)}>\r\n <Search\r\n className='pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-admin-muted'\r\n aria-hidden\r\n />\r\n <input\r\n type='search'\r\n value={query}\r\n onChange={(e) => setQuery(e.target.value)}\r\n placeholder={placeholder}\r\n className={cn(\r\n 'h-10 w-full rounded-xl border border-admin-border bg-admin-bg pl-10 pr-4 text-sm text-admin-text',\r\n 'placeholder:text-admin-muted focus:border-admin-primary focus:outline-none focus:ring-2 focus:ring-admin-primary/20',\r\n )}\r\n aria-label='Search'\r\n />\r\n </form>\r\n )\r\n}\r\n","import { Bell } from 'lucide-react'\r\nimport { useEffect, useRef, useState } from 'react'\r\nimport type { NotificationItem } from '../types'\r\nimport { cn } from '../utils/cn'\r\n\r\nexport type NotificationMenuProps = {\r\n notifications?: NotificationItem[]\r\n className?: string\r\n}\r\n\r\nexport function NotificationMenu({ notifications = [], className }: NotificationMenuProps) {\r\n const [open, setOpen] = useState(false)\r\n const ref = useRef<HTMLDivElement>(null)\r\n const unread = notifications.filter((n) => !n.read).length\r\n\r\n useEffect(() => {\r\n const handler = (e: MouseEvent) => {\r\n if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false)\r\n }\r\n document.addEventListener('mousedown', handler)\r\n return () => document.removeEventListener('mousedown', handler)\r\n }, [])\r\n\r\n return (\r\n <div ref={ref} className={cn('relative', className)}>\r\n <button\r\n type='button'\r\n onClick={() => setOpen((v) => !v)}\r\n className={cn(\r\n 'relative inline-flex h-9 w-9 items-center justify-center rounded-lg border border-admin-border',\r\n 'bg-admin-surface text-admin-muted transition-colors hover:bg-admin-bg hover:text-admin-text',\r\n 'focus-visible:ring-2 focus-visible:ring-admin-primary',\r\n )}\r\n aria-label={`Notifications${unread ? `, ${unread} unread` : ''}`}\r\n aria-expanded={open}\r\n >\r\n <Bell className='h-4 w-4' aria-hidden />\r\n {unread > 0 && (\r\n <span className='absolute -right-0.5 -top-0.5 flex h-4 min-w-4 items-center justify-center rounded-full bg-red-500 px-1 text-[10px] font-bold text-white'>\r\n {unread > 9 ? '9+' : unread}\r\n </span>\r\n )}\r\n </button>\r\n\r\n {open && (\r\n <div className='absolute right-0 top-full z-50 mt-2 w-80 rounded-xl border border-admin-border bg-admin-surface shadow-admin-lg animate-fade-in'>\r\n <div className='border-b border-admin-border px-4 py-3'>\r\n <p className='text-sm font-semibold text-admin-text'>Notifications</p>\r\n </div>\r\n <ul className='max-h-72 overflow-y-auto p-2'>\r\n {notifications.length === 0 ? (\r\n <li className='px-3 py-6 text-center text-sm text-admin-muted'>No notifications</li>\r\n ) : (\r\n notifications.map((n) => (\r\n <li\r\n key={n.id}\r\n className={cn(\r\n 'rounded-lg px-3 py-2.5 transition-colors hover:bg-admin-bg',\r\n !n.read && 'bg-admin-primary/5',\r\n )}\r\n >\r\n <p className='text-sm font-medium text-admin-text'>{n.title}</p>\r\n {n.description && (\r\n <p className='mt-0.5 text-xs text-admin-muted line-clamp-2'>{n.description}</p>\r\n )}\r\n {n.time && <p className='mt-1 text-[11px] text-admin-muted'>{n.time}</p>}\r\n </li>\r\n ))\r\n )}\r\n </ul>\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n","import { useLayoutContext } from '../context/LayoutContext'\r\n\r\nexport function useDarkMode() {\r\n const { darkMode, toggleDarkMode, setDarkMode } = useLayoutContext()\r\n return {\r\n isDark: darkMode,\r\n toggle: toggleDarkMode,\r\n setDarkMode,\r\n }\r\n}\r\n","import { Moon, Sun } from 'lucide-react'\r\nimport { useDarkMode } from '../hooks/useDarkMode'\r\nimport { cn } from '../utils/cn'\r\n\r\nexport type ThemeToggleProps = {\r\n className?: string\r\n}\r\n\r\nexport function ThemeToggle({ className }: ThemeToggleProps) {\r\n const { isDark, toggle } = useDarkMode()\r\n\r\n return (\r\n <button\r\n type='button'\r\n onClick={toggle}\r\n className={cn(\r\n 'inline-flex h-9 w-9 items-center justify-center rounded-lg border border-admin-border',\r\n 'bg-admin-surface text-admin-muted transition-colors hover:bg-admin-bg hover:text-admin-text',\r\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-admin-primary focus-visible:ring-offset-2',\r\n className,\r\n )}\r\n aria-label={isDark ? 'Switch to light mode' : 'Switch to dark mode'}\r\n >\r\n {isDark ? <Sun className='h-4 w-4' aria-hidden /> : <Moon className='h-4 w-4' aria-hidden />}\r\n </button>\r\n )\r\n}\r\n","import { ChevronDown, LogOut, Settings, User } from 'lucide-react'\r\nimport { useEffect, useRef, useState } from 'react'\r\nimport type { AdminUser } from '../types'\r\nimport { cn } from '../utils/cn'\r\n\r\nexport type UserMenuProps = {\r\n user: AdminUser\r\n onLogout?: () => void\r\n onSettings?: () => void\r\n className?: string\r\n}\r\n\r\nexport function UserMenu({ user, onLogout, onSettings, className }: UserMenuProps) {\r\n const [open, setOpen] = useState(false)\r\n const ref = useRef<HTMLDivElement>(null)\r\n\r\n useEffect(() => {\r\n const handler = (e: MouseEvent) => {\r\n if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false)\r\n }\r\n document.addEventListener('mousedown', handler)\r\n return () => document.removeEventListener('mousedown', handler)\r\n }, [])\r\n\r\n const initials = user.name\r\n .split(' ')\r\n .map((n) => n[0])\r\n .join('')\r\n .slice(0, 2)\r\n .toUpperCase()\r\n\r\n return (\r\n <div ref={ref} className={cn('relative', className)}>\r\n <button\r\n type='button'\r\n onClick={() => setOpen((v) => !v)}\r\n className={cn(\r\n 'flex items-center gap-2 rounded-xl border border-admin-border bg-admin-surface px-2 py-1.5',\r\n 'transition-colors hover:bg-admin-bg focus-visible:ring-2 focus-visible:ring-admin-primary',\r\n )}\r\n aria-expanded={open}\r\n aria-haspopup='menu'\r\n >\r\n {user.avatar ? (\r\n <img src={user.avatar} alt='' className='h-8 w-8 rounded-lg object-cover' />\r\n ) : (\r\n <div className='flex h-8 w-8 items-center justify-center rounded-lg bg-admin-primary text-xs font-semibold text-white'>\r\n {initials}\r\n </div>\r\n )}\r\n <div className='hidden text-left sm:block'>\r\n <p className='text-sm font-medium text-admin-text leading-tight'>{user.name}</p>\r\n <p className='text-xs text-admin-muted leading-tight'>{user.email}</p>\r\n </div>\r\n <ChevronDown className='hidden h-4 w-4 text-admin-muted sm:block' aria-hidden />\r\n </button>\r\n\r\n {open && (\r\n <div\r\n role='menu'\r\n className='absolute right-0 top-full z-50 mt-2 w-56 rounded-xl border border-admin-border bg-admin-surface p-1.5 shadow-admin-lg animate-fade-in'\r\n >\r\n <button\r\n type='button'\r\n role='menuitem'\r\n className='flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm text-admin-text hover:bg-admin-bg'\r\n onClick={() => {\r\n onSettings?.()\r\n setOpen(false)\r\n }}\r\n >\r\n <Settings className='h-4 w-4 text-admin-muted' />\r\n Settings\r\n </button>\r\n <button\r\n type='button'\r\n role='menuitem'\r\n className='flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm text-admin-text hover:bg-admin-bg'\r\n >\r\n <User className='h-4 w-4 text-admin-muted' />\r\n Profile\r\n </button>\r\n <hr className='my-1 border-admin-border' />\r\n <button\r\n type='button'\r\n role='menuitem'\r\n className='flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm text-red-600 hover:bg-red-50 dark:hover:bg-red-950/30'\r\n onClick={() => {\r\n onLogout?.()\r\n setOpen(false)\r\n }}\r\n >\r\n <LogOut className='h-4 w-4' />\r\n Log out\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n","import { Menu, PanelLeftClose, PanelLeftOpen } from 'lucide-react'\r\nimport type { NavbarProps } from '../types'\r\nimport { cn } from '../utils/cn'\r\nimport { Breadcrumbs } from './Breadcrumbs'\r\nimport { NavbarSearch } from './NavbarSearch'\r\nimport { NotificationMenu } from './NotificationMenu'\r\nimport { ThemeToggle } from './ThemeToggle'\r\nimport { UserMenu } from './UserMenu'\r\n\r\nexport function Navbar({\r\n user,\r\n notifications = [],\r\n onSearch,\r\n searchPlaceholder = 'Search...',\r\n showSearch = true,\r\n className,\r\n breadcrumbs = [],\r\n onMenuClick,\r\n sidebarCollapsed,\r\n onToggleSidebar,\r\n}: NavbarProps) {\r\n return (\r\n <header\r\n className={cn(\r\n 'sticky top-0 z-40 flex h-16 shrink-0 items-center gap-4 border-b border-admin-border',\r\n 'admin-glass bg-admin-surface px-4 lg:px-6',\r\n className,\r\n )}\r\n >\r\n <button\r\n type='button'\r\n className='rounded-lg p-2 text-admin-muted hover:bg-admin-bg lg:hidden'\r\n onClick={onMenuClick}\r\n aria-label='Open menu'\r\n >\r\n <Menu className='h-5 w-5' />\r\n </button>\r\n\r\n <button\r\n type='button'\r\n className='hidden rounded-lg p-2 text-admin-muted hover:bg-admin-bg lg:inline-flex'\r\n onClick={onToggleSidebar}\r\n aria-label={sidebarCollapsed ? 'Expand sidebar' : 'Collapse sidebar'}\r\n >\r\n {sidebarCollapsed ? (\r\n <PanelLeftOpen className='h-5 w-5' />\r\n ) : (\r\n <PanelLeftClose className='h-5 w-5' />\r\n )}\r\n </button>\r\n\r\n <div className='hidden min-w-0 flex-1 md:block'>\r\n <Breadcrumbs items={breadcrumbs} />\r\n </div>\r\n\r\n <div className='flex flex-1 items-center justify-end gap-2 sm:gap-3'>\r\n {showSearch && (\r\n <div className='hidden flex-1 sm:flex sm:max-w-md'>\r\n <NavbarSearch placeholder={searchPlaceholder} onSearch={onSearch} />\r\n </div>\r\n )}\r\n <ThemeToggle />\r\n <NotificationMenu notifications={notifications} />\r\n {user && <UserMenu user={user} />}\r\n </div>\r\n </header>\r\n )\r\n}\r\n","import { PanelLeftClose, PanelLeftOpen } from 'lucide-react'\r\nimport { useSidebar } from '../hooks/useSidebar'\r\nimport { useLayoutContext } from '../context/LayoutContext'\r\nimport type { SidebarProps } from '../types'\r\nimport { filterSidebarByPermissions } from '../utils/permissions'\r\nimport { cn } from '../utils/cn'\r\nimport { SidebarGroup } from './SidebarGroup'\r\nimport { SidebarItem } from './SidebarItem'\r\n\r\nexport function Sidebar({\r\n items,\r\n collapsed: collapsedProp,\r\n appName = 'Admin',\r\n appLogo,\r\n className,\r\n onNavigate,\r\n activePath: activePathProp,\r\n LinkComponent,\r\n}: SidebarProps) {\r\n const { collapsed: ctxCollapsed, toggle, closeMobile } = useSidebar()\r\n const { permissions, activePath: ctxPath } = useLayoutContext()\r\n\r\n const collapsed = collapsedProp ?? ctxCollapsed\r\n const activePath = activePathProp ?? ctxPath\r\n const filtered = filterSidebarByPermissions(items, permissions)\r\n\r\n const handleNavigate = (path: string) => {\r\n onNavigate?.(path)\r\n closeMobile()\r\n }\r\n\r\n return (\r\n <aside\r\n className={cn(\r\n 'hidden lg:flex flex-col border-r border-admin-border bg-admin-surface transition-all duration-300 ease-in-out',\r\n collapsed ? 'w-[var(--admin-sidebar-collapsed)]' : 'w-[var(--admin-sidebar-width)]',\r\n className,\r\n )}\r\n aria-label='Sidebar navigation'\r\n >\r\n <div\r\n className={cn(\r\n 'flex h-16 items-center border-b border-admin-border px-4',\r\n collapsed ? 'justify-center' : 'justify-between gap-2',\r\n )}\r\n >\r\n <div className={cn('flex items-center gap-3 min-w-0', collapsed && 'justify-center')}>\r\n {appLogo ?? (\r\n <div className='flex h-9 w-9 shrink-0 items-center justify-center rounded-xl bg-admin-primary text-sm font-bold text-white shadow-admin'>\r\n {appName.charAt(0)}\r\n </div>\r\n )}\r\n {!collapsed && (\r\n <span className='truncate text-base font-semibold text-admin-text'>{appName}</span>\r\n )}\r\n </div>\r\n {!collapsed && (\r\n <button\r\n type='button'\r\n onClick={toggle}\r\n className='rounded-lg p-2 text-admin-muted hover:bg-admin-bg hover:text-admin-text focus-visible:ring-2 focus-visible:ring-admin-primary'\r\n aria-label='Collapse sidebar'\r\n >\r\n <PanelLeftClose className='h-4 w-4' />\r\n </button>\r\n )}\r\n </div>\r\n\r\n {collapsed && (\r\n <div className='flex justify-center py-2 border-b border-admin-border'>\r\n <button\r\n type='button'\r\n onClick={toggle}\r\n className='rounded-lg p-2 text-admin-muted hover:bg-admin-bg'\r\n aria-label='Expand sidebar'\r\n >\r\n <PanelLeftOpen className='h-4 w-4' />\r\n </button>\r\n </div>\r\n )}\r\n\r\n <nav className='flex-1 overflow-y-auto p-3'>\r\n <SidebarGroup collapsed={collapsed}>\r\n {filtered.map((item) => (\r\n <SidebarItem\r\n key={item.label + (item.path ?? '')}\r\n item={item}\r\n collapsed={collapsed}\r\n activePath={activePath}\r\n onNavigate={handleNavigate}\r\n LinkComponent={LinkComponent}\r\n />\r\n ))}\r\n </SidebarGroup>\r\n </nav>\r\n </aside>\r\n )\r\n}\r\n","import { useMemo } from 'react'\r\nimport { LayoutProvider } from '../context/LayoutContext'\r\nimport { useLayoutContext } from '../context/LayoutContext'\r\nimport { useSidebar } from '../hooks/useSidebar'\r\nimport type { AdminLayoutProps } from '../types'\r\nimport { generateBreadcrumbsFromPath } from '../utils/breadcrumbs'\r\nimport { cn } from '../utils/cn'\r\nimport { AdminLayoutRouterSync } from './AdminLayoutRouterSync'\r\nimport { Footer } from './Footer'\r\nimport { MobileSidebar } from './MobileSidebar'\r\nimport { Navbar } from './Navbar'\r\nimport { Sidebar } from './Sidebar'\r\n\r\nfunction AdminLayoutInner({\r\n children,\r\n sidebarItems,\r\n appName = 'Admin',\r\n appLogo,\r\n user,\r\n notifications = [],\r\n footer,\r\n showFooter = true,\r\n showSearch = true,\r\n searchPlaceholder,\r\n onSearch,\r\n breadcrumbs: breadcrumbsProp,\r\n contentClassName,\r\n activePath: activePathProp,\r\n onNavigate,\r\n LinkComponent,\r\n enableRouter: _enableRouter = false,\r\n}: AdminLayoutProps) {\r\n const {\r\n sidebarCollapsed,\r\n toggleSidebar,\r\n toggleMobile,\r\n breadcrumbs: ctxBreadcrumbs,\r\n setBreadcrumbs,\r\n activePath: ctxPath,\r\n setActivePath,\r\n } = useLayoutContext()\r\n const { closeMobile } = useSidebar()\r\n\r\n const activePath = activePathProp ?? ctxPath\r\n const breadcrumbs = breadcrumbsProp ?? ctxBreadcrumbs\r\n\r\n const handleNavigate = (path: string) => {\r\n setActivePath(path)\r\n if (!breadcrumbsProp) {\r\n setBreadcrumbs(generateBreadcrumbsFromPath(path))\r\n }\r\n onNavigate?.(path)\r\n closeMobile()\r\n }\r\n\r\n const mainOffset = sidebarCollapsed\r\n ? 'lg:pl-[var(--admin-sidebar-collapsed)]'\r\n : 'lg:pl-[var(--admin-sidebar-width)]'\r\n\r\n return (\r\n <div className='admin-layout-root min-h-screen bg-admin-bg text-admin-text'>\r\n <Sidebar\r\n items={sidebarItems}\r\n appName={appName}\r\n appLogo={appLogo}\r\n activePath={activePath}\r\n onNavigate={handleNavigate}\r\n LinkComponent={LinkComponent}\r\n />\r\n <MobileSidebar\r\n items={sidebarItems}\r\n appName={appName}\r\n appLogo={appLogo}\r\n activePath={activePath}\r\n onNavigate={handleNavigate}\r\n LinkComponent={LinkComponent}\r\n />\r\n\r\n <div className={cn('flex min-h-screen flex-col transition-all duration-300', mainOffset)}>\r\n <Navbar\r\n user={user}\r\n notifications={notifications}\r\n onSearch={onSearch}\r\n searchPlaceholder={searchPlaceholder}\r\n showSearch={showSearch}\r\n breadcrumbs={breadcrumbs}\r\n onMenuClick={toggleMobile}\r\n sidebarCollapsed={sidebarCollapsed}\r\n onToggleSidebar={toggleSidebar}\r\n />\r\n\r\n <main className={cn('flex-1 p-4 lg:p-6', contentClassName)}>{children}</main>\r\n\r\n {showFooter && <Footer>{footer}</Footer>}\r\n </div>\r\n </div>\r\n )\r\n}\r\n\r\nexport function AdminLayout(props: AdminLayoutProps) {\r\n const {\r\n storageKey = 'rqdhw3n-admin-layout',\r\n defaultCollapsed = false,\r\n initialDarkMode = false,\r\n permissions = {},\r\n breadcrumbs: initialBreadcrumbs = [],\r\n activePath: initialActivePath = '/',\r\n enableRouter = false,\r\n children,\r\n ...rest\r\n } = props\r\n\r\n const initialBc = useMemo(\r\n () =>\r\n initialBreadcrumbs.length\r\n ? initialBreadcrumbs\r\n : generateBreadcrumbsFromPath(initialActivePath),\r\n [initialBreadcrumbs, initialActivePath],\r\n )\r\n\r\n return (\r\n <LayoutProvider\r\n storageKey={storageKey}\r\n defaultCollapsed={defaultCollapsed}\r\n permissions={permissions}\r\n initialBreadcrumbs={initialBc}\r\n initialActivePath={initialActivePath}\r\n initialDarkMode={initialDarkMode}\r\n >\r\n {enableRouter ? (\r\n <AdminLayoutRouterSync>\r\n <AdminLayoutInner {...rest} enableRouter={enableRouter}>\r\n {children}\r\n </AdminLayoutInner>\r\n </AdminLayoutRouterSync>\r\n ) : (\r\n <AdminLayoutInner {...rest} enableRouter={enableRouter}>\r\n {children}\r\n </AdminLayoutInner>\r\n )}\r\n </LayoutProvider>\r\n )\r\n}\r\n","import { NavLink } from 'react-router-dom'\r\nimport type { ReactNode } from 'react'\r\n\r\nexport type RouterLinkProps = {\r\n to: string\r\n className?: string\r\n children: ReactNode\r\n onClick?: () => void\r\n}\r\n\r\nexport function RouterLink({ to, className, children, onClick }: RouterLinkProps) {\r\n return (\r\n <NavLink to={to} className={className} onClick={onClick}>\r\n {children}\r\n </NavLink>\r\n )\r\n}\r\n","import { useLayoutContext } from '../context/LayoutContext'\r\n\r\nexport function useLayoutState() {\r\n return useLayoutContext()\r\n}\r\n","import { useCallback } from 'react'\r\nimport { useLayoutContext } from '../context/LayoutContext'\r\nimport type { BreadcrumbItem } from '../types'\r\n\r\nexport function useBreadcrumbs() {\r\n const { breadcrumbs, setBreadcrumbs } = useLayoutContext()\r\n\r\n const update = useCallback(\r\n (items: BreadcrumbItem[]) => setBreadcrumbs(items),\r\n [setBreadcrumbs],\r\n )\r\n\r\n return {\r\n items: breadcrumbs,\r\n setBreadcrumbs: update,\r\n }\r\n}\r\n"],"names":["loadLayoutState","key","raw","saveLayoutState","state","LayoutContext","createContext","LayoutProvider","children","storageKey","defaultCollapsed","permissions","initialBreadcrumbs","initialActivePath","initialDarkMode","persisted","sidebarCollapsed","setSidebarCollapsed","useState","mobileOpen","setMobileOpen","darkMode","setDarkMode","breadcrumbs","setBreadcrumbs","activePath","setActivePath","useEffect","root","toggleSidebar","useCallback","v","toggleMobile","toggleDarkMode","value","useMemo","jsx","useLayoutContext","ctx","useContext","useSidebar","generateBreadcrumbsFromPath","pathname","segments","seg","i","path","c","r","e","t","f","n","o","clsx","cn","inputs","AdminLayoutRouterSync","useLocation","manualBreadcrumbs","Footer","className","jsxs","parsePermission","permission","dot","hasPermission","resource","action","allowed","filterSidebarByPermissions","items","item","_a","SidebarGroup","label","collapsed","isActive","SidebarItem","depth","onNavigate","LinkComponent","onItemClick","hasChildren","active","childActive","_b","open","setOpen","Icon","baseClass","content","Fragment","ChevronDown","handleClick","row","child","MobileSidebar","appName","appLogo","activePathProp","closeMobile","ctxPath","filtered","onKey","handleNavigate","X","Breadcrumbs","renderLink","isLast","classNames","Home","index","ChevronRight","NavbarSearch","placeholder","onSearch","query","setQuery","handleSubmit","Search","NotificationMenu","notifications","ref","useRef","unread","handler","Bell","useDarkMode","ThemeToggle","isDark","toggle","Sun","Moon","UserMenu","user","onLogout","onSettings","initials","Settings","User","LogOut","Navbar","searchPlaceholder","showSearch","onMenuClick","onToggleSidebar","Menu","PanelLeftOpen","PanelLeftClose","Sidebar","collapsedProp","ctxCollapsed","AdminLayoutInner","sidebarItems","footer","showFooter","breadcrumbsProp","contentClassName","_enableRouter","ctxBreadcrumbs","mainOffset","AdminLayout","props","enableRouter","rest","initialBc","RouterLink","to","onClick","NavLink","useLayoutState","useBreadcrumbs","update"],"mappings":"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","x_google_ignoreList":[4]}
1
+ {"version":3,"file":"index.cjs","sources":["../src/utils/storage.ts","../src/theme/defaults.ts","../src/theme/variables.ts","../src/theme/resolveTheme.ts","../src/theme/ThemeContext.ts","../src/theme/useSystemMode.ts","../src/context/LayoutContext.tsx","../src/hooks/useSidebar.ts","../src/utils/breadcrumbs.ts","../node_modules/clsx/dist/clsx.mjs","../src/utils/cn.ts","../src/components/AdminLayoutRouterSync.tsx","../src/components/Footer.tsx","../src/utils/permissions.ts","../src/components/SidebarGroup.tsx","../src/components/SidebarItem.tsx","../src/components/MobileSidebar.tsx","../src/components/Breadcrumbs.tsx","../src/components/NavbarSearch.tsx","../src/components/NotificationMenu.tsx","../src/hooks/useDarkMode.ts","../src/components/ThemeToggle.tsx","../src/components/UserMenu.tsx","../src/components/Navbar.tsx","../src/components/Sidebar.tsx","../src/components/AdminLayout.tsx","../src/components/RouterLink.tsx","../src/hooks/useLayoutState.ts","../src/hooks/useBreadcrumbs.ts"],"sourcesContent":["import type { LayoutState } from '../types'\nimport type { AdminLayoutThemeMode } from '../theme/types'\n\r\nexport type PersistedLayout = Partial<Pick<LayoutState, 'sidebarCollapsed' | 'darkMode'>> & {\n mode?: AdminLayoutThemeMode\n}\n\r\nexport function loadLayoutState(key: string): Partial<PersistedLayout> {\r\n if (typeof window === 'undefined') return {}\r\n try {\r\n const raw = localStorage.getItem(key)\r\n const value: unknown = raw ? JSON.parse(raw) : null\n if (!value || typeof value !== 'object') return {}\n const data = value as Record<string, unknown>\n return {\n sidebarCollapsed: typeof data.sidebarCollapsed === 'boolean' ? data.sidebarCollapsed : undefined,\n darkMode: typeof data.darkMode === 'boolean' ? data.darkMode : undefined,\n mode: data.mode === 'light' || data.mode === 'dark' || data.mode === 'system' ? data.mode : undefined,\n }\n } catch {\r\n return {}\r\n }\r\n}\r\n\r\nexport function saveLayoutState(key: string, state: PersistedLayout): void {\r\n if (typeof window === 'undefined') return\r\n try {\r\n localStorage.setItem(key, JSON.stringify(state))\r\n } catch {\r\n /* ignore quota errors */\r\n }\r\n}\r\n","import type { AdminLayoutColors, AdminLayoutStyle, AdminLayoutTheme } from './types'\n\nexport const lightThemeColors: Readonly<Required<AdminLayoutColors>> = Object.freeze({\n primary: '#2563eb',\n secondary: '#7c3aed',\n background: '#f8fafc',\n surface: '#ffffff',\n text: '#0f172a',\n textSecondary: '#64748b',\n sidebarBackground: '#ffffff',\n sidebarText: '#64748b',\n headerBackground: '#ffffff',\n headerText: '#0f172a',\n hoverBackground: '#f1f5f9',\n hoverText: '#0f172a',\n activeBackground: '#2563eb',\n activeText: '#ffffff',\n border: '#e2e8f0',\n onPrimary: '#ffffff',\n danger: '#dc2626',\n onDanger: '#ffffff',\n overlay: 'rgb(15 23 42 / 0.5)',\n})\n\nexport const darkThemeColors: Readonly<Required<AdminLayoutColors>> = Object.freeze({\n ...lightThemeColors,\n primary: '#3b82f6',\n secondary: '#a78bfa',\n background: '#0b1220',\n surface: '#111827',\n text: '#f1f5f9',\n textSecondary: '#94a3b8',\n sidebarBackground: '#111827',\n sidebarText: '#cbd5e1',\n headerBackground: '#111827',\n headerText: '#f1f5f9',\n hoverBackground: '#1e293b',\n hoverText: '#ffffff',\n activeBackground: '#3b82f6',\n activeText: '#020617',\n onPrimary: '#020617',\n border: '#334155',\n danger: '#f87171',\n onDanger: '#020617',\n overlay: 'rgb(2 6 23 / 0.7)',\n})\n\nexport const adminLayoutPresets: Readonly<Record<AdminLayoutStyle, Readonly<AdminLayoutTheme>>> =\n Object.freeze({\n modern: Object.freeze({ style: 'modern' }),\n minimal: Object.freeze({ style: 'minimal' }),\n compact: Object.freeze({ style: 'compact' }),\n })\n","import type { AdminLayoutColors } from './types'\n\nexport const colorVariables: Readonly<Record<keyof AdminLayoutColors, `--ral-${string}`>> = {\n primary: '--ral-primary', secondary: '--ral-secondary',\n background: '--ral-background', surface: '--ral-surface',\n text: '--ral-text', textSecondary: '--ral-text-secondary',\n sidebarBackground: '--ral-sidebar-bg', sidebarText: '--ral-sidebar-text',\n headerBackground: '--ral-header-bg', headerText: '--ral-header-text',\n hoverBackground: '--ral-hover-bg', hoverText: '--ral-hover-text',\n activeBackground: '--ral-active-bg', activeText: '--ral-active-text',\n border: '--ral-border', onPrimary: '--ral-on-primary', danger: '--ral-danger',\n onDanger: '--ral-on-danger', overlay: '--ral-overlay',\n}\n","import type { CSSProperties } from 'react'\nimport { darkThemeColors, lightThemeColors } from './defaults'\nimport { colorVariables } from './variables'\nimport type { AdminLayoutColors, AdminLayoutResolvedMode, AdminLayoutTheme, ResolvedAdminLayoutTheme } from './types'\n\n/** Defaults < generic colors < selected mode colors. Undefined values never erase defaults. */\nexport function resolveTheme(\n theme: AdminLayoutTheme = {},\n systemMode: AdminLayoutResolvedMode = 'light',\n): ResolvedAdminLayoutTheme {\n const mode = theme.mode === 'system' ? systemMode : (theme.mode ?? 'light')\n const colors = { ...(mode === 'dark' ? darkThemeColors : lightThemeColors) }\n const overrides: AdminLayoutColors = {}\n for (const palette of [theme.colors, theme[mode]]) {\n if (!palette) continue\n for (const key of Object.keys(colors) as (keyof AdminLayoutColors)[]) {\n const value = palette[key]\n if (typeof value === 'string' && value.trim()) overrides[key] = value\n }\n }\n Object.assign(colors, overrides)\n // A brand color also colors active navigation unless explicitly overridden.\n if (overrides.primary && !overrides.activeBackground) colors.activeBackground = overrides.primary\n return { mode, style: theme.style ?? 'modern', colors }\n}\n\n/** Apply once at a layout boundary; every descendant inherits the palette. */\nexport function themeToCSSVariables(theme: ResolvedAdminLayoutTheme): CSSProperties {\n return Object.fromEntries(\n (Object.keys(colorVariables) as (keyof AdminLayoutColors)[]).map(\n (key) => [colorVariables[key], theme.colors[key]],\n ),\n ) as CSSProperties\n}\n","import { createContext, useContext } from 'react'\nimport type { AdminLayoutThemeContextValue } from './types'\n\nexport const ThemeContext = createContext<AdminLayoutThemeContextValue | null>(null)\n\nexport function useAdminLayoutTheme() {\n const context = useContext(ThemeContext)\n if (!context) throw new Error('useAdminLayoutTheme must be used within LayoutProvider / AdminLayout')\n return {\n mode: context.requestedMode,\n resolvedMode: context.mode,\n style: context.style,\n colors: context.colors,\n setMode: context.setMode,\n }\n}\n","import { useCallback, useSyncExternalStore } from 'react'\nimport type { AdminLayoutResolvedMode } from './types'\n\nconst query = '(prefers-color-scheme: dark)'\nconst serverSnapshot = (): AdminLayoutResolvedMode => 'light'\n\nexport function useSystemMode(enabled: boolean): AdminLayoutResolvedMode {\n const subscribe = useCallback((onChange: () => void) => {\n if (!enabled || typeof window === 'undefined' || !window.matchMedia) return () => {}\n const media = window.matchMedia(query)\n if (media.addEventListener) {\n media.addEventListener('change', onChange)\n return () => media.removeEventListener('change', onChange)\n }\n media.addListener(onChange)\n return () => media.removeListener(onChange)\n }, [enabled])\n const getSnapshot = useCallback((): AdminLayoutResolvedMode =>\n enabled && typeof window !== 'undefined' && window.matchMedia?.(query).matches ? 'dark' : 'light',\n [enabled])\n return useSyncExternalStore(subscribe, getSnapshot, serverSnapshot)\n}\n","import {\r\n createContext,\r\n useCallback,\r\n useContext,\r\n useEffect,\r\n useMemo,\r\n useState,\r\n type ReactNode,\r\n} from 'react'\r\nimport type { BreadcrumbItem, LayoutContextValue, PermissionsMap } from '../types'\r\nimport { loadLayoutState, saveLayoutState } from '../utils/storage'\nimport { resolveTheme } from '../theme/resolveTheme'\nimport { ThemeContext } from '../theme/ThemeContext'\nimport { useSystemMode } from '../theme/useSystemMode'\nimport type { AdminLayoutTheme, AdminLayoutThemeMode } from '../theme/types'\n\r\nconst LayoutContext = createContext<LayoutContextValue | null>(null)\r\n\r\nexport type LayoutProviderProps = {\r\n children: ReactNode\r\n storageKey?: string\r\n defaultCollapsed?: boolean\r\n permissions?: PermissionsMap\r\n initialBreadcrumbs?: BreadcrumbItem[]\r\n initialActivePath?: string\r\n initialDarkMode?: boolean\n theme?: AdminLayoutTheme\n onThemeModeChange?: (mode: AdminLayoutThemeMode) => void\n}\r\n\r\nexport function LayoutProvider({\r\n children,\r\n storageKey = 'rqdhw3n-admin-layout',\r\n defaultCollapsed = false,\r\n permissions = {},\r\n initialBreadcrumbs = [],\r\n initialActivePath = '/',\r\n initialDarkMode,\n theme,\n onThemeModeChange,\n}: LayoutProviderProps) {\n const [sidebarCollapsed, setSidebarCollapsed] = useState(defaultCollapsed)\n const [mobileOpen, setMobileOpen] = useState(false)\n const [localMode, setLocalMode] = useState<AdminLayoutThemeMode>(initialDarkMode ? 'dark' : 'light')\n const [loadedKey, setLoadedKey] = useState<string | null>(null)\n const mode = theme?.mode ?? localMode\n const systemMode = useSystemMode(mode === 'system')\n const resolved = resolveTheme({ ...theme, mode }, systemMode)\n const darkMode = resolved.mode === 'dark'\n const setMode = useCallback((next: AdminLayoutThemeMode) => {\n if (theme?.mode === undefined) setLocalMode(next)\n onThemeModeChange?.(next)\n }, [theme?.mode, onThemeModeChange])\n const setDarkMode = useCallback((value: boolean) => setMode(value ? 'dark' : 'light'), [setMode])\n const [breadcrumbs, setBreadcrumbs] = useState<BreadcrumbItem[]>(initialBreadcrumbs)\r\n const [activePath, setActivePath] = useState(initialActivePath)\r\n\r\n useEffect(() => {\n const persisted = loadLayoutState(storageKey)\n setSidebarCollapsed(persisted.sidebarCollapsed ?? defaultCollapsed)\n setLocalMode(persisted.mode ?? (persisted.darkMode ?? initialDarkMode ? 'dark' : 'light'))\n setLoadedKey(storageKey)\n // Defaults are initial values; changing storageKey switches the persisted profile.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [storageKey])\n\n useEffect(() => {\n if (loadedKey !== storageKey) return\n const persisted = loadLayoutState(storageKey)\n saveLayoutState(storageKey, theme?.mode === undefined\n ? { sidebarCollapsed, darkMode, mode }\n : { ...persisted, sidebarCollapsed })\n }, [storageKey, sidebarCollapsed, darkMode, mode, theme?.mode, loadedKey])\n\r\n useEffect(() => {\n // Preserve the original document-wide dark class only for legacy consumers.\n if (theme !== undefined) return\n const root = document.documentElement\n const wasDark = root.classList.contains('dark')\n if (darkMode) root.classList.add('dark')\n else root.classList.remove('dark')\n return () => { root.classList.toggle('dark', wasDark) }\n }, [darkMode, theme])\n\r\n const toggleSidebar = useCallback(() => setSidebarCollapsed((v) => !v), [])\r\n const toggleMobile = useCallback(() => setMobileOpen((v) => !v), [])\r\n const toggleDarkMode = useCallback(() => setDarkMode(!darkMode), [setDarkMode, darkMode])\n\r\n const value = useMemo<LayoutContextValue>(\r\n () => ({\r\n sidebarCollapsed,\r\n mobileOpen,\r\n darkMode,\r\n toggleSidebar,\r\n setSidebarCollapsed,\r\n toggleMobile,\r\n setMobileOpen,\r\n toggleDarkMode,\r\n setDarkMode,\r\n permissions,\r\n breadcrumbs,\r\n setBreadcrumbs,\r\n activePath,\r\n setActivePath,\r\n }),\r\n [\r\n sidebarCollapsed,\r\n mobileOpen,\r\n darkMode,\r\n toggleSidebar,\r\n toggleMobile,\r\n toggleDarkMode,\n setDarkMode,\n permissions,\n breadcrumbs,\r\n activePath,\r\n ],\r\n )\r\n\r\n return (\n <LayoutContext.Provider value={value}>\n <ThemeContext.Provider value={{ ...resolved, requestedMode: mode, setMode }}>\n {children}\n </ThemeContext.Provider>\n </LayoutContext.Provider>\n )\n}\n\r\nexport function useLayoutContext(): LayoutContextValue {\r\n const ctx = useContext(LayoutContext)\r\n if (!ctx) {\r\n throw new Error('useLayoutContext must be used within LayoutProvider / AdminLayout')\r\n }\r\n return ctx\r\n}\r\n","import { useLayoutContext } from '../context/LayoutContext'\nimport { useCallback } from 'react'\n\r\nexport function useSidebar() {\r\n const {\r\n sidebarCollapsed,\r\n mobileOpen,\r\n toggleSidebar,\r\n setSidebarCollapsed,\r\n toggleMobile,\r\n setMobileOpen,\r\n } = useLayoutContext()\r\n\r\n const closeMobile = useCallback(() => setMobileOpen(false), [setMobileOpen])\n return {\n collapsed: sidebarCollapsed,\r\n mobileOpen,\r\n toggle: toggleSidebar,\r\n setCollapsed: setSidebarCollapsed,\r\n toggleMobile,\r\n setMobileOpen,\r\n closeMobile,\n }\r\n}\r\n","import type { BreadcrumbItem } from '../types'\r\n\r\nexport function generateBreadcrumbsFromPath(pathname: string): BreadcrumbItem[] {\r\n const segments = pathname.split('/').filter(Boolean)\r\n if (!segments.length) return [{ label: 'Home', path: '/' }]\r\n\r\n return segments.map((seg, i) => {\r\n const path = '/' + segments.slice(0, i + 1).join('/')\r\n const label = seg\r\n .replace(/-/g, ' ')\r\n .replace(/\\b\\w/g, (c) => c.toUpperCase())\r\n return { label, path: i < segments.length - 1 ? path : undefined }\r\n })\r\n}\r\n","function r(e){var t,f,n=\"\";if(\"string\"==typeof e||\"number\"==typeof e)n+=e;else if(\"object\"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=\" \"),n+=f)}else for(f in e)e[f]&&(n&&(n+=\" \"),n+=f);return n}export function clsx(){for(var e,t,f=0,n=\"\",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=\" \"),n+=t);return n}export default clsx;","import clsx, { type ClassValue } from 'clsx'\r\n\r\nexport function cn(...inputs: ClassValue[]): string {\r\n return clsx(inputs)\r\n}\r\n","import { useEffect, type ReactNode } from 'react'\r\nimport { useLocation } from 'react-router-dom'\r\nimport { useLayoutContext } from '../context/LayoutContext'\r\nimport { generateBreadcrumbsFromPath } from '../utils/breadcrumbs'\r\n\r\nexport type AdminLayoutRouterSyncProps = {\r\n children: ReactNode\r\n}\r\n\r\nexport function AdminLayoutRouterSync({ children }: AdminLayoutRouterSyncProps) {\r\n const { pathname } = useLocation()\r\n const { setActivePath, setBreadcrumbs, breadcrumbs: manualBreadcrumbs } = useLayoutContext()\r\n\r\n useEffect(() => {\r\n setActivePath(pathname)\r\n if (!manualBreadcrumbs.length) {\r\n setBreadcrumbs(generateBreadcrumbsFromPath(pathname))\r\n }\r\n }, [pathname, setActivePath, setBreadcrumbs, manualBreadcrumbs.length])\r\n\r\n return <>{children}</>\r\n}\r\n","import { cn } from '../utils/cn'\r\n\r\nexport type FooterProps = {\r\n children?: React.ReactNode\r\n className?: string\r\n}\r\n\r\nexport function Footer({ children, className }: FooterProps) {\r\n return (\r\n <footer\r\n className={cn(\r\n 'mt-auto border-t border-admin-border bg-admin-surface px-6 py-4 text-sm text-admin-muted',\r\n className,\r\n )}\r\n >\r\n {children ?? (\r\n <p className='text-center'>\r\n © {new Date().getFullYear()} Admin Layout · Built with @rqdhw3n/react-admin-layout\r\n </p>\r\n )}\r\n </footer>\r\n )\r\n}\r\n","import type { PermissionsMap, SidebarItemType } from '../types'\r\n\r\nexport function parsePermission(permission: string): { resource: string; action: string } {\r\n const dot = permission.indexOf('.')\r\n if (dot === -1) return { resource: permission, action: 'view' }\r\n return {\r\n resource: permission.slice(0, dot),\r\n action: permission.slice(dot + 1),\r\n }\r\n}\r\n\r\nexport function hasPermission(\r\n permissions: PermissionsMap,\r\n permission?: string,\r\n): boolean {\r\n if (!permission) return true\r\n const { resource, action } = parsePermission(permission)\r\n const allowed = permissions[resource]\r\n if (!allowed?.length) return false\r\n return allowed.includes(action) || allowed.includes('*')\r\n}\r\n\r\nexport function filterSidebarByPermissions(\r\n items: SidebarItemType[],\r\n permissions: PermissionsMap,\r\n): SidebarItemType[] {\r\n return items\r\n .filter((item) => hasPermission(permissions, item.permission))\r\n .map((item) => ({\r\n ...item,\r\n children: item.children\r\n ? filterSidebarByPermissions(item.children, permissions)\r\n : undefined,\r\n }))\r\n .filter((item) => !item.children?.length || item.children.length > 0 || item.path)\r\n}\r\n","import type { ReactNode } from 'react'\r\nimport { cn } from '../utils/cn'\r\n\r\nexport type SidebarGroupProps = {\r\n label?: string\r\n children: ReactNode\r\n collapsed?: boolean\r\n className?: string\r\n}\r\n\r\nexport function SidebarGroup({ label, children, collapsed, className }: SidebarGroupProps) {\r\n return (\r\n <div className={cn('ral-sidebar-group mb-4', className)}>\n {label && !collapsed && (\r\n <p className='ral-sidebar-brand mb-2 px-3 text-[11px] font-semibold uppercase tracking-wider'>\n {label}\r\n </p>\r\n )}\r\n <ul className='space-y-0.5'>{children}</ul>\r\n </div>\r\n )\r\n}\r\n","import { ChevronDown } from 'lucide-react'\r\nimport { useEffect, useState } from 'react'\nimport type { SidebarItemType } from '../types'\r\nimport { cn } from '../utils/cn'\r\n\r\nexport type SidebarItemProps = {\r\n item: SidebarItemType\r\n collapsed?: boolean\r\n depth?: number\r\n activePath?: string\r\n onNavigate?: (path: string) => void\r\n LinkComponent?: React.ComponentType<{\r\n to: string\r\n className?: string\r\n children: React.ReactNode\r\n onClick?: () => void\r\n }>\r\n onItemClick?: () => void\r\n}\r\n\r\nfunction isActive(path: string | undefined, activePath: string): boolean {\n if (!path) return false\r\n return activePath === path || activePath.startsWith(`${path}/`)\r\n}\n\nfunction hasActiveChild(item: SidebarItemType, activePath: string): boolean {\n return Boolean(item.children?.some((child) => isActive(child.path, activePath) || hasActiveChild(child, activePath)))\n}\n\r\nexport function SidebarItem({\r\n item,\r\n collapsed = false,\r\n depth = 0,\r\n activePath = '/',\r\n onNavigate,\r\n LinkComponent,\r\n onItemClick,\r\n}: SidebarItemProps) {\r\n const hasChildren = Boolean(item.children?.length)\r\n const active = item.path ? isActive(item.path, activePath) : false\r\n const childActive = hasActiveChild(item, activePath)\n const [open, setOpen] = useState(active || childActive)\n useEffect(() => { if (childActive) setOpen(true) }, [activePath, childActive])\n\r\n const Icon = item.icon\r\n\r\n const baseClass = cn(\r\n 'ral-nav-item group flex w-full items-center gap-3 px-3 text-sm font-medium',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-admin-primary',\r\n item.disabled && 'pointer-events-none opacity-50',\r\n depth > 0 && 'text-[13px]',\n collapsed && 'justify-center',\n (active || childActive) && 'ral-nav-active',\n )\r\n\r\n const content = (\r\n <>\r\n {Icon && (\r\n <Icon\r\n className='h-[18px] w-[18px] shrink-0'\n aria-hidden\r\n />\r\n )}\n {collapsed && !Icon && <span aria-hidden>{item.label.charAt(0)}</span>}\n {collapsed && <span className='sr-only'>{item.label}</span>}\n {!collapsed && (\r\n <>\r\n <span className='flex-1 truncate text-left'>{item.label}</span>\r\n {item.badge != null && (\r\n <span\r\n className={cn(\r\n 'ral-nav-badge rounded-full px-2 py-0.5 text-[11px] font-semibold',\n )}\r\n >\r\n {item.badge}\r\n </span>\r\n )}\r\n {hasChildren && (\r\n <ChevronDown\r\n className={cn('h-4 w-4 shrink-0 transition-transform', open && 'rotate-180')}\r\n aria-hidden\r\n />\r\n )}\r\n </>\r\n )}\r\n </>\r\n )\r\n\r\n const handleClick = () => {\n if (item.disabled) return\n if (hasChildren) {\r\n setOpen((v) => !v)\r\n return\r\n }\r\n if (item.path) {\r\n onNavigate?.(item.path)\r\n onItemClick?.()\r\n }\r\n }\r\n\r\n const row =\r\n item.path && !hasChildren && LinkComponent && !item.disabled ? (\n <LinkComponent\r\n to={item.path}\r\n className={baseClass}\n onClick={handleClick}\n >\r\n {content}\r\n </LinkComponent>\r\n ) : (\r\n <button type='button' className={baseClass} onClick={handleClick} disabled={item.disabled}\n data-active={active || childActive}\n aria-label={collapsed ? item.label : undefined}\n title={collapsed ? item.label : undefined}\n aria-expanded={hasChildren ? Boolean(open) : undefined}\n aria-current={active && !hasChildren ? 'page' : undefined}>\n {content}\r\n </button>\r\n )\r\n\r\n return (\r\n <li data-active={active || childActive} aria-label={collapsed ? item.label : undefined}>\n {row}\r\n {hasChildren && open && (\n <ul className={cn('mt-1 space-y-0.5', !collapsed && 'border-l border-admin-border ml-5 pl-2')}>\n {item.children!.map((child) => (\r\n <SidebarItem\r\n key={child.label + (child.path ?? '')}\r\n item={child}\r\n collapsed={collapsed}\r\n depth={depth + 1}\r\n activePath={activePath}\r\n onNavigate={onNavigate}\r\n LinkComponent={LinkComponent}\r\n onItemClick={onItemClick}\r\n />\r\n ))}\r\n </ul>\r\n )}\r\n </li>\r\n )\r\n}\r\n","import { X } from 'lucide-react'\r\nimport { useEffect, useRef } from 'react'\nimport { useSidebar } from '../hooks/useSidebar'\r\nimport { useLayoutContext } from '../context/LayoutContext'\r\nimport type { SidebarProps } from '../types'\r\nimport { filterSidebarByPermissions } from '../utils/permissions'\r\nimport { cn } from '../utils/cn'\r\nimport { SidebarGroup } from './SidebarGroup'\r\nimport { SidebarItem } from './SidebarItem'\r\n\r\nexport type MobileSidebarProps = SidebarProps\r\n\r\nexport function MobileSidebar({\r\n items,\r\n appName = 'Admin',\r\n appLogo,\r\n onNavigate,\r\n activePath: activePathProp,\r\n LinkComponent,\r\n}: MobileSidebarProps) {\r\n const { mobileOpen, closeMobile } = useSidebar()\r\n const { permissions, activePath: ctxPath } = useLayoutContext()\r\n const activePath = activePathProp ?? ctxPath\r\n const filtered = filterSidebarByPermissions(items, permissions)\n const dialogRef = useRef<HTMLDivElement>(null)\n\r\n useEffect(() => {\r\n if (!mobileOpen) return\n const previousFocus = document.activeElement as HTMLElement | null\n const previousOverflow = document.body.style.overflow\n const focusable = () => Array.from(dialogRef.current?.querySelectorAll<HTMLElement>(\n 'button:not(:disabled), a[href], input, [tabindex=\"0\"]',\n ) ?? []).filter((element) => element.getClientRects().length > 0)\n dialogRef.current?.querySelector<HTMLElement>('[aria-label=\"Close sidebar\"]')?.focus()\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') closeMobile()\n if (e.key === 'Tab') {\n const elements = focusable()\n const first = elements[0]\n const last = elements[elements.length - 1]\n if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last?.focus() }\n else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first?.focus() }\n }\n }\n const desktop = window.matchMedia?.('(min-width: 1024px)')\n const onResize = () => { if (desktop?.matches) closeMobile() }\n desktop?.addEventListener?.('change', onResize)\n document.addEventListener('keydown', onKey)\r\n document.body.style.overflow = 'hidden'\r\n return () => {\r\n document.removeEventListener('keydown', onKey)\r\n desktop?.removeEventListener?.('change', onResize)\n document.body.style.overflow = previousOverflow\n previousFocus?.focus()\n }\r\n }, [mobileOpen, closeMobile])\r\n\r\n if (!mobileOpen) return null\r\n\r\n const handleNavigate = (path: string) => {\r\n onNavigate?.(path)\r\n closeMobile()\r\n }\r\n\r\n return (\r\n <div ref={dialogRef} className='fixed inset-0 z-50 lg:hidden' role='dialog' aria-modal='true' aria-label='Navigation menu'>\n <button\r\n type='button'\r\n className='ral-overlay absolute inset-0 backdrop-blur-sm animate-fade-in'\n aria-label='Close menu'\r\n onClick={closeMobile}\r\n />\r\n <aside\r\n className={cn(\r\n 'ral-sidebar absolute left-0 top-0 flex h-full w-[min(var(--ral-sidebar-width),85vw)] flex-col',\n 'border-r border-admin-border shadow-admin-lg animate-slide-in',\n )}\r\n >\r\n <div className='ral-sidebar-top flex items-center justify-between border-b border-admin-border px-4'>\n <div className='flex items-center gap-3'>\r\n {appLogo ?? (\r\n <div className='flex h-9 w-9 items-center justify-center rounded-admin bg-admin-primary text-sm font-bold text-admin-on-primary'>\r\n {appName.charAt(0)}\r\n </div>\r\n )}\r\n <span className='ral-sidebar-brand font-semibold'>{appName}</span>\n </div>\r\n <button\r\n type='button'\r\n onClick={closeMobile}\r\n className='rounded-admin p-2 text-admin-muted hover:bg-admin-hover'\r\n aria-label='Close sidebar'\r\n >\r\n <X className='h-5 w-5' />\r\n </button>\r\n </div>\r\n <nav className='flex-1 overflow-y-auto p-3'>\r\n <SidebarGroup>\r\n {filtered.map((item) => (\r\n <SidebarItem\r\n key={item.label + (item.path ?? '')}\r\n item={item}\r\n activePath={activePath}\r\n onNavigate={handleNavigate}\r\n LinkComponent={LinkComponent}\r\n onItemClick={closeMobile}\r\n />\r\n ))}\r\n </SidebarGroup>\r\n </nav>\r\n </aside>\r\n </div>\r\n )\r\n}\r\n","import { ChevronRight, Home } from 'lucide-react'\r\nimport type { BreadcrumbItem } from '../types'\r\nimport { cn } from '../utils/cn'\r\n\r\nexport type BreadcrumbsProps = {\r\n items: BreadcrumbItem[]\r\n className?: string\r\n LinkComponent?: React.ComponentType<{\r\n to: string\r\n className?: string\r\n children: React.ReactNode\r\n }>\r\n onNavigate?: (path: string) => void\r\n}\r\n\r\nexport function Breadcrumbs({\r\n items,\r\n className,\r\n LinkComponent,\r\n onNavigate,\r\n}: BreadcrumbsProps) {\r\n if (!items.length) return null\r\n\r\n const renderLink = (item: BreadcrumbItem, isLast: boolean) => {\r\n const classNames = cn(\r\n 'text-sm transition-colors',\r\n isLast ? 'font-medium text-admin-text' : 'text-admin-muted hover:text-admin-hover-text',\r\n )\r\n\r\n if (!item.path || isLast) {\r\n return <span className={classNames}>{item.label}</span>\r\n }\r\n\r\n if (LinkComponent) {\r\n return (\r\n <LinkComponent to={item.path} className={classNames}>\r\n {item.label}\r\n </LinkComponent>\r\n )\r\n }\r\n\r\n return (\r\n <button type='button' className={classNames} onClick={() => onNavigate?.(item.path!)}>\r\n {item.label}\r\n </button>\r\n )\r\n }\r\n\r\n return (\r\n <nav aria-label='Breadcrumb' className={cn('flex items-center gap-1.5', className)}>\r\n <Home className='h-4 w-4 text-admin-muted shrink-0' aria-hidden />\r\n {items.map((item, index) => {\r\n const isLast = index === items.length - 1\r\n return (\r\n <span key={`${item.label}-${index}`} className='flex items-center gap-1.5'>\r\n <ChevronRight className='h-3.5 w-3.5 text-admin-muted' aria-hidden />\r\n {renderLink(item, isLast)}\r\n </span>\r\n )\r\n })}\r\n </nav>\r\n )\r\n}\r\n","import { Search } from 'lucide-react'\r\nimport { useState, type FormEvent } from 'react'\r\nimport { cn } from '../utils/cn'\r\n\r\nexport type NavbarSearchProps = {\r\n placeholder?: string\r\n onSearch?: (query: string) => void\r\n className?: string\r\n}\r\n\r\nexport function NavbarSearch({\r\n placeholder = 'Search...',\r\n onSearch,\r\n className,\r\n}: NavbarSearchProps) {\r\n const [query, setQuery] = useState('')\r\n\r\n const handleSubmit = (e: FormEvent) => {\r\n e.preventDefault()\r\n onSearch?.(query.trim())\r\n }\r\n\r\n return (\r\n <form onSubmit={handleSubmit} className={cn('relative w-full max-w-md', className)}>\r\n <Search\r\n className='pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-admin-muted'\r\n aria-hidden\r\n />\r\n <input\r\n type='search'\r\n value={query}\r\n onChange={(e) => setQuery(e.target.value)}\r\n placeholder={placeholder}\r\n className={cn(\r\n 'h-10 w-full rounded-admin border border-admin-border bg-admin-bg pl-10 pr-4 text-sm text-admin-text',\r\n 'placeholder:text-admin-muted focus:border-admin-primary focus:outline-none focus:ring-2 focus:ring-admin-primary',\n )}\r\n aria-label='Search'\r\n />\r\n </form>\r\n )\r\n}\r\n","import { Bell } from 'lucide-react'\r\nimport { useEffect, useRef, useState } from 'react'\r\nimport type { NotificationItem } from '../types'\r\nimport { cn } from '../utils/cn'\r\n\r\nexport type NotificationMenuProps = {\r\n notifications?: NotificationItem[]\r\n className?: string\r\n}\r\n\r\nexport function NotificationMenu({ notifications = [], className }: NotificationMenuProps) {\r\n const [open, setOpen] = useState(false)\r\n const ref = useRef<HTMLDivElement>(null)\r\n const unread = notifications.filter((n) => !n.read).length\r\n\r\n useEffect(() => {\r\n const handler = (e: MouseEvent) => {\r\n if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false)\r\n }\r\n document.addEventListener('mousedown', handler)\r\n return () => document.removeEventListener('mousedown', handler)\r\n }, [])\r\n\r\n return (\r\n <div ref={ref} className={cn('relative', className)} onKeyDown={(event) => {\n if (event.key === 'Escape') { setOpen(false); ref.current?.querySelector('button')?.focus() }\n }}>\n <button\r\n type='button'\r\n onClick={() => setOpen((v) => !v)}\r\n className={cn(\r\n 'relative inline-flex h-9 w-9 items-center justify-center rounded-admin border border-admin-border',\r\n 'bg-admin-surface text-admin-muted transition-colors hover:bg-admin-hover hover:text-admin-hover-text',\r\n 'focus-visible:ring-2 focus-visible:ring-admin-primary',\r\n )}\r\n aria-label={`Notifications${unread ? `, ${unread} unread` : ''}`}\r\n aria-expanded={open}\r\n >\r\n <Bell className='h-4 w-4' aria-hidden />\r\n {unread > 0 && (\r\n <span className='absolute -right-0.5 -top-0.5 flex h-4 min-w-4 items-center justify-center rounded-full bg-admin-danger px-1 text-[10px] font-bold text-admin-on-danger'>\n {unread > 9 ? '9+' : unread}\r\n </span>\r\n )}\r\n </button>\r\n\r\n {open && (\r\n <div className='absolute right-0 top-full z-50 mt-2 w-80 max-w-[calc(100vw-6rem)] rounded-admin border border-admin-border bg-admin-surface shadow-admin-lg animate-fade-in'>\n <div className='border-b border-admin-border px-4 py-3'>\r\n <p className='text-sm font-semibold text-admin-text'>Notifications</p>\r\n </div>\r\n <ul className='max-h-72 overflow-y-auto p-2'>\r\n {notifications.length === 0 ? (\r\n <li className='px-3 py-6 text-center text-sm text-admin-muted'>No notifications</li>\r\n ) : (\r\n notifications.map((n) => (\r\n <li\r\n key={n.id}\r\n className={cn(\r\n 'rounded-admin px-3 py-2.5 transition-colors hover:bg-admin-hover',\r\n !n.read && 'ral-unread',\r\n )}\r\n >\r\n <p className='text-sm font-medium text-admin-text'>{n.title}</p>\r\n {n.description && (\r\n <p className='mt-0.5 text-xs text-admin-muted line-clamp-2'>{n.description}</p>\r\n )}\r\n {n.time && <p className='mt-1 text-[11px] text-admin-muted'>{n.time}</p>}\r\n </li>\r\n ))\r\n )}\r\n </ul>\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n","import { useLayoutContext } from '../context/LayoutContext'\r\n\r\nexport function useDarkMode() {\r\n const { darkMode, toggleDarkMode, setDarkMode } = useLayoutContext()\r\n return {\r\n isDark: darkMode,\r\n toggle: toggleDarkMode,\r\n setDarkMode,\r\n }\r\n}\r\n","import { Moon, Sun } from 'lucide-react'\r\nimport { useDarkMode } from '../hooks/useDarkMode'\r\nimport { cn } from '../utils/cn'\r\n\r\nexport type ThemeToggleProps = {\r\n className?: string\r\n}\r\n\r\nexport function ThemeToggle({ className }: ThemeToggleProps) {\r\n const { isDark, toggle } = useDarkMode()\r\n\r\n return (\r\n <button\r\n type='button'\r\n onClick={toggle}\r\n className={cn(\r\n 'inline-flex h-9 w-9 items-center justify-center rounded-admin border border-admin-border',\r\n 'bg-admin-surface text-admin-muted transition-colors hover:bg-admin-hover hover:text-admin-hover-text',\r\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-admin-primary focus-visible:ring-offset-2',\r\n className,\r\n )}\r\n aria-label={isDark ? 'Switch to light mode' : 'Switch to dark mode'}\r\n >\r\n {isDark ? <Sun className='h-4 w-4' aria-hidden /> : <Moon className='h-4 w-4' aria-hidden />}\r\n </button>\r\n )\r\n}\r\n","import { ChevronDown, LogOut, Settings, User } from 'lucide-react'\r\nimport { useEffect, useRef, useState } from 'react'\r\nimport type { AdminUser } from '../types'\r\nimport { cn } from '../utils/cn'\r\n\r\nexport type UserMenuProps = {\r\n user: AdminUser\r\n onLogout?: () => void\r\n onSettings?: () => void\r\n className?: string\r\n}\r\n\r\nexport function UserMenu({ user, onLogout, onSettings, className }: UserMenuProps) {\r\n const [open, setOpen] = useState(false)\r\n const ref = useRef<HTMLDivElement>(null)\r\n\r\n useEffect(() => {\r\n const handler = (e: MouseEvent) => {\r\n if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false)\r\n }\r\n document.addEventListener('mousedown', handler)\r\n return () => document.removeEventListener('mousedown', handler)\r\n }, [])\n\n useEffect(() => {\n if (open) ref.current?.querySelector<HTMLElement>('[role=\"menuitem\"]')?.focus()\n }, [open])\n\r\n const initials = user.name\r\n .split(' ')\r\n .map((n) => n[0])\r\n .join('')\r\n .slice(0, 2)\r\n .toUpperCase()\r\n\r\n return (\r\n <div ref={ref} className={cn('relative', className)} onKeyDown={(event) => {\n const trigger = ref.current?.querySelector<HTMLButtonElement>('[aria-haspopup]')\n if (event.key === 'Escape' && open) { event.preventDefault(); setOpen(false); trigger?.focus() }\n if (event.key === 'Tab') setOpen(false)\n if (['ArrowDown', 'ArrowUp', 'Home', 'End'].includes(event.key)) {\n event.preventDefault()\n if (!open) { setOpen(true); return }\n const entries = Array.from(ref.current?.querySelectorAll<HTMLButtonElement>('[role=\"menuitem\"]') ?? [])\n const current = entries.indexOf(document.activeElement as HTMLButtonElement)\n const next = event.key === 'Home' ? 0 : event.key === 'End' ? entries.length - 1\n : (current + (event.key === 'ArrowDown' ? 1 : -1) + entries.length) % entries.length\n entries[next]?.focus()\n }\n }}>\n <button\r\n type='button'\r\n onClick={() => setOpen((v) => !v)}\r\n className={cn(\r\n 'flex items-center gap-2 rounded-admin border border-admin-border bg-admin-surface px-2 py-1.5',\r\n 'transition-colors hover:bg-admin-hover focus-visible:ring-2 focus-visible:ring-admin-primary',\r\n )}\r\n aria-expanded={open}\r\n aria-haspopup='menu'\n aria-label={`User menu for ${user.name}`}\n >\r\n {user.avatar ? (\r\n <img src={user.avatar} alt='' className='h-8 w-8 rounded-admin object-cover' />\r\n ) : (\r\n <div className='flex h-8 w-8 items-center justify-center rounded-admin bg-admin-primary text-xs font-semibold text-admin-on-primary'>\r\n {initials}\r\n </div>\r\n )}\r\n <div className='hidden text-left sm:block'>\r\n <p className='text-sm font-medium text-admin-text leading-tight'>{user.name}</p>\r\n <p className='text-xs text-admin-muted leading-tight'>{user.email}</p>\r\n </div>\r\n <ChevronDown className='hidden h-4 w-4 text-admin-muted sm:block' aria-hidden />\r\n </button>\r\n\r\n {open && (\r\n <div\r\n role='menu'\r\n className='absolute right-0 top-full z-50 mt-2 w-56 rounded-admin border border-admin-border bg-admin-surface p-1.5 shadow-admin-lg animate-fade-in'\r\n >\r\n <button\r\n type='button'\r\n role='menuitem'\r\n className='flex w-full items-center gap-2 rounded-admin px-3 py-2 text-sm text-admin-text hover:bg-admin-hover'\r\n onClick={() => {\r\n onSettings?.()\r\n setOpen(false)\r\n }}\r\n >\r\n <Settings className='h-4 w-4 text-admin-muted' />\r\n Settings\r\n </button>\r\n <button\r\n type='button'\r\n role='menuitem'\r\n className='flex w-full items-center gap-2 rounded-admin px-3 py-2 text-sm text-admin-text hover:bg-admin-hover'\r\n >\r\n <User className='h-4 w-4 text-admin-muted' />\r\n Profile\r\n </button>\r\n <hr className='my-1 border-admin-border' />\r\n <button\r\n type='button'\r\n role='menuitem'\r\n className='flex w-full items-center gap-2 rounded-admin px-3 py-2 text-sm ral-danger'\r\n onClick={() => {\r\n onLogout?.()\r\n setOpen(false)\r\n }}\r\n >\r\n <LogOut className='h-4 w-4' />\r\n Log out\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n","import { Menu, PanelLeftClose, PanelLeftOpen } from 'lucide-react'\r\nimport type { NavbarProps } from '../types'\r\nimport { cn } from '../utils/cn'\r\nimport { Breadcrumbs } from './Breadcrumbs'\r\nimport { NavbarSearch } from './NavbarSearch'\r\nimport { NotificationMenu } from './NotificationMenu'\r\nimport { ThemeToggle } from './ThemeToggle'\r\nimport { UserMenu } from './UserMenu'\r\n\r\nexport function Navbar({\r\n user,\r\n notifications = [],\r\n onSearch,\r\n searchPlaceholder = 'Search...',\r\n showSearch = true,\r\n className,\r\n breadcrumbs = [],\r\n onMenuClick,\r\n sidebarCollapsed,\r\n onToggleSidebar,\r\n}: NavbarProps) {\r\n return (\r\n <header\r\n className={cn(\r\n 'ral-header sticky top-0 z-40 flex shrink-0 items-center gap-4 border-b border-admin-border',\n className,\r\n )}\r\n >\r\n <button\r\n type='button'\r\n className='rounded-admin p-2 text-admin-muted hover:bg-admin-hover lg:hidden'\r\n onClick={onMenuClick}\r\n aria-label='Open menu'\r\n >\r\n <Menu className='h-5 w-5' />\r\n </button>\r\n\r\n <button\r\n type='button'\r\n className='hidden rounded-admin p-2 text-admin-muted hover:bg-admin-hover lg:inline-flex'\r\n onClick={onToggleSidebar}\r\n aria-label={sidebarCollapsed ? 'Expand sidebar' : 'Collapse sidebar'}\r\n >\r\n {sidebarCollapsed ? (\r\n <PanelLeftOpen className='h-5 w-5' />\r\n ) : (\r\n <PanelLeftClose className='h-5 w-5' />\r\n )}\r\n </button>\r\n\r\n <div className='hidden min-w-0 flex-1 md:block'>\r\n <Breadcrumbs items={breadcrumbs} />\r\n </div>\r\n\r\n <div className='flex flex-1 items-center justify-end gap-2 sm:gap-3'>\r\n {showSearch && (\r\n <div className='hidden flex-1 sm:flex sm:max-w-md'>\r\n <NavbarSearch placeholder={searchPlaceholder} onSearch={onSearch} />\r\n </div>\r\n )}\r\n <ThemeToggle />\r\n <NotificationMenu notifications={notifications} />\r\n {user && <UserMenu user={user} />}\r\n </div>\r\n </header>\r\n )\r\n}\r\n","import { PanelLeftClose, PanelLeftOpen } from 'lucide-react'\r\nimport { useSidebar } from '../hooks/useSidebar'\r\nimport { useLayoutContext } from '../context/LayoutContext'\r\nimport type { SidebarProps } from '../types'\r\nimport { filterSidebarByPermissions } from '../utils/permissions'\r\nimport { cn } from '../utils/cn'\r\nimport { SidebarGroup } from './SidebarGroup'\r\nimport { SidebarItem } from './SidebarItem'\r\n\r\nexport function Sidebar({\r\n items,\r\n collapsed: collapsedProp,\r\n appName = 'Admin',\r\n appLogo,\r\n className,\r\n onNavigate,\r\n activePath: activePathProp,\r\n LinkComponent,\r\n}: SidebarProps) {\r\n const { collapsed: ctxCollapsed, toggle, closeMobile } = useSidebar()\r\n const { permissions, activePath: ctxPath } = useLayoutContext()\r\n\r\n const collapsed = collapsedProp ?? ctxCollapsed\r\n const activePath = activePathProp ?? ctxPath\r\n const filtered = filterSidebarByPermissions(items, permissions)\r\n\r\n const handleNavigate = (path: string) => {\r\n onNavigate?.(path)\r\n closeMobile()\r\n }\r\n\r\n return (\r\n <aside\r\n className={cn(\r\n 'ral-sidebar hidden lg:flex shrink-0 flex-col border-r border-admin-border',\n 'h-screen sticky top-0 transition-[width] duration-300 ease-in-out',\r\n collapsed ? 'w-[var(--admin-sidebar-collapsed)]' : 'w-[var(--admin-sidebar-width)]',\r\n className,\r\n )}\r\n aria-label='Sidebar navigation'\r\n >\r\n <div\r\n className={cn(\r\n 'ral-sidebar-top flex items-center border-b border-admin-border px-4',\n collapsed ? 'justify-center' : 'justify-between gap-2',\r\n )}\r\n >\r\n <div className={cn('flex items-center gap-3 min-w-0', collapsed && 'justify-center')}>\r\n {appLogo ?? (\r\n <div className='flex h-9 w-9 shrink-0 items-center justify-center rounded-admin bg-admin-primary text-sm font-bold text-admin-on-primary shadow-admin'>\r\n {appName.charAt(0)}\r\n </div>\r\n )}\r\n {!collapsed && (\r\n <span className='ral-sidebar-brand truncate text-base font-semibold'>{appName}</span>\n )}\r\n </div>\r\n {!collapsed && (\r\n <button\r\n type='button'\r\n onClick={toggle}\r\n className='rounded-admin p-2 text-admin-muted hover:bg-admin-hover hover:text-admin-hover-text focus-visible:ring-2 focus-visible:ring-admin-primary'\r\n aria-label='Collapse sidebar'\r\n >\r\n <PanelLeftClose className='h-4 w-4' />\r\n </button>\r\n )}\r\n </div>\r\n\r\n {collapsed && (\r\n <div className='flex justify-center py-2 border-b border-admin-border'>\r\n <button\r\n type='button'\r\n onClick={toggle}\r\n className='rounded-admin p-2 text-admin-muted hover:bg-admin-hover'\r\n aria-label='Expand sidebar'\r\n >\r\n <PanelLeftOpen className='h-4 w-4' />\r\n </button>\r\n </div>\r\n )}\r\n\r\n <nav className='flex-1 overflow-y-auto p-3'>\r\n <SidebarGroup collapsed={collapsed}>\r\n {filtered.map((item) => (\r\n <SidebarItem\r\n key={item.label + (item.path ?? '')}\r\n item={item}\r\n collapsed={collapsed}\r\n activePath={activePath}\r\n onNavigate={handleNavigate}\r\n LinkComponent={LinkComponent}\r\n />\r\n ))}\r\n </SidebarGroup>\r\n </nav>\r\n </aside>\r\n )\r\n}\r\n","import { useMemo } from 'react'\r\nimport { LayoutProvider } from '../context/LayoutContext'\r\nimport { useLayoutContext } from '../context/LayoutContext'\r\nimport { useSidebar } from '../hooks/useSidebar'\r\nimport type { AdminLayoutProps } from '../types'\r\nimport { generateBreadcrumbsFromPath } from '../utils/breadcrumbs'\r\nimport { cn } from '../utils/cn'\r\nimport { AdminLayoutRouterSync } from './AdminLayoutRouterSync'\r\nimport { Footer } from './Footer'\r\nimport { MobileSidebar } from './MobileSidebar'\r\nimport { Navbar } from './Navbar'\r\nimport { Sidebar } from './Sidebar'\nimport { useAdminLayoutTheme } from '../theme/ThemeContext'\nimport { themeToCSSVariables } from '../theme/resolveTheme'\n\r\nfunction AdminLayoutInner({\r\n children,\r\n sidebarItems,\r\n appName = 'Admin',\r\n appLogo,\r\n user,\r\n notifications = [],\r\n footer,\r\n showFooter = true,\r\n showSearch = true,\r\n searchPlaceholder,\r\n onSearch,\r\n breadcrumbs: breadcrumbsProp,\r\n contentClassName,\n className,\n activePath: activePathProp,\r\n onNavigate,\r\n LinkComponent,\r\n enableRouter: _enableRouter = false,\r\n}: AdminLayoutProps) {\r\n const {\r\n sidebarCollapsed,\r\n toggleSidebar,\r\n toggleMobile,\r\n breadcrumbs: ctxBreadcrumbs,\r\n setBreadcrumbs,\r\n activePath: ctxPath,\r\n setActivePath,\r\n } = useLayoutContext()\r\n const { closeMobile } = useSidebar()\n const { resolvedMode, style, colors } = useAdminLayoutTheme()\n\r\n const activePath = activePathProp ?? ctxPath\r\n const breadcrumbs = breadcrumbsProp ?? ctxBreadcrumbs\r\n\r\n const handleNavigate = (path: string) => {\r\n setActivePath(path)\r\n if (!breadcrumbsProp) {\r\n setBreadcrumbs(generateBreadcrumbsFromPath(path))\r\n }\r\n onNavigate?.(path)\r\n closeMobile()\r\n }\r\n\r\n return (\r\n <div\n className={cn('ral-layout admin-layout-root min-h-screen bg-admin-bg text-admin-text', resolvedMode === 'dark' && 'dark', className)}\n data-theme={resolvedMode}\n data-style={style}\n style={themeToCSSVariables({ mode: resolvedMode, style, colors })}\n >\n <MobileSidebar\r\n items={sidebarItems}\r\n appName={appName}\r\n appLogo={appLogo}\r\n activePath={activePath}\r\n onNavigate={handleNavigate}\r\n LinkComponent={LinkComponent}\r\n />\r\n\r\n <div className='flex min-h-screen w-full'>\r\n <Sidebar\r\n items={sidebarItems}\r\n appName={appName}\r\n appLogo={appLogo}\r\n activePath={activePath}\r\n onNavigate={handleNavigate}\r\n LinkComponent={LinkComponent}\r\n />\r\n\r\n <div className='flex min-h-screen min-w-0 flex-1 flex-col'>\r\n <Navbar\r\n user={user}\r\n notifications={notifications}\r\n onSearch={onSearch}\r\n searchPlaceholder={searchPlaceholder}\r\n showSearch={showSearch}\r\n breadcrumbs={breadcrumbs}\r\n onMenuClick={toggleMobile}\r\n sidebarCollapsed={sidebarCollapsed}\r\n onToggleSidebar={toggleSidebar}\r\n />\r\n\r\n <main className={cn('ral-content flex-1', contentClassName)}>{children}</main>\n\r\n {showFooter && <Footer>{footer}</Footer>}\r\n </div>\r\n </div>\r\n </div>\r\n )\r\n}\r\n\r\nexport function AdminLayout(props: AdminLayoutProps) {\r\n const {\r\n storageKey = 'rqdhw3n-admin-layout',\r\n defaultCollapsed = false,\r\n initialDarkMode = false,\r\n permissions = {},\r\n breadcrumbs: initialBreadcrumbs = [],\r\n activePath: initialActivePath = '/',\r\n enableRouter = false,\r\n children,\r\n ...rest\r\n } = props\r\n\r\n const initialBc = useMemo(\r\n () =>\r\n initialBreadcrumbs.length\r\n ? initialBreadcrumbs\r\n : generateBreadcrumbsFromPath(initialActivePath),\r\n [initialBreadcrumbs, initialActivePath],\r\n )\r\n\r\n return (\r\n <LayoutProvider\r\n storageKey={storageKey}\r\n defaultCollapsed={defaultCollapsed}\r\n permissions={permissions}\r\n initialBreadcrumbs={initialBc}\r\n initialActivePath={initialActivePath}\r\n initialDarkMode={initialDarkMode}\n theme={props.theme}\n onThemeModeChange={props.onThemeModeChange}\n >\r\n {enableRouter ? (\r\n <AdminLayoutRouterSync>\r\n <AdminLayoutInner {...rest} enableRouter={enableRouter}>\r\n {children}\r\n </AdminLayoutInner>\r\n </AdminLayoutRouterSync>\r\n ) : (\r\n <AdminLayoutInner {...rest} enableRouter={enableRouter}>\r\n {children}\r\n </AdminLayoutInner>\r\n )}\r\n </LayoutProvider>\r\n )\r\n}\r\n","import { NavLink } from 'react-router-dom'\r\nimport type { ReactNode } from 'react'\r\n\r\nexport type RouterLinkProps = {\r\n to: string\r\n className?: string\r\n children: ReactNode\r\n onClick?: () => void\r\n}\r\n\r\nexport function RouterLink({ to, className, children, onClick }: RouterLinkProps) {\r\n return (\r\n <NavLink to={to} className={className} onClick={onClick}>\r\n {children}\r\n </NavLink>\r\n )\r\n}\r\n","import { useLayoutContext } from '../context/LayoutContext'\r\n\r\nexport function useLayoutState() {\r\n return useLayoutContext()\r\n}\r\n","import { useCallback } from 'react'\r\nimport { useLayoutContext } from '../context/LayoutContext'\r\nimport type { BreadcrumbItem } from '../types'\r\n\r\nexport function useBreadcrumbs() {\r\n const { breadcrumbs, setBreadcrumbs } = useLayoutContext()\r\n\r\n const update = useCallback(\r\n (items: BreadcrumbItem[]) => setBreadcrumbs(items),\r\n [setBreadcrumbs],\r\n )\r\n\r\n return {\r\n items: breadcrumbs,\r\n setBreadcrumbs: update,\r\n }\r\n}\r\n"],"names":["loadLayoutState","key","raw","value","data","saveLayoutState","state","lightThemeColors","darkThemeColors","adminLayoutPresets","colorVariables","resolveTheme","theme","systemMode","mode","colors","overrides","palette","themeToCSSVariables","ThemeContext","createContext","useAdminLayoutTheme","context","useContext","query","serverSnapshot","useSystemMode","enabled","subscribe","useCallback","onChange","media","getSnapshot","_a","useSyncExternalStore","LayoutContext","LayoutProvider","children","storageKey","defaultCollapsed","permissions","initialBreadcrumbs","initialActivePath","initialDarkMode","onThemeModeChange","sidebarCollapsed","setSidebarCollapsed","useState","mobileOpen","setMobileOpen","localMode","setLocalMode","loadedKey","setLoadedKey","resolved","darkMode","setMode","next","setDarkMode","breadcrumbs","setBreadcrumbs","activePath","setActivePath","useEffect","persisted","root","wasDark","toggleSidebar","v","toggleMobile","toggleDarkMode","useMemo","jsx","useLayoutContext","ctx","useSidebar","closeMobile","generateBreadcrumbsFromPath","pathname","segments","seg","i","path","c","r","t","f","n","o","clsx","cn","inputs","AdminLayoutRouterSync","useLocation","manualBreadcrumbs","Footer","className","jsxs","parsePermission","permission","dot","hasPermission","resource","action","allowed","filterSidebarByPermissions","items","item","SidebarGroup","label","collapsed","isActive","hasActiveChild","child","SidebarItem","depth","onNavigate","LinkComponent","onItemClick","hasChildren","active","childActive","open","setOpen","Icon","baseClass","content","Fragment","ChevronDown","handleClick","row","MobileSidebar","appName","appLogo","activePathProp","ctxPath","filtered","dialogRef","useRef","previousFocus","previousOverflow","focusable","element","_b","onKey","e","elements","first","last","desktop","_c","onResize","_d","handleNavigate","X","Breadcrumbs","renderLink","isLast","classNames","Home","index","ChevronRight","NavbarSearch","placeholder","onSearch","setQuery","handleSubmit","Search","NotificationMenu","notifications","ref","unread","handler","event","Bell","useDarkMode","ThemeToggle","isDark","toggle","Sun","Moon","UserMenu","user","onLogout","onSettings","initials","trigger","entries","current","Settings","User","LogOut","Navbar","searchPlaceholder","showSearch","onMenuClick","onToggleSidebar","Menu","PanelLeftOpen","PanelLeftClose","Sidebar","collapsedProp","ctxCollapsed","AdminLayoutInner","sidebarItems","footer","showFooter","breadcrumbsProp","contentClassName","_enableRouter","ctxBreadcrumbs","resolvedMode","style","AdminLayout","props","enableRouter","rest","initialBc","RouterLink","to","onClick","NavLink","useLayoutState","useBreadcrumbs","update"],"mappings":"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","x_google_ignoreList":[9]}