@rqdhw3n/react-admin-layout 1.0.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","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","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","e","handleNavigate","X","Breadcrumbs","renderLink","isLast","classNames","Home","index","ChevronRight","NavbarSearch","placeholder","onSearch","query","setQuery","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","AdminLayout","props","enableRouter","rest","initialBc","RouterLink","to","onClick","NavLink","useLayoutState","useBreadcrumbs","update"],"mappings":"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","x_google_ignoreList":[4]}
package/dist/style.css ADDED
@@ -0,0 +1 @@
1
+ *,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}:root{--admin-bg: #f8fafc;--admin-surface: #ffffff;--admin-border: #e2e8f0;--admin-text: #0f172a;--admin-muted: #64748b;--admin-primary: #2563eb;--admin-primary-hover: #1d4ed8;--admin-sidebar-width: 260px;--admin-sidebar-collapsed: 72px}.dark{--admin-bg: #0b1220;--admin-surface: #111827;--admin-border: #1e293b;--admin-text: #f1f5f9;--admin-muted: #94a3b8;--admin-primary: #3b82f6;--admin-primary-hover: #60a5fa}.admin-layout-root{font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.admin-glass{border-width:1px;border-color:var(--admin-border);--tw-backdrop-blur: blur(24px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);background-color:color-mix(in srgb,var(--admin-surface) 88%,transparent)}.pointer-events-none{pointer-events:none}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.-right-0\.5{right:-.125rem}.-top-0\.5{top:-.125rem}.left-0{left:0}.left-3{left:.75rem}.right-0{right:0}.top-0{top:0}.top-1\/2{top:50%}.top-full{top:100%}.z-40{z-index:40}.z-50{z-index:50}.my-1{margin-top:.25rem;margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.ml-5{margin-left:1.25rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-auto{margin-top:auto}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.flex{display:flex}.inline-flex{display:inline-flex}.hidden{display:none}.h-10{height:2.5rem}.h-16{height:4rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-\[18px\]{height:18px}.h-full{height:100%}.max-h-72{max-height:18rem}.min-h-screen{min-height:100vh}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-56{width:14rem}.w-8{width:2rem}.w-80{width:20rem}.w-9{width:2.25rem}.w-\[18px\]{width:18px}.w-\[min\(280px\,85vw\)\]{width:min(280px,85vw)}.w-\[var\(--admin-sidebar-collapsed\)\]{width:var(--admin-sidebar-collapsed)}.w-\[var\(--admin-sidebar-width\)\]{width:var(--admin-sidebar-width)}.w-full{width:100%}.min-w-0{min-width:0px}.min-w-4{min-width:1rem}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.-translate-y-1\/2{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.animate-fade-in{animation:fadeIn .2s ease-out}@keyframes slideIn{0%{transform:translate(-100%)}to{transform:translate(0)}}.animate-slide-in{animation:slideIn .25s ease-out}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.125rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem * var(--tw-space-y-reverse))}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-admin-border{border-color:var(--admin-border)}.bg-admin-bg{background-color:var(--admin-bg)}.bg-admin-primary{background-color:var(--admin-primary)}.bg-admin-surface{background-color:var(--admin-surface)}.bg-red-500{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity, 1))}.bg-slate-900\/50{background-color:#0f172a80}.bg-white\/20{background-color:#fff3}.object-cover{-o-object-fit:cover;object-fit:cover}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.pl-10{padding-left:2.5rem}.pl-2{padding-left:.5rem}.pr-4{padding-right:1rem}.text-left{text-align:left}.text-center{text-align:center}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[13px\]{font-size:13px}.text-base{font-size:1rem;line-height:1.5rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.leading-tight{line-height:1.25}.tracking-wider{letter-spacing:.05em}.text-admin-muted{color:var(--admin-muted)}.text-admin-primary{color:var(--admin-primary)}.text-admin-text{color:var(--admin-text)}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.opacity-50{opacity:.5}.shadow-admin{--tw-shadow: 0 1px 3px rgba(15, 23, 42, .06), 0 8px 24px rgba(15, 23, 42, .08);--tw-shadow-colored: 0 1px 3px var(--tw-shadow-color), 0 8px 24px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-admin-lg{--tw-shadow: 0 4px 24px rgba(15, 23, 42, .12);--tw-shadow-colored: 0 4px 24px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.placeholder\:text-admin-muted::-moz-placeholder{color:var(--admin-muted)}.placeholder\:text-admin-muted::placeholder{color:var(--admin-muted)}.hover\:bg-admin-bg:hover{background-color:var(--admin-bg)}.hover\:bg-red-50:hover{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.hover\:text-admin-text:hover{color:var(--admin-text)}.focus\:border-admin-primary:focus{border-color:var(--admin-primary)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus-visible\:outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.focus-visible\:ring-2:focus-visible{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus-visible\:ring-admin-primary:focus-visible{--tw-ring-color: var(--admin-primary)}.focus-visible\:ring-offset-2:focus-visible{--tw-ring-offset-width: 2px}.dark\:hover\:bg-red-950\/30:hover:is(.dark *){background-color:#450a0a4d}@media(min-width:640px){.sm\:block{display:block}.sm\:flex{display:flex}.sm\:max-w-md{max-width:28rem}.sm\:gap-3{gap:.75rem}}@media(min-width:768px){.md\:block{display:block}}@media(min-width:1024px){.lg\:flex{display:flex}.lg\:inline-flex{display:inline-flex}.lg\:hidden{display:none}.lg\:p-6{padding:1.5rem}.lg\:px-6{padding-left:1.5rem;padding-right:1.5rem}.lg\:pl-\[var\(--admin-sidebar-collapsed\)\]{padding-left:var(--admin-sidebar-collapsed)}.lg\:pl-\[var\(--admin-sidebar-width\)\]{padding-left:var(--admin-sidebar-width)}}
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@rqdhw3n/react-admin-layout",
3
+ "version": "1.0.0",
4
+ "description": "Production-ready admin dashboard layout for React — sidebar, navbar, dark mode, breadcrumbs, RBAC",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
19
+ },
20
+ "./style.css": "./dist/style.css"
21
+ },
22
+ "files": ["dist", "README.md"],
23
+ "scripts": {
24
+ "build": "tsc -p tsconfig.build.json --noEmit && vite build",
25
+ "dev": "vite build --watch",
26
+ "typecheck": "tsc --noEmit",
27
+ "preview:basic": "vite --config examples/basic/vite.config.ts"
28
+ },
29
+ "peerDependencies": {
30
+ "lucide-react": ">=0.400.0",
31
+ "react": ">=18.0.0",
32
+ "react-dom": ">=18.0.0",
33
+ "react-router-dom": ">=6.0.0"
34
+ },
35
+ "peerDependenciesMeta": {
36
+ "react-router-dom": { "optional": true },
37
+ "framer-motion": { "optional": true }
38
+ },
39
+ "dependencies": {
40
+ "clsx": "^2.1.1"
41
+ },
42
+ "devDependencies": {
43
+ "@types/react": "^19.1.2",
44
+ "@types/react-dom": "^19.1.2",
45
+ "autoprefixer": "^10.4.21",
46
+ "framer-motion": "^12.16.0",
47
+ "lucide-react": "^0.513.0",
48
+ "postcss": "^8.5.4",
49
+ "react": "^18.2.0",
50
+ "react-dom": "^18.2.0",
51
+ "react-router-dom": "^7.6.2",
52
+ "tailwindcss": "^3.4.17",
53
+ "typescript": "^5.8.3",
54
+ "vite": "^6.3.5",
55
+ "vite-plugin-dts": "^4.5.3"
56
+ },
57
+ "keywords": ["react", "admin", "dashboard", "layout", "sidebar", "tailwind"],
58
+ "license": "MIT",
59
+ "publishConfig": { "access": "public" }
60
+ }