import type { ReactNode, ComponentType } from 'react'
import type {
AppConfig,
DataProvider,
AuthProvider as AuthProviderInterface,
NavigationProvider as NavigationProviderInterface,
ResourceDefinition,
Theme,
} from '../types'
import { AppProvider } from '../context/app-context'
import { DataProviderProvider } from '../context/data-provider-context'
import { AuthProvider } from '../context/auth-context'
import { NavigationProvider } from '../context/navigation-context'
import { ThemeProvider } from '../context/theme-context'
import { ResourcesProvider } from '../context/resource-context'
export interface AppProps {
children: ReactNode
/** App configuration (name, basePath, logo, etc.) */
config: AppConfig
/** Data provider for CRUD operations - consumers must implement */
dataProvider: DataProvider
/** Auth provider for authentication - consumers must implement */
authProvider: AuthProviderInterface
/** Navigation provider for routing integration (optional - defaults to window.location) */
navigationProvider?: NavigationProviderInterface
/** Resource definitions for auto-generating navigation and routes */
resources?: ResourceDefinition[]
/** Default theme setting */
defaultTheme?: Theme
/** Storage key for theme persistence */
themeStorageKey?: string
/** Custom layout component to wrap children */
layout?: ComponentType<{ children: ReactNode }>
}
/**
* App is the root component for building admin/app interfaces with @mdxui/app.
*
* It composes all the necessary providers (data, auth, navigation, theme, resources)
* and requires consumers to provide their own implementations for DataProvider and AuthProvider.
*
* **Bring Your Own Backend Pattern:**
* - `dataProvider`: Implement the 6-method DataProvider interface for your API/database
* - `authProvider`: Implement the AuthProvider interface for your auth system
* - `navigationProvider`: Optionally integrate with your router (react-router, next/router, etc.)
*
* @example
* ```tsx
* // Define your data provider
* const myDataProvider: DataProvider = {
* getList: async (resource, params) => { ... },
* getOne: async (resource, params) => { ... },
* getMany: async (resource, params) => { ... },
* create: async (resource, params) => { ... },
* update: async (resource, params) => { ... },
* delete: async (resource, params) => { ... },
* }
*
* // Define your auth provider
* const myAuthProvider: AuthProvider = {
* login: async (params) => { ... },
* logout: async () => { ... },
* checkAuth: async () => { ... },
* checkError: async (error) => { ... },
* getIdentity: async () => ({ id: '1', fullName: 'John Doe' }),
* getPermissions: async () => ['admin'],
* }
*
* // Define resources
* const resources: ResourceDefinition[] = [
* { name: 'users', label: 'Users', icon: Users, list: UsersList, edit: UserEdit },
* { name: 'products', label: 'Products', icon: Package, list: ProductsList },
* ]
*
* // Use in your application
*
* }
* nav={}
* footer={}
* >
*
* } />
* {resources.map(r => (
* } />
* ))}
*
*
*
* ```
*/
export function App({
children,
config,
dataProvider,
authProvider,
navigationProvider,
resources = [],
defaultTheme = 'system',
themeStorageKey = 'mdxui-app-theme',
layout: Layout,
}: AppProps) {
// Build navigation groups from resources
const navigation = resources.length > 0
? [{
label: 'Resources',
items: resources
.filter((r) => r.list) // Only include resources with list views
.map((r) => ({
title: r.labelPlural ?? r.label ?? r.name,
url: `${config.basePath ?? ''}/${r.name}`,
icon: r.icon,
})),
}]
: []
const content = Layout ? {children} : children
return (
{content}
)
}