UNPKG

react-antd-admin-panel

Version:

Modern TypeScript-first React admin panel builder with Ant Design 6

1 lines 26.4 kB
{"version":3,"file":"ProtectedRoute-bxRuhSKp.cjs","sources":["../src/main/Main.ts","../src/main/ProfileMenu.tsx","../src/main/AppLayout.tsx","../src/main/ProtectedRoute.tsx"],"sourcesContent":["import type { MainConfig, RouteConfig, MainInstance } from './types';\nimport { GlobalStore } from './Store';\nimport { UserState } from './UserState';\n\n/**\n * Main - Central Application Orchestrator\n * Manages configuration, routing, and global state\n * \n * @example\n * const app = new Main({\n * config: {\n * pathToApi: 'https://api.example.com',\n * defaultRoute: '/dashboard',\n * boot: async (main) => {\n * const user = await fetchUser();\n * main.User().set(user);\n * },\n * },\n * sections: {\n * '/dashboard': {\n * component: DashboardPage,\n * icon: <DashboardOutlined />,\n * title: 'Dashboard',\n * },\n * '/users': {\n * component: UsersPage,\n * icon: <UserOutlined />,\n * title: 'Users',\n * requiredRole: 'admin',\n * },\n * },\n * });\n */\nexport class Main {\n private _config: MainConfig;\n private _store: GlobalStore;\n private _userState: UserState;\n private _navigate?: (path: string) => void;\n\n constructor(config: MainConfig) {\n this._config = config;\n this._store = new GlobalStore();\n this._userState = new UserState();\n }\n\n /**\n * Get the configuration\n */\n getConfig(): MainConfig {\n return this._config;\n }\n\n /**\n * Get route sections\n */\n getSections(): Record<string, RouteConfig> {\n return this._config.sections;\n }\n\n /**\n * Get a specific section/route config\n */\n getSection(path: string): RouteConfig | undefined {\n return this._config.sections[path];\n }\n\n /**\n * Get the global store\n */\n Store(): GlobalStore {\n return this._store;\n }\n\n /**\n * Get the user state manager\n */\n User(): UserState {\n return this._userState;\n }\n\n /**\n * Set the navigation function (called by MainProvider)\n */\n setNavigate(fn: (path: string) => void): void {\n this._navigate = fn;\n }\n\n /**\n * Navigate to a route\n */\n navigate(path: string): void {\n if (this._navigate) {\n this._navigate(path);\n } else {\n console.warn('Main: navigate called before setNavigate');\n }\n }\n\n /**\n * Check if the current user can access a route\n */\n canAccess(route: RouteConfig): boolean {\n // Check required role\n if (route.requiredRole && !this._userState.hasRole(route.requiredRole)) {\n return false;\n }\n\n // Check required permissions\n if (route.requiredPermissions && !this._userState.hasAllPermissions(route.requiredPermissions)) {\n return false;\n }\n\n return true;\n }\n\n /**\n * Get all accessible routes for the current user\n */\n getAccessibleRoutes(): Record<string, RouteConfig> {\n const accessible: Record<string, RouteConfig> = {};\n\n for (const [path, route] of Object.entries(this._config.sections)) {\n if (this.canAccess(route)) {\n accessible[path] = route;\n }\n }\n\n return accessible;\n }\n\n /**\n * Get routes for sidebar (non-hidden, accessible)\n */\n getSidebarRoutes(): Array<{ path: string; route: RouteConfig }> {\n return Object.entries(this._config.sections)\n .filter(([_, route]) => !route.hidden && this.canAccess(route))\n .map(([path, route]) => ({ path, route }));\n }\n\n /**\n * Create a MainInstance for use in context\n */\n createInstance(navigate: (path: string) => void): MainInstance {\n this.setNavigate(navigate);\n \n return {\n User: () => this._userState,\n Store: () => this._store,\n config: this._config.config,\n navigate: (path: string) => this.navigate(path),\n canAccess: (route: RouteConfig) => this.canAccess(route),\n };\n }\n\n /**\n * Get the default route\n */\n getDefaultRoute(): string {\n return this._config.config.defaultRoute || '/';\n }\n\n /**\n * Get the auth route (for unauthenticated users)\n */\n getAuthRoute(): string {\n return this._config.config.authRoute || '/login';\n }\n\n /**\n * Check if user is authenticated\n */\n isAuthenticated(): boolean {\n return this._userState.isAuthenticated();\n }\n\n /**\n * Flatten nested routes for routing\n */\n getFlatRoutes(): Array<{ path: string; route: RouteConfig }> {\n const routes: Array<{ path: string; route: RouteConfig }> = [];\n\n const flatten = (sections: Record<string, RouteConfig>, prefix = '') => {\n for (const [path, route] of Object.entries(sections)) {\n const fullPath = prefix + path;\n routes.push({ path: fullPath, route });\n\n if (route.children) {\n flatten(route.children, fullPath);\n }\n }\n };\n\n flatten(this._config.sections);\n return routes;\n }\n}\r\n","import React from 'react';\nimport { Dropdown, Avatar, Space, Typography } from 'antd';\nimport { UserOutlined, LogoutOutlined } from '@ant-design/icons';\nimport type { MenuProps } from 'antd';\nimport type { ProfileMenuConfig } from './types';\nimport { useMain, useUser } from './MainContext';\n\nconst { Text } = Typography;\n\ninterface ProfileMenuProps {\n config?: ProfileMenuConfig;\n}\n\n/**\n * ProfileMenu - User profile dropdown menu\n * Shows avatar, name, and configurable menu items\n */\nexport function ProfileMenu({ config }: ProfileMenuProps): React.ReactElement | null {\n const main = useMain();\n const user = useUser();\n const profileConfig = config || main.config.profileMenu;\n\n if (!user) {\n return null;\n }\n\n const {\n showAvatar = true,\n avatarKey = 'avatar',\n nameKey = 'name',\n emailKey = 'email',\n extraItems = [],\n onLogout,\n showLogout = true,\n } = profileConfig || {};\n\n const avatarUrl = user[avatarKey] as string | undefined;\n const userName = user[nameKey] as string || 'User';\n const userEmail = user[emailKey] as string | undefined;\n\n // Build menu items\n const menuItems: MenuProps['items'] = [];\n\n // User info header\n menuItems.push({\n key: '_header',\n label: React.createElement(\n Space,\n { direction: 'vertical', size: 0, style: { padding: '8px 0' } },\n React.createElement(Text, { strong: true }, userName),\n userEmail && React.createElement(Text, { type: 'secondary', style: { fontSize: 12 } }, userEmail),\n ),\n disabled: true,\n });\n\n menuItems.push({ type: 'divider' });\n\n // Extra items\n for (const item of extraItems) {\n if (item.divider) {\n menuItems.push({ type: 'divider' });\n } else {\n menuItems.push({\n key: item.key,\n label: item.label,\n icon: item.icon,\n danger: item.danger,\n onClick: item.onClick,\n });\n }\n }\n\n // Logout\n if (showLogout) {\n if (extraItems.length > 0) {\n menuItems.push({ type: 'divider' });\n }\n menuItems.push({\n key: '_logout',\n label: 'Logout',\n icon: React.createElement(LogoutOutlined),\n danger: true,\n onClick: async () => {\n if (onLogout) {\n await onLogout();\n }\n main.User().clear();\n if (main.config.authRoute) {\n main.navigate(main.config.authRoute);\n }\n },\n });\n }\n\n const avatarElement = showAvatar\n ? React.createElement(\n Avatar,\n {\n src: avatarUrl,\n icon: !avatarUrl ? React.createElement(UserOutlined) : undefined,\n style: { cursor: 'pointer' },\n },\n )\n : React.createElement(\n Space,\n { style: { cursor: 'pointer' } },\n React.createElement(UserOutlined),\n React.createElement('span', {}, userName),\n );\n\n return React.createElement(\n Dropdown,\n {\n menu: { items: menuItems },\n trigger: ['click'],\n placement: 'bottomRight',\n },\n avatarElement,\n );\n}\r\n","import React from 'react';\nimport { Layout, Menu } from 'antd';\nimport { MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons';\nimport type { MenuProps } from 'antd';\nimport type { RouteConfig, SidebarConfig } from './types';\nimport { useMain, useUser } from './MainContext';\nimport { ProfileMenu } from './ProfileMenu';\n\nconst { Header, Sider, Content } = Layout;\n\ninterface AppLayoutProps {\n sections: Record<string, RouteConfig>;\n currentPath: string;\n sidebarConfig?: SidebarConfig;\n children: React.ReactNode;\n}\n\n/**\n * AppLayout - Main application layout with sidebar navigation\n * Renders a collapsible sidebar with menu items generated from sections\n */\nexport function AppLayout({ \n sections, \n currentPath, \n sidebarConfig,\n children \n}: AppLayoutProps): React.ReactElement {\n const main = useMain();\n const user = useUser();\n const config = sidebarConfig || main.config.sidebar || {};\n\n const {\n logo,\n collapsedLogo,\n title,\n defaultCollapsed = false,\n theme = 'dark',\n width = 256,\n collapsedWidth = 80,\n footer,\n } = config;\n\n const [collapsed, setCollapsed] = React.useState(defaultCollapsed);\n\n // Build menu items from sections\n const menuItems = React.useMemo((): MenuProps['items'] => {\n const items: MenuProps['items'] = [];\n\n for (const [path, route] of Object.entries(sections)) {\n // Skip hidden routes\n if (route.hidden) continue;\n\n // Check access\n if (!main.canAccess(route)) continue;\n\n // Handle nested routes\n if (route.children) {\n const childItems: MenuProps['items'] = [];\n for (const [childPath, childRoute] of Object.entries(route.children)) {\n if (childRoute.hidden) continue;\n if (!main.canAccess(childRoute)) continue;\n \n childItems.push({\n key: `${path}${childPath}`,\n label: childRoute.title,\n icon: childRoute.icon,\n });\n }\n\n if (childItems.length > 0) {\n items.push({\n key: path,\n label: route.title,\n icon: route.icon,\n children: childItems,\n });\n }\n } else {\n items.push({\n key: path,\n label: route.title,\n icon: route.icon,\n });\n }\n }\n\n return items;\n }, [sections, main]);\n\n // Handle menu click\n const handleMenuClick: MenuProps['onClick'] = ({ key }) => {\n main.navigate(key);\n };\n\n // Determine selected keys\n const selectedKeys = [currentPath];\n const openKeys = Object.keys(sections).filter(path => {\n const section = sections[path];\n return currentPath.startsWith(path) && section && section.children;\n });\n\n // Render logo\n const renderLogo = () => {\n const logoContent = collapsed ? collapsedLogo || logo : logo;\n \n if (!logoContent) return null;\n\n const logoElement = typeof logoContent === 'string'\n ? React.createElement('img', { \n src: logoContent, \n alt: 'Logo',\n style: { height: 32, objectFit: 'contain' },\n })\n : logoContent;\n\n return React.createElement(\n 'div',\n {\n style: {\n height: 64,\n display: 'flex',\n alignItems: 'center',\n justifyContent: collapsed ? 'center' : 'flex-start',\n padding: collapsed ? 0 : '0 16px',\n gap: 12,\n },\n },\n logoElement,\n !collapsed && title && React.createElement(\n 'span',\n { \n style: { \n color: theme === 'dark' ? '#fff' : '#000',\n fontSize: 18,\n fontWeight: 600,\n whiteSpace: 'nowrap',\n },\n },\n title,\n ),\n );\n };\n\n return React.createElement(\n Layout,\n { style: { minHeight: '100vh' } },\n // Sidebar\n React.createElement(\n Sider,\n {\n collapsible: true,\n collapsed,\n onCollapse: setCollapsed,\n theme,\n width,\n collapsedWidth,\n trigger: null,\n style: {\n overflow: 'auto',\n height: '100vh',\n position: 'fixed',\n left: 0,\n top: 0,\n bottom: 0,\n },\n },\n renderLogo(),\n React.createElement(\n Menu,\n {\n theme,\n mode: 'inline',\n selectedKeys,\n defaultOpenKeys: openKeys,\n items: menuItems,\n onClick: handleMenuClick,\n },\n ),\n footer && React.createElement(\n 'div',\n {\n style: {\n position: 'absolute',\n bottom: 48,\n left: 0,\n right: 0,\n padding: '0 16px',\n },\n },\n footer,\n ),\n ),\n // Main content area\n React.createElement(\n Layout,\n {\n style: {\n marginLeft: collapsed ? collapsedWidth : width,\n transition: 'margin-left 0.2s',\n },\n },\n // Header\n React.createElement(\n Header,\n {\n style: {\n padding: '0 24px',\n background: '#fff',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n boxShadow: '0 1px 4px rgba(0, 21, 41, 0.08)',\n position: 'sticky',\n top: 0,\n zIndex: 1,\n },\n },\n // Collapse trigger\n React.createElement(\n 'div',\n {\n onClick: () => setCollapsed(!collapsed),\n style: { cursor: 'pointer', fontSize: 18 },\n },\n React.createElement(collapsed ? MenuUnfoldOutlined : MenuFoldOutlined),\n ),\n // Profile menu\n user && React.createElement(ProfileMenu, {}),\n ),\n // Content\n React.createElement(\n Content,\n {\n style: {\n margin: 24,\n padding: 24,\n background: '#fff',\n minHeight: 280,\n borderRadius: 8,\n },\n },\n children,\n ),\n ),\n );\n}\n","import React from 'react';\nimport { useMain, useUser } from './MainContext';\nimport type { RouteConfig } from './types';\n\ninterface ProtectedRouteProps {\n route: RouteConfig;\n children: React.ReactNode;\n fallback?: React.ReactNode;\n}\n\n/**\n * ProtectedRoute - Wraps a route component with access control\n * Redirects to auth route or shows fallback if user doesn't have access\n */\nexport function ProtectedRoute({ \n route, \n children, \n fallback \n}: ProtectedRouteProps): React.ReactElement | null {\n const main = useMain();\n const user = useUser();\n\n // Check if user is authenticated\n if (!user) {\n if (main.config.authRoute) {\n main.navigate(main.config.authRoute);\n }\n return fallback ? React.createElement(React.Fragment, {}, fallback) : null;\n }\n\n // Check access\n if (!main.canAccess(route)) {\n return fallback \n ? React.createElement(React.Fragment, {}, fallback)\n : React.createElement('div', {\n style: {\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n height: '50vh',\n flexDirection: 'column',\n gap: 16,\n },\n },\n React.createElement('h2', {}, 'Access Denied'),\n React.createElement('p', {}, 'You do not have permission to access this page.'),\n );\n }\n\n return React.createElement(React.Fragment, {}, children);\n}\n\ninterface ProtectedProps {\n /** Required role to view children */\n role?: string;\n /** Required permission to view children */\n permission?: string;\n /** Required permissions (all) to view children */\n permissions?: string[];\n /** Required permissions (any) to view children */\n anyPermission?: string[];\n /** Fallback content when access denied */\n fallback?: React.ReactNode;\n children: React.ReactNode;\n}\n\n/**\n * Protected - Component-level access control\n * Shows children only if user has required role/permissions\n * \n * @example\n * <Protected role=\"admin\">\n * <Button onClick={deleteUser}>Delete</Button>\n * </Protected>\n * \n * @example\n * <Protected permission=\"users.edit\" fallback={<span>No access</span>}>\n * <EditUserForm />\n * </Protected>\n */\nexport function Protected({ \n role, \n permission, \n permissions, \n anyPermission,\n fallback,\n children,\n}: ProtectedProps): React.ReactElement | null {\n const main = useMain();\n const userState = main.User();\n\n // Check role\n if (role && !userState.hasRole(role)) {\n return fallback ? React.createElement(React.Fragment, {}, fallback) : null;\n }\n\n // Check single permission\n if (permission && !userState.hasPermission(permission)) {\n return fallback ? React.createElement(React.Fragment, {}, fallback) : null;\n }\n\n // Check all permissions\n if (permissions && !userState.hasAllPermissions(permissions)) {\n return fallback ? React.createElement(React.Fragment, {}, fallback) : null;\n }\n\n // Check any permission\n if (anyPermission && !userState.hasAnyPermission(anyPermission)) {\n return fallback ? React.createElement(React.Fragment, {}, fallback) : null;\n }\n\n return React.createElement(React.Fragment, {}, children);\n}\r\n"],"names":["GlobalStore","UserState","Typography","useMain","useUser","Space","LogoutOutlined","Avatar","UserOutlined","Dropdown","Layout","Menu","MenuUnfoldOutlined","MenuFoldOutlined"],"mappings":"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"}