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} ) }