'use client';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useState, useMemo, useEffect, useRef, useCallback } from 'react';
import { toast } from 'sonner';
import { Layout } from './layout/Layout.js';
import { useAdminRouter } from './router/index.js';
import { cmsApi, ensureCsrfToken } from './lib/api.js';
import { Dashboard } from './views/Dashboard.js';
import { CollectionList } from './views/CollectionList.js';
import { DocumentEdit } from './views/DocumentEdit.js';
import { MediaBrowser } from './views/MediaBrowser.js';
import { Settings } from './views/Settings.js';
import { Profile } from './views/Profile.js';
import { Forms } from './views/Forms.js';
import { FormEditor } from './views/FormEditor.js';
import { FormSubmissions } from './views/FormSubmissions.js';
import { FormEntries } from './views/FormEntries.js';
import { SEO } from './views/SEO.js';
import { ScriptTags } from './views/ScriptTags.js';
import { ScriptTagEditor } from './views/ScriptTagEditor.js';
import { SetupWizard } from './views/SetupWizard.js';
import { Login } from './views/Login.js';
import { ForgotPassword } from './views/ForgotPassword.js';
import { ResetPassword } from './views/ResetPassword.js';
import { ErrorBoundary } from './components/ErrorBoundary.js';
import { ThemeProvider } from './components/ThemeProvider.js';
import { LocaleProvider } from './components/LocaleProvider.js';
import { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts.js';
import { PageBuilder } from './views/page-builder/PageBuilder.js';
import { PageSectionEditor } from './views/page-editor/PageSectionEditor.js';
import { PagePreview } from './views/page-editor/PagePreview.js';
import { SavedSections } from './views/page-builder/SavedSections.js';
import { PageTemplates } from './views/page-builder/PageTemplates.js';
import { Widgets } from './views/page-builder/Widgets.js';
import { PagesListView } from './views/Pages/PagesListView.js';
import { PageTagManager } from './views/Pages/PageTagManager.js';
import { PostsListView } from './views/Posts/PostsListView.js';
import { PostTypesView } from './views/Posts/PostTypesView.js';
import { NewPostPicker } from './views/Posts/NewPostPicker.js';
import { NewPostTypeInstructions } from './views/Posts/NewPostTypeInstructions.js';
import { PostSectionEditor } from './views/post-editor/PostSectionEditor.js';
import { PostTemplateEditor } from './views/post-editor/PostTemplateEditor.js';
import { PostPreview } from './views/post-editor/PostPreview.js';
function AdminShell({ config, session, basePath = '/admin', initialPath = '/', setupRequired, onSetupComplete, onLogin, onVerifyTotp, onLogout, captchaConfig, }) {
    const { currentPath, navigate, matchRoute, buildHref } = useAdminRouter(basePath, initialPath);
    const [shortcutHelpOpen, setShortcutHelpOpen] = useState(false);
    // Sign out: revoke the server-side session (and clear the cookie) first, then
    // let the consumer drop its local session state. We clear local state even if
    // the network call fails so a user is never stuck "logged in" in the UI.
    const handleLogout = useCallback(async () => {
        try {
            await cmsApi('/auth/logout', { method: 'POST' });
        }
        catch {
            // Best-effort: proceed to clear client state regardless.
        }
        navigate(initialPath);
        await onLogout?.();
    }, [navigate, initialPath, onLogout]);
    // Open a preview route in a new browser tab so it behaves like a normal,
    // shareable page (its own URL, no admin chrome — see the standalone branch
    // below). The blank tab is opened synchronously inside the click gesture so
    // popup blockers permit it; `prepare` (e.g. saving an unsaved draft) runs
    // before we point the tab at the URL, guaranteeing the preview reflects the
    // latest saved content. If `prepare` rejects, the tab is closed.
    const openPreview = useCallback((path, prepare) => {
        if (typeof window === 'undefined')
            return;
        const tab = window.open('about:blank', '_blank');
        if (!tab) {
            toast.error('Enable pop-ups for this site to open the preview in a new tab.');
            return;
        }
        const go = (ok) => {
            if (ok === false) {
                tab?.close();
                return;
            }
            if (tab && !tab.closed) {
                // Sever the opener link for safety, then load the real URL.
                try {
                    tab.opener = null;
                }
                catch {
                    /* cross-origin guard — never throws for same-origin admin */
                }
                tab.location.replace(buildHref(path));
            }
        };
        Promise.resolve(prepare?.())
            .then(go)
            .catch(() => tab?.close());
    }, [buildHref]);
    useBranding(config);
    useAdminPageTitle(config, currentPath);
    // When the session was minted via a custom Server Action (the Next.js App
    // Router pattern) the admin won't have hit /auth/login directly and thus
    // won't have an actuate_csrf cookie yet — every subsequent mutation 403s.
    // Proactively bootstrap one as soon as we mount with a session. cmsApi
    // also bootstraps lazily inside non-GET requests as a belt-and-braces.
    useEffect(() => {
        if (session) {
            void ensureCsrfToken();
        }
    }, [session]);
    const shortcuts = useMemo(() => ({
        'mod+k': () => {
            const searchInput = document.querySelector('input[placeholder*="Search"]');
            searchInput?.focus();
        },
        'mod+s': () => {
            const saveBtn = document.querySelector('[data-shortcut="save"]');
            saveBtn?.click();
        },
        escape: () => {
            const closeBtn = document.querySelector('[data-shortcut="close"]');
            closeBtn?.click();
        },
        'mod+/': () => {
            setShortcutHelpOpen((prev) => !prev);
        },
    }), []);
    useKeyboardShortcuts(shortcuts);
    // IMPORTANT: this useMemo MUST stay above the `setupRequired` / `!session`
    // early returns. React's Rules of Hooks require the same number of hooks
    // on every render — putting it below the early returns means we call N
    // hooks pre-login and N+1 post-login, which crashes AdminShell with
    // "Rendered more hooks than during the previous render." (caught by the
    // e2e auth.spec.ts → login redirects to dashboard test).
    const collectionMap = useMemo(() => {
        const map = new Map();
        if (config?.collections) {
            for (const c of Object.values(config.collections)) {
                if (c?.slug)
                    map.set(c.slug, c);
            }
        }
        if (map.size === 0) {
            map.set('pages', { slug: 'pages', type: 'page' });
            map.set('posts', { slug: 'posts' });
        }
        return map;
    }, [config]);
    if (setupRequired && onSetupComplete) {
        return (_jsx(SetupWizard, { onComplete: onSetupComplete, siteName: config?.admin?.branding?.name ?? 'Actuate CMS' }));
    }
    if (!session && !setupRequired) {
        if (matchRoute('/forgot-password')) {
            return _jsx(ForgotPassword, { onNavigate: navigate });
        }
        const resetMatch = matchRoute('/reset-password');
        if (resetMatch) {
            const params = new URLSearchParams(typeof window !== 'undefined' ? window.location.search : '');
            return _jsx(ResetPassword, { onNavigate: navigate, token: params.get('token') });
        }
        if (onLogin) {
            // Thread `config.admin.branding` through so the login screen matches the
            // sidebar (single source of truth for the logo + brand name).
            const branding = config?.admin?.branding;
            return (_jsx(Login, { onLogin: onLogin, onVerifyTotp: onVerifyTotp, onNavigate: navigate, captchaConfig: captchaConfig, branding: branding }));
        }
        return (_jsx("div", { className: "bg-background flex min-h-screen items-center justify-center", children: _jsxs("div", { className: "text-center", children: [_jsx("h1", { className: "text-foreground mb-2 text-xl font-semibold", children: "Unauthorized" }), _jsx("p", { className: "text-muted-foreground text-sm", children: "Please log in to access the admin panel." })] }) }));
    }
    function renderView() {
        if (matchRoute('/')) {
            return _jsx(Dashboard, { config: config, session: session, onNavigate: navigate });
        }
        // Reserved admin routes — must match BEFORE iterating collection slugs
        // so they cannot be shadowed by a consumer-defined collection (e.g.
        // a collection slugged `media`, `users`, or `settings`).
        if (matchRoute('/media')) {
            return _jsx(MediaBrowser, { onNavigate: navigate });
        }
        // ─── Posts area ────────────────────────────────────────────────
        // These take priority over the per-collection `/<slug>` matcher
        // below so a consumer-defined `posts` collection can't accidentally
        // shadow the aggregate Posts view.
        if (matchRoute('/posts/types/new')) {
            return _jsx(NewPostTypeInstructions, { onNavigate: navigate });
        }
        // Per-type template editor — must match before `/posts/types/:slug/edit`
        // is irrelevant (distinct last segment) but stays grouped with the type
        // routes so it can't be shadowed by the generic `/posts/:type/*` block.
        const postTypeTemplate = matchRoute('/posts/types/:slug/template');
        if (postTypeTemplate?.slug) {
            return (_jsx(PostTemplateEditor, { postType: postTypeTemplate.slug, config: config, session: session, onNavigate: navigate }));
        }
        const postTypeEdit = matchRoute('/posts/types/:slug/edit');
        if (postTypeEdit?.slug) {
            // V1 falls through to the per-collection list view; future
            // PR introduces a dedicated PostTypeEditor with field-level
            // metadata. The list view is the natural per-type management
            // surface today (it already shows posts in that type).
            return (_jsx(CollectionList, { collectionSlug: postTypeEdit.slug, config: config, onNavigate: navigate }));
        }
        if (matchRoute('/posts/types')) {
            return _jsx(PostTypesView, { onNavigate: navigate });
        }
        if (matchRoute('/posts/new')) {
            return _jsx(NewPostPicker, { onNavigate: navigate });
        }
        if (matchRoute('/posts')) {
            return _jsx(PostsListView, { onNavigate: navigate });
        }
        // Section-based Post editor. These `/posts/:type/*` patterns are tested
        // AFTER every `/posts/types/*` route above so `:type` cannot swallow the
        // reserved "types" segment.
        const postNew = matchRoute('/posts/:type/new');
        if (postNew?.type) {
            return (_jsx(PostSectionEditor, { postType: postNew.type, config: config, session: session, onNavigate: navigate, onOpenPreview: openPreview }));
        }
        const postPreview = matchRoute('/posts/:type/:id/preview');
        if (postPreview?.type && postPreview?.id) {
            return (_jsx(PostPreview, { postType: postPreview.type, documentId: postPreview.id, session: session, onNavigate: navigate }));
        }
        const postEdit = matchRoute('/posts/:type/:id/edit');
        if (postEdit?.type && postEdit?.id) {
            return (_jsx(PostSectionEditor, { postType: postEdit.type, documentId: postEdit.id, config: config, session: session, onNavigate: navigate, onOpenPreview: openPreview }));
        }
        // ─── Pages area ────────────────────────────────────────────────
        // Ordering matters: tag routes and /pages/new must be tested before
        // the `/pages/:id` matcher, otherwise `:id` swallows "tags"/"new".
        if (matchRoute('/pages/tags/new')) {
            return _jsx(PageTagManager, { onNavigate: navigate, startCreating: true });
        }
        const pageTagEdit = matchRoute('/pages/tags/:id/edit');
        if (pageTagEdit?.id) {
            // The manager is a single CRUD surface; deep-linking to a tag just
            // opens the manager (inline edit lives per-row).
            return _jsx(PageTagManager, { onNavigate: navigate });
        }
        if (matchRoute('/pages/tags')) {
            return _jsx(PageTagManager, { onNavigate: navigate });
        }
        if (matchRoute('/pages/new')) {
            return (_jsx(PageSectionEditor, { config: config, session: session, onNavigate: navigate, onOpenPreview: openPreview }));
        }
        const pagePreview = matchRoute('/pages/:id/preview');
        if (pagePreview?.id) {
            return _jsx(PagePreview, { documentId: pagePreview.id, onNavigate: navigate });
        }
        const pageEdit = matchRoute('/pages/:id/edit');
        if (pageEdit?.id) {
            return (_jsx(PageSectionEditor, { documentId: pageEdit.id, config: config, session: session, onNavigate: navigate, onOpenPreview: openPreview }));
        }
        const pageEditBare = matchRoute('/pages/:id');
        if (pageEditBare?.id) {
            return (_jsx(PageSectionEditor, { documentId: pageEditBare.id, config: config, session: session, onNavigate: navigate, onOpenPreview: openPreview }));
        }
        if (matchRoute('/pages')) {
            return _jsx(PagesListView, { onNavigate: navigate });
        }
        if (matchRoute('/forms/new')) {
            return _jsx(FormEditor, { onNavigate: navigate });
        }
        if (matchRoute('/forms/entries')) {
            return _jsx(FormEntries, { onNavigate: navigate });
        }
        const formEdit = matchRoute('/forms/:id/edit');
        if (formEdit?.id) {
            return _jsx(FormEditor, { formId: formEdit.id, onNavigate: navigate });
        }
        const formSubmissions = matchRoute('/forms/:id/submissions');
        if (formSubmissions?.id) {
            return _jsx(FormSubmissions, { formId: formSubmissions.id, onNavigate: navigate });
        }
        if (matchRoute('/forms')) {
            return _jsx(Forms, { onNavigate: navigate });
        }
        // Legacy deep paths map onto the new five-tab IA.
        if (matchRoute('/seo/redirects')) {
            return _jsx(SEO, { onNavigate: navigate, initialTab: "redirects" });
        }
        if (matchRoute('/seo/content') || matchRoute('/seo/canonicals')) {
            return _jsx(SEO, { onNavigate: navigate, initialTab: "content" });
        }
        if (matchRoute('/seo/technical') || matchRoute('/seo/links')) {
            return _jsx(SEO, { onNavigate: navigate, initialTab: "technical" });
        }
        if (matchRoute('/seo/audit')) {
            return _jsx(SEO, { onNavigate: navigate, initialTab: "audit" });
        }
        if (matchRoute('/seo')) {
            return _jsx(SEO, { onNavigate: navigate, initialTab: "overview" });
        }
        if (matchRoute('/script-tags/new')) {
            return _jsx(ScriptTagEditor, { onNavigate: navigate });
        }
        const scriptTagEdit = matchRoute('/script-tags/:id');
        if (scriptTagEdit?.id) {
            return _jsx(ScriptTagEditor, { tagId: scriptTagEdit.id, onNavigate: navigate });
        }
        if (matchRoute('/script-tags')) {
            return _jsx(ScriptTags, { onNavigate: navigate });
        }
        if (matchRoute('/saved-sections')) {
            return _jsx(SavedSections, { onNavigate: navigate, config: config });
        }
        if (matchRoute('/page-templates')) {
            return _jsx(PageTemplates, { onNavigate: navigate });
        }
        if (matchRoute('/widgets')) {
            return _jsx(Widgets, { onNavigate: navigate });
        }
        // Users + API Keys moved into the Settings view as tabs. The legacy
        // top-level routes still resolve — they just land on the matching tab.
        if (matchRoute('/users')) {
            return _jsx(Settings, { onNavigate: navigate, config: config, session: session, initialTab: "users" });
        }
        if (matchRoute('/api-keys')) {
            return (_jsx(Settings, { onNavigate: navigate, config: config, session: session, initialTab: "api-keys" }));
        }
        if (matchRoute('/settings')) {
            return _jsx(Settings, { onNavigate: navigate, config: config, session: session });
        }
        if (matchRoute('/profile')) {
            return _jsx(Profile, { onNavigate: navigate, session: session });
        }
        // Page Builder routes — explicit /page-builder/* takes precedence over
        // the collection-derived routing below, but we ALSO route a collection
        // declared as `type: 'page'` through the Page Builder by default.
        const pageBuilderNew = matchRoute('/page-builder/new');
        if (pageBuilderNew) {
            return _jsx(PageBuilder, { collectionSlug: "pages", config: config, onNavigate: navigate });
        }
        const pageBuilderEdit = matchRoute('/page-builder/:id');
        if (pageBuilderEdit?.id) {
            return (_jsx(PageBuilder, { documentId: pageBuilderEdit.id, collectionSlug: "pages", config: config, onNavigate: navigate }));
        }
        const RESERVED_SLUGS = new Set([
            'media',
            'forms',
            'seo',
            'script-tags',
            'saved-sections',
            'page-templates',
            'widgets',
            'users',
            'settings',
            'profile',
            'page-builder',
            'collections',
            // `pages` is reserved so the Pages list/editor/tag routes above
            // own the `/pages/*` namespace and can't be shadowed by a
            // consumer-defined `pages` collection. The per-collection list is
            // still reachable via `/collections/pages`.
            'pages',
            // `posts` is reserved so the aggregate Posts area is reachable
            // even if a consumer defines a collection literally called
            // `posts`. The per-type collection list is still available via
            // `/collections/posts`.
            'posts',
        ]);
        for (const [slug, def] of collectionMap) {
            if (RESERVED_SLUGS.has(slug))
                continue;
            const isPageType = def.type === 'page';
            const newMatch = matchRoute(`/${slug}/new`);
            if (newMatch) {
                return isPageType ? (_jsx(PageBuilder, { collectionSlug: slug, config: config, onNavigate: navigate })) : (_jsx(DocumentEdit, { collectionSlug: slug, config: config }));
            }
            const editMatch = matchRoute(`/${slug}/:id`);
            if (editMatch?.id) {
                return isPageType ? (_jsx(PageBuilder, { documentId: editMatch.id, collectionSlug: slug, config: config, onNavigate: navigate })) : (_jsx(DocumentEdit, { collectionSlug: slug, documentId: editMatch.id, config: config }));
            }
            if (matchRoute(`/${slug}`)) {
                return _jsx(CollectionList, { collectionSlug: slug, config: config, onNavigate: navigate });
            }
        }
        const newCollMatch = matchRoute('/collections/:slug/new');
        if (newCollMatch?.slug) {
            const def = collectionMap.get(newCollMatch.slug);
            return def?.type === 'page' ? (_jsx(PageBuilder, { collectionSlug: newCollMatch.slug, config: config, onNavigate: navigate })) : (_jsx(DocumentEdit, { collectionSlug: newCollMatch.slug, config: config }));
        }
        const editCollMatch = matchRoute('/collections/:slug/:id');
        if (editCollMatch?.slug && editCollMatch.id) {
            const def = collectionMap.get(editCollMatch.slug);
            return def?.type === 'page' ? (_jsx(PageBuilder, { documentId: editCollMatch.id, collectionSlug: editCollMatch.slug, config: config, onNavigate: navigate })) : (_jsx(DocumentEdit, { collectionSlug: editCollMatch.slug, documentId: editCollMatch.id, config: config }));
        }
        const collectionMatch = matchRoute('/collections/:slug');
        if (collectionMatch?.slug) {
            return (_jsx(CollectionList, { collectionSlug: collectionMatch.slug, config: config, onNavigate: navigate }));
        }
        return (_jsxs("div", { className: "flex min-h-[400px] flex-col items-center justify-center p-6 text-center", children: [_jsx("h1", { className: "text-foreground mb-2 text-4xl font-bold", children: "404" }), _jsx("p", { className: "text-muted-foreground mb-4", children: "The page you are looking for does not exist." }), _jsx("button", { onClick: () => navigate('/'), className: "text-primary-foreground bg-primary rounded-md px-4 py-2 text-sm font-medium hover:opacity-90", children: "Back to Dashboard" })] }));
    }
    // Preview routes render as standalone pages (no sidebar/header) so a
    // new-tab preview looks like the real published page rather than an
    // embedded admin view. Everything else gets the full admin chrome.
    if (currentPath.endsWith('/preview')) {
        return (_jsx("div", { className: "bg-background h-full min-h-screen", children: _jsx(ErrorBoundary, { children: renderView() }) }));
    }
    return (_jsxs(Layout, { config: config, session: session, currentPath: currentPath, onNavigate: navigate, onLogout: handleLogout, children: [_jsx(ErrorBoundary, { children: renderView() }), shortcutHelpOpen && _jsx(ShortcutHelp, { onClose: () => setShortcutHelpOpen(false) })] }));
}
function ShortcutHelp({ onClose }) {
    return (_jsx("div", { className: "fixed inset-0 z-100 flex items-center justify-center bg-black/50", onClick: (e) => {
            if (e.target === e.currentTarget)
                onClose();
        }, children: _jsxs("div", { className: "bg-card text-card-foreground border-border mx-4 w-full max-w-sm rounded-xl border p-6 shadow-2xl", children: [_jsx("h3", { className: "mb-4 text-lg font-semibold", children: "Keyboard Shortcuts" }), _jsx("div", { className: "space-y-3 text-sm", children: [
                        ['⌘ K', 'Open search'],
                        ['⌘ S', 'Save document'],
                        ['⌘ /', 'Toggle this help'],
                        ['Esc', 'Close panel / modal'],
                    ].map(([key, desc]) => (_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-muted-foreground", children: desc }), _jsx("kbd", { className: "bg-muted rounded px-2 py-1 font-mono text-xs", children: key })] }, key))) }), _jsx("button", { onClick: onClose, className: "bg-primary text-primary-foreground mt-4 w-full rounded-lg py-2 text-sm hover:opacity-90", children: "Close" })] }) }));
}
function useBranding(config) {
    const originalFaviconRef = useRef(null);
    const originalTitleRef = useRef(null);
    const injectedLinkRef = useRef(null);
    useEffect(() => {
        const branding = config?.admin?.branding;
        if (!branding)
            return;
        // --- Favicon ---
        if (branding.favicon) {
            const existing = document.querySelector('link[rel="icon"]');
            originalFaviconRef.current = existing?.href ?? null;
            if (existing) {
                existing.href = branding.favicon;
            }
            else {
                const link = document.createElement('link');
                link.rel = 'icon';
                link.href = branding.favicon;
                document.head.appendChild(link);
                injectedLinkRef.current = link;
            }
        }
        // --- Document title ---
        originalTitleRef.current = document.title;
        if (branding.title) {
            document.title = branding.title;
        }
        else if (branding.name) {
            document.title = `${branding.name} Admin`;
        }
        // --- Primary color ---
        const adminEl = document.querySelector('.actuate-admin');
        if (branding.primaryColor && adminEl) {
            adminEl.style.setProperty('--primary', branding.primaryColor);
            adminEl.style.setProperty('--sidebar-primary', branding.primaryColor);
        }
        return () => {
            // Restore favicon
            if (branding.favicon) {
                const link = document.querySelector('link[rel="icon"]');
                if (link && originalFaviconRef.current) {
                    link.href = originalFaviconRef.current;
                }
                if (injectedLinkRef.current) {
                    injectedLinkRef.current.remove();
                    injectedLinkRef.current = null;
                }
            }
            // Restore title
            if (originalTitleRef.current !== null) {
                document.title = originalTitleRef.current;
            }
            // Remove primary color override
            if (branding.primaryColor && adminEl) {
                adminEl.style.removeProperty('--primary');
                adminEl.style.removeProperty('--sidebar-primary');
            }
        };
    }, [config]);
}
function useAdminPageTitle(config, currentPath) {
    useEffect(() => {
        const branding = config?.admin?.branding;
        const baseName = branding?.title ?? (branding?.name ? `${branding.name} Admin` : null);
        if (!baseName)
            return;
        const segment = currentPath === '/' ? 'Dashboard' : currentPath.split('/').filter(Boolean)[0];
        const pageName = segment ? segment.charAt(0).toUpperCase() + segment.slice(1) : 'Dashboard';
        document.title = `${pageName} — ${baseName}`;
    }, [config, currentPath]);
}
const ISOLATION_STYLE = {
    position: 'fixed',
    inset: '0',
    zIndex: 50,
    overflow: 'auto',
    isolation: 'isolate',
};
export function AdminRoot(props) {
    const defaultDarkMode = props.config?.admin?.branding?.darkMode;
    // The admin is private application UI and must never be indexed. Ensure a
    // `noindex, nofollow` robots meta tag is present while the admin is mounted,
    // as defense-in-depth alongside the server `robots.txt` Disallow rule. This
    // covers every consumer install (the admin page is typically a client
    // component that can't export Next.js route metadata).
    useEffect(() => {
        if (typeof document === 'undefined')
            return;
        const PREV = document.querySelector('meta[name="robots"]');
        const prevContent = PREV?.getAttribute('content') ?? null;
        const meta = PREV ?? document.createElement('meta');
        meta.setAttribute('name', 'robots');
        meta.setAttribute('content', 'noindex, nofollow');
        if (!PREV)
            document.head.appendChild(meta);
        return () => {
            if (prevContent === null) {
                meta.remove();
            }
            else {
                meta.setAttribute('content', prevContent);
            }
        };
    }, []);
    return (_jsx("div", { style: ISOLATION_STYLE, className: "actuate-admin", children: _jsx(ThemeProvider, { defaultDarkMode: defaultDarkMode, children: _jsx(LocaleProvider, { config: props.config, children: _jsx(AdminShell, { ...props }) }) }) }));
}
//# sourceMappingURL=AdminRoot.js.map