@leverege/imaginarium-ui 1.9.0 → 1.9.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"ImaginariumApp-DAu-61PK.js","sources":["../src/docs/PageDocsContext.tsx","../src/docs/DocsPanel.tsx","../src/shell/Shell.tsx","../src/shell/groupNavItems.ts","../src/shell/AppSidebar.tsx","../src/components/ui/Toast.tsx","../src/components/ui/Toaster.tsx","../src/auth/LoginPage.tsx","../src/auth/RequireAuth.tsx","../src/theme/activeAppearance.ts","../src/shell/ImaginariumApp.tsx"],"sourcesContent":["import { createContext, useContext, useEffect, useState, type ReactNode } from 'react'\n\ninterface PageDocsContextValue {\n tabMarkdown: string | null\n setTabMarkdown: ( markdown: string | null ) => void\n}\n\nconst PageDocsContext = createContext<PageDocsContextValue>( {\n tabMarkdown: null,\n setTabMarkdown: () => {},\n} )\n\nexport function PageDocsProvider( { children }: { children: ReactNode } ) {\n const [ tabMarkdown, setTabMarkdown ] = useState<string | null>( null )\n return (\n <PageDocsContext.Provider value={{ tabMarkdown, setTabMarkdown }}>\n {children}\n </PageDocsContext.Provider>\n )\n}\n\n/**\n * Call inside a page component to register tab-specific docs.\n * When the component unmounts or markdown changes, the panel falls back\n * to the page-level docs registered via addPageDocs().\n */\nexport function useRegisterTabDocs( markdown: string ) {\n const { setTabMarkdown } = useContext( PageDocsContext )\n useEffect( () => {\n setTabMarkdown( markdown )\n return () => { setTabMarkdown( null ) }\n }, [ markdown, setTabMarkdown ] )\n}\n\nexport function useActiveTabDocs(): string | null {\n return useContext( PageDocsContext ).tabMarkdown\n}\n","import ReactMarkdown from 'react-markdown'\nimport { cn } from '../lib/utils'\nimport type { PageDocsPlugin } from '../plugins/types'\nimport { mdComponents } from './mdComponents'\n\ninterface DocsTriggerProps {\n href?: string\n open?: boolean\n onToggle?: () => void\n}\n\nconst triggerClass = ( active: boolean ) => cn(\n 'flex items-center gap-1.5 rounded-md border px-2.5 py-1 text-xs font-medium transition-colors',\n active\n ? 'border-primary/50 bg-primary/10 text-primary'\n : 'border-border bg-card text-muted-foreground hover:border-primary/30 hover:text-foreground'\n)\n\nconst TriggerIcon = () => (\n <span className=\"flex h-3.5 w-3.5 items-center justify-center rounded-full border border-current text-[9px] font-bold leading-none\">\n i\n </span>\n)\n\nexport function DocsTrigger( { href, open = false, onToggle }: DocsTriggerProps ) {\n if ( href != null ) {\n return (\n <div>\n <a href={href} target=\"_blank\" rel=\"noopener noreferrer\" className={triggerClass( false )}>\n <TriggerIcon />\n Docs\n </a>\n </div>\n )\n }\n return (\n <div>\n <button onClick={onToggle} className={triggerClass( open )}>\n <TriggerIcon />\n Docs\n </button>\n </div>\n )\n}\n\ninterface DocsSidePanelProps {\n pageDocs: PageDocsPlugin\n tabMarkdown: string | null\n onClose: () => void\n}\n\nexport function DocsSidePanel( { pageDocs, tabMarkdown, onClose }: DocsSidePanelProps ) {\n const title = pageDocs.path.replace( /^\\//, '' ) || 'docs'\n const Component = pageDocs.component\n\n return (\n <aside className=\"absolute right-0 top-0 bottom-0 z-20 w-[26rem] border-l border-border bg-card flex flex-col overflow-hidden shadow-xl\">\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-border\">\n <span className=\"text-sm font-semibold text-foreground\">{title}</span>\n <button\n onClick={onClose}\n className=\"text-xs text-muted-foreground hover:text-foreground transition-colors\"\n aria-label=\"Close docs panel\"\n >\n ✕\n </button>\n </div>\n\n <div className=\"flex-1 overflow-y-auto px-4 py-4\">\n {tabMarkdown != null && (\n <>\n <ReactMarkdown components={mdComponents}>{tabMarkdown}</ReactMarkdown>\n <hr className=\"border-border my-3\" />\n </>\n )}\n {Component != null && <Component />}\n </div>\n </aside>\n )\n}\n","import { isValidElement, createElement, useState, useEffect, type ReactNode } from 'react'\nimport { Route, Switch, useLocation } from 'wouter'\n\nimport { getPageDocs, getPages } from '../plugins/registry'\nimport { PageDocsProvider, useActiveTabDocs } from '../docs/PageDocsContext'\nimport { DocsTrigger, DocsSidePanel } from '../docs/DocsPanel'\nimport type { PagePlugin } from '../plugins/types'\n\nfunction renderPageElement( plugin: PagePlugin ): ReactNode {\n const { element } = plugin\n if ( isValidElement( element ) ) { return element }\n if ( typeof element === 'function' ) {\n return createElement( element as React.ComponentType )\n }\n return element as ReactNode\n}\n\nexport interface ShellProps {\n fallback?: ReactNode\n children?: ReactNode\n}\n\nexport function Shell( { fallback, children }: ShellProps ) {\n return (\n <PageDocsProvider>\n <ShellContent fallback={fallback}>{children}</ShellContent>\n </PageDocsProvider>\n )\n}\n\nfunction ShellContent( { fallback, children }: ShellProps ) {\n const pages = getPages()\n const [ open, setOpen ] = useState( false )\n const [ location ] = useLocation()\n const pageDocs = getPageDocs( location )\n\n useEffect( () => { setOpen( false ) }, [ location ] )\n const tabMarkdown = useActiveTabDocs()\n\n return (\n <div className=\"relative flex flex-1 overflow-hidden\">\n <main className=\"relative flex-1 overflow-y-auto\">\n {pageDocs != null && (\n <div className=\"flex justify-end px-6 pt-4\">\n {pageDocs.href != null\n ? <DocsTrigger href={pageDocs.href} />\n : <DocsTrigger open={open} onToggle={() => setOpen( ( o ) => !o )} />}\n </div>\n )}\n <div className=\"px-6 pb-6 pt-4\">\n {children}\n <Switch>\n {pages.map( ( page ) => (\n <Route key={page.path} path={page.path}>\n {renderPageElement( page )}\n </Route>\n ) )}\n <Route>{fallback ?? <div className=\"p-8 text-muted-foreground\">Not found</div>}</Route>\n </Switch>\n </div>\n </main>\n {open && pageDocs != null && pageDocs.href == null && (\n <DocsSidePanel\n pageDocs={pageDocs}\n tabMarkdown={tabMarkdown}\n onClose={() => setOpen( false )}\n />\n )}\n </div>\n )\n}\n","import type { NavItemPlugin } from '../plugins/types'\n\nexport interface NavSection {\n label: string\n sectionSort: number\n items: NavItemPlugin[]\n}\n\nexport interface GroupedNav {\n ungrouped: NavItemPlugin[]\n sections: NavSection[]\n}\n\nexport function groupNavItems( items: NavItemPlugin[] ): GroupedNav {\n const ungrouped: NavItemPlugin[] = []\n const sectionMap = new Map<string, NavSection>()\n\n for ( const item of items ) {\n if ( !item.section ) {\n ungrouped.push( item )\n continue\n }\n if ( !sectionMap.has( item.section ) ) {\n sectionMap.set( item.section, {\n label : item.section,\n sectionSort : item.sectionSort ?? item.sort ?? 0,\n items : [],\n } )\n }\n sectionMap.get( item.section )!.items.push( item )\n }\n\n ungrouped.sort( ( a, b ) => ( a.sort ?? 0 ) - ( b.sort ?? 0 ) )\n\n const sections = Array.from( sectionMap.values() )\n for ( const s of sections ) {\n s.items.sort( ( a, b ) => ( a.sort ?? 0 ) - ( b.sort ?? 0 ) )\n }\n sections.sort( ( a, b ) => {\n const d = a.sectionSort - b.sectionSort\n return d !== 0 ? d : a.label.localeCompare( b.label )\n } )\n\n return { ungrouped, sections }\n}\n","import { useState, useEffect, useCallback } from 'react'\nimport { Link, useLocation } from 'wouter'\nimport { ChevronLeft, ChevronDown } from 'lucide-react'\nimport { cn } from '../lib/utils'\nimport { getNavItems, getTopBarItems } from '../plugins/registry'\nimport { groupNavItems } from './groupNavItems'\nimport type { ComponentType } from 'react'\n\n/**\n * Accepted icon forms (anywhere we render an inline icon):\n * - React component: `Settings` from lucide-react\n * - URL string: `/logo.png`, `https://...`, `data:image/...`, `blob:...`\n * - CSS class string: `fa-solid fa-gear`, `material-icons` (rendered on a <span>)\n */\nexport type IconRef = ComponentType<{ className?: string }> | string\n\nconst STORAGE_COLLAPSED = 'imaginarium.ui.sidebar.collapsed'\nconst STORAGE_SECTIONS = 'imaginarium.ui.sidebar.sections'\n\nfunction readBool( key: string, fallback: boolean ): boolean {\n try {\n const v = localStorage.getItem( key )\n return v === null ? fallback : v === 'true'\n } catch { return fallback }\n}\n\nfunction readSections(): Set<string> {\n try {\n const v = localStorage.getItem( STORAGE_SECTIONS )\n if ( !v ) { return new Set() }\n const parsed = JSON.parse( v )\n return new Set( Array.isArray( parsed ) ? parsed as string[] : [] )\n } catch { return new Set() }\n}\n\nconst URL_RE = /^(https?:|data:|blob:|\\/|\\.\\/|\\.\\.\\/)/\n\nfunction renderIcon( icon: IconRef | undefined, className: string ) {\n if ( !icon ) { return null }\n if ( typeof icon === 'string' ) {\n if ( URL_RE.test( icon ) ) { return <img src={icon} alt=\"\" className={className} /> }\n return <span className={`${icon} ${className}`} aria-hidden=\"true\" />\n }\n const Icon = icon\n return <Icon className={className} />\n}\n\nexport interface AppSidebarProps {\n title?: string\n titleIcon?: IconRef\n rightSlot?: React.ReactNode\n}\n\nexport function AppSidebar( { title = 'Imaginarium', titleIcon, rightSlot }: AppSidebarProps ) {\n const [ location ] = useLocation()\n const [ collapsed, setCollapsed ] = useState( () => readBool( STORAGE_COLLAPSED, false ) )\n const [ collapsedSections, setCollapsedSections ] = useState<Set<string>>( readSections )\n\n useEffect( () => {\n try { localStorage.setItem( STORAGE_COLLAPSED, String( collapsed ) ) } catch { /* ignore */ }\n }, [ collapsed ] )\n\n useEffect( () => {\n try {\n localStorage.setItem( STORAGE_SECTIONS, JSON.stringify( Array.from( collapsedSections ) ) )\n } catch { /* ignore */ }\n }, [ collapsedSections ] )\n\n const toggleSidebar = useCallback( () => setCollapsed( v => !v ), [] )\n\n const toggleSection = useCallback( ( label: string ) => {\n setCollapsedSections( prev => {\n const next = new Set( prev )\n next.has( label ) ? next.delete( label ) : next.add( label )\n return next\n } )\n }, [] )\n\n const { ungrouped, sections } = groupNavItems( getNavItems() )\n const topBarItems = getTopBarItems()\n\n return (\n <aside\n className={cn(\n 'flex flex-col flex-shrink-0 border-r bg-background transition-[width] duration-200 ease-in-out overflow-hidden',\n collapsed ? 'w-[52px]' : 'w-[220px]',\n )}\n >\n {/* Header */}\n <div className=\"flex h-[52px] flex-shrink-0 items-center border-b px-2.5 gap-2\">\n {!collapsed && renderIcon( titleIcon, 'h-6 w-6' )}\n {!collapsed && (\n <span className=\"flex-1 truncate text-sm font-semibold\">{title}</span>\n )}\n <button\n onClick={toggleSidebar}\n aria-label={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}\n className={cn(\n 'flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-md border text-muted-foreground',\n 'hover:bg-accent hover:text-accent-foreground transition-colors',\n collapsed && 'mx-auto border-transparent',\n )}\n >\n <ChevronLeft\n className={cn( 'h-4 w-4 transition-transform duration-200', collapsed && 'rotate-180' )}\n />\n </button>\n </div>\n\n {/* Nav */}\n <nav className=\"flex flex-1 flex-col gap-0.5 overflow-y-auto overflow-x-hidden p-1.5\">\n {/* Ungrouped items */}\n {ungrouped.map( ( { path, label, icon: Icon } ) => {\n const isActive = location === path || location.startsWith( `${path}/` )\n return (\n <Link\n key={path}\n href={path}\n title={collapsed ? label : undefined}\n className={cn(\n 'relative flex items-center gap-2.5 rounded-md px-2 py-1.5 text-sm text-muted-foreground',\n 'hover:bg-accent hover:text-accent-foreground transition-colors whitespace-nowrap',\n isActive && 'bg-accent/50 text-accent-foreground font-medium',\n collapsed && 'justify-center px-2',\n )}\n >\n {Icon && <Icon className=\"h-4 w-4 flex-shrink-0\" />}\n {!collapsed && <span>{label}</span>}\n </Link>\n )\n } )}\n\n {/* Sections */}\n {sections.map( ( section, index ) => {\n const isSectionCollapsed = !collapsed && collapsedSections.has( section.label )\n // The divider separates a section from what's above it. Skip it for the\n // first section when nothing precedes it (no ungrouped items) so it\n // doesn't stack under the header's border-b and read as a double line.\n const showDivider = index > 0 || ungrouped.length > 0\n return (\n <div key={section.label} className=\"flex flex-col\">\n {/* Section divider + header */}\n {showDivider && <div className=\"my-1.5 h-px bg-border\" />}\n {!collapsed && (\n <button\n onClick={() => toggleSection( section.label )}\n className={cn(\n 'flex items-center justify-between px-2 pb-1 pt-2.5',\n 'text-[10px] font-semibold uppercase tracking-widest text-muted-foreground',\n 'hover:text-foreground transition-colors cursor-pointer rounded-sm',\n )}\n >\n {section.label}\n <ChevronDown\n className={cn(\n 'h-3 w-3 transition-transform duration-200',\n isSectionCollapsed && '-rotate-90',\n )}\n />\n </button>\n )}\n\n {/* Section items */}\n <div\n className={cn(\n 'flex flex-col gap-0.5 overflow-hidden transition-all duration-200',\n isSectionCollapsed ? 'max-h-0 opacity-0' : 'max-h-screen opacity-100',\n )}\n >\n {section.items.map( ( { path, label, icon: Icon } ) => {\n const isActive = location === path || location.startsWith( `${path}/` )\n return (\n <Link\n key={path}\n href={path}\n title={collapsed ? label : undefined}\n className={cn(\n 'relative flex items-center gap-2.5 rounded-md px-2 py-1.5 text-sm text-muted-foreground',\n 'hover:bg-accent hover:text-accent-foreground transition-colors whitespace-nowrap',\n isActive && 'bg-accent/50 text-accent-foreground font-medium',\n collapsed && 'justify-center px-2',\n )}\n >\n {Icon && <Icon className=\"h-4 w-4 flex-shrink-0\" />}\n {!collapsed && <span>{label}</span>}\n </Link>\n )\n } )}\n </div>\n </div>\n )\n } )}\n </nav>\n\n {/* Footer: rightSlot + TopBarItems */}\n <div className={cn(\n 'flex flex-shrink-0 items-center border-t p-1.5',\n collapsed ? 'flex-col gap-1' : 'flex-row justify-end gap-0.5',\n )}>\n {!collapsed && rightSlot}\n {topBarItems.map( ( item ) => {\n const C = item.component\n return <C key={item.id} />\n } )}\n </div>\n </aside>\n )\n}\n","import * as React from 'react'\nimport * as ToastPrimitives from '@radix-ui/react-toast'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { X } from 'lucide-react'\n\nimport { cn } from '../../lib/utils'\n\nconst ToastProvider = ToastPrimitives.Provider\n\nconst ToastViewport = React.forwardRef<\n React.ElementRef<typeof ToastPrimitives.Viewport>,\n React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport>\n>( ( { className, ...props }, ref ) => (\n <ToastPrimitives.Viewport\n ref={ref}\n className={cn(\n 'fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]',\n className,\n )}\n {...props}\n />\n) )\nToastViewport.displayName = ToastPrimitives.Viewport.displayName\n\nconst toastVariants = cva(\n 'group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full',\n {\n variants: {\n variant: {\n default: 'border bg-background text-foreground',\n destructive: 'destructive group border-destructive bg-destructive text-destructive-foreground',\n },\n },\n defaultVariants: { variant: 'default' },\n },\n)\n\nconst Toast = React.forwardRef<\n React.ElementRef<typeof ToastPrimitives.Root>,\n React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> & VariantProps<typeof toastVariants>\n>( ( { className, variant, ...props }, ref ) => (\n <ToastPrimitives.Root ref={ref} className={cn( toastVariants( { variant } ), className )} {...props} />\n) )\nToast.displayName = ToastPrimitives.Root.displayName\n\nconst ToastAction = React.forwardRef<\n React.ElementRef<typeof ToastPrimitives.Action>,\n React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>\n>( ( { className, ...props }, ref ) => (\n <ToastPrimitives.Action\n ref={ref}\n className={cn(\n 'inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',\n className,\n )}\n {...props}\n />\n) )\nToastAction.displayName = ToastPrimitives.Action.displayName\n\nconst ToastClose = React.forwardRef<\n React.ElementRef<typeof ToastPrimitives.Close>,\n React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>\n>( ( { className, ...props }, ref ) => (\n <ToastPrimitives.Close\n ref={ref}\n className={cn(\n 'absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100',\n className,\n )}\n toast-close=\"\"\n {...props}\n >\n <X className=\"h-4 w-4\" />\n </ToastPrimitives.Close>\n) )\nToastClose.displayName = ToastPrimitives.Close.displayName\n\nconst ToastTitle = React.forwardRef<\n React.ElementRef<typeof ToastPrimitives.Title>,\n React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>\n>( ( { className, ...props }, ref ) => (\n <ToastPrimitives.Title ref={ref} className={cn( 'text-sm font-semibold', className )} {...props} />\n) )\nToastTitle.displayName = ToastPrimitives.Title.displayName\n\nconst ToastDescription = React.forwardRef<\n React.ElementRef<typeof ToastPrimitives.Description>,\n React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>\n>( ( { className, ...props }, ref ) => (\n <ToastPrimitives.Description ref={ref} className={cn( 'text-sm opacity-90', className )} {...props} />\n) )\nToastDescription.displayName = ToastPrimitives.Description.displayName\n\nexport type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>\nexport type ToastActionElement = React.ReactElement<typeof ToastAction>\n\nexport {\n ToastProvider,\n ToastViewport,\n Toast,\n ToastTitle,\n ToastDescription,\n ToastClose,\n ToastAction,\n}\n","import { useToast } from '../../hooks/useToast'\nimport {\n Toast,\n ToastClose,\n ToastDescription,\n ToastProvider,\n ToastTitle,\n ToastViewport,\n} from './Toast'\n\nexport function Toaster() {\n const { toasts } = useToast()\n\n return (\n <ToastProvider>\n {toasts.map( ( { id, title, description, action, ...props } ) => (\n <Toast key={id} {...props}>\n <div className=\"grid gap-1\">\n {title && <ToastTitle>{title}</ToastTitle>}\n {description && <ToastDescription>{description}</ToastDescription>}\n </div>\n {action}\n <ToastClose />\n </Toast>\n ) )}\n <ToastViewport />\n </ToastProvider>\n )\n}\n","import { Button } from '../components/ui/Button'\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from '../components/ui/Card'\n\nexport interface LoginPageProps {\n loginPath: string\n title?: string\n subtitle?: string\n buttonLabel?: string\n /** URL of an image to show behind the sign-in card. Empty/null skips it. */\n backgroundUrl?: string\n /** Optional message shown above the button (e.g. an error from a failed prior attempt). */\n errorMessage?: string\n}\n\nfunction GoogleGlyph( { className }: { className?: string } ) {\n return (\n <svg viewBox=\"0 0 24 24\" className={className} aria-hidden=\"true\">\n <path fill=\"#4285F4\" d=\"M23.49 12.27c0-.79-.07-1.54-.19-2.27H12v4.51h6.16c-.27 1.4-1.04 2.59-2.21 3.41v2.77h3.59c2.08-1.92 3.95-4.74 3.95-8.42z\" />\n <path fill=\"#34A853\" d=\"M12 24c2.97 0 5.46-.98 7.28-2.66l-3.59-2.77c-.98.66-2.23 1.06-3.69 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 21.53 7.7 24 12 24z\" />\n <path fill=\"#FBBC05\" d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\" />\n <path fill=\"#EA4335\" d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\" />\n </svg>\n )\n}\n\nconst ERROR_MESSAGES: Record<string, string> = {\n auth_failed : 'Sign-in failed. Please try again.',\n}\n\nfunction readUrlError(): string | undefined {\n if ( typeof window === 'undefined' ) { \n return undefined \n }\n const code = new URLSearchParams( window.location.search ).get( 'error' )\n if ( !code ) { \n return undefined \n }\n return ERROR_MESSAGES[code] ?? `Sign-in error: ${code}`\n}\n\nexport function LoginPage( {\n loginPath,\n title = 'Sign in',\n subtitle,\n buttonLabel = 'Sign in with Google',\n backgroundUrl,\n errorMessage,\n}: LoginPageProps ) {\n const message = errorMessage ?? readUrlError()\n const hasBackground = Boolean( backgroundUrl )\n\n return (\n <div\n className=\"min-h-screen flex items-center justify-center bg-background bg-cover bg-center px-4\"\n style={hasBackground ? { backgroundImage: `url(${backgroundUrl})` } : undefined}\n >\n <Card className={`w-full max-w-md ${hasBackground ? 'backdrop-blur-sm bg-card/90' : ''}`}>\n <CardHeader className=\"text-center\">\n <CardTitle>{title}</CardTitle>\n {subtitle && <CardDescription>{subtitle}</CardDescription>}\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {message && (\n <div className=\"rounded-md border border-destructive bg-destructive/10 px-4 py-2 text-sm text-destructive\">\n {message}\n </div>\n )}\n <Button\n className=\"w-full\"\n variant=\"outline\"\n onClick={() => { window.location.href = loginPath }}\n >\n <GoogleGlyph className=\"h-5 w-5 mr-2\" />\n {buttonLabel}\n </Button>\n </CardContent>\n </Card>\n </div>\n )\n}\n\nexport default LoginPage\n","import { createElement, type ComponentType, type ReactNode } from 'react'\nimport { useQuery } from '@tanstack/react-query'\nimport { Config } from '@leverege/plugin'\n\nimport { useImaginariumApi } from '../api/ImaginariumApiContext'\nimport { LoginPage, type LoginPageProps } from './LoginPage'\n\nexport interface RequireAuthProps {\n children: ReactNode\n}\n\n/**\n * Wraps `children` with an authentication gate. On mount, fetches\n * `Config.get('ImaginariumApp', 'userPath', '/auth/user')` from the configured\n * API base URL. While loading, renders a small placeholder. On error, renders\n * the configured login component (defaults to the bundled `LoginPage`). On\n * success, renders `children`.\n *\n * Recognized config keys (under `'ImaginariumApp'`):\n * - `userPath` endpoint to check (default `/auth/user`)\n * - `loginPath` URL the login button navigates to (default `/api/login`)\n * - `loginPage` component to render when unauthenticated\n * - `loginTitle` default page heading\n * - `loginSubtitle` default page subtitle\n * - `loginButtonLabel` default button label\n * - `loginBackgroundUrl` URL of an image to show behind the sign-in card\n */\nexport function RequireAuth( { children }: RequireAuthProps ) {\n const { fetchJson } = useImaginariumApi()\n const userPath = Config.get<string>( 'ImaginariumApp', 'userPath', '/auth/user' )\n\n const { isPending, isError } = useQuery( {\n queryKey: [ 'imaginarium', 'auth', 'user', userPath ],\n queryFn: () => fetchJson( userPath ),\n retry: false,\n refetchOnWindowFocus: false,\n } )\n\n if ( isPending ) {\n return <div className=\"p-8 text-muted-foreground\">Checking sign-in…</div>\n }\n\n if ( isError ) {\n const LoginComponent = Config.get<ComponentType<LoginPageProps>>(\n 'ImaginariumApp', 'loginPage', LoginPage,\n )\n const title = Config.get<string | undefined>( 'ImaginariumApp', 'loginTitle', undefined )\n const subtitle = Config.get<string | undefined>( 'ImaginariumApp', 'loginSubtitle', undefined )\n const buttonLabel = Config.get<string | undefined>(\n 'ImaginariumApp', 'loginButtonLabel', undefined,\n )\n const loginPath = Config.get<string>( 'ImaginariumApp', 'loginPath', '/api/login' )\n const backgroundUrl = Config.get<string | undefined>(\n 'ImaginariumApp', 'loginBackgroundUrl', undefined,\n )\n\n const appTitle = Config.get<string>( 'ImaginariumApp', 'title', 'Imaginarium' )\n const resolvedTitle = title ?? `Sign in to ${appTitle}`\n\n return createElement( LoginComponent, {\n loginPath,\n title: resolvedTitle,\n subtitle,\n buttonLabel,\n backgroundUrl,\n } )\n }\n\n return <>{children}</>\n}\n\nexport default RequireAuth\n","import { ActiveTheme } from '../ui-elements'\n\n// ui-elements components read `theme.props`/`theme.classes` off the Theme\n// context and THROW if it is null. `ActiveTheme` provides those methods,\n// delegating to this fallback for any component an appearance doesn't define so\n// components render (unstyled) instead of crashing.\nconst FALLBACK_THEME = {\n props : ( _component : string, variant : unknown, userProps : unknown ) => {\n if ( variant && typeof variant === 'object' ) { return variant }\n return ( userProps && typeof userProps === 'object' ) ? userProps : {}\n },\n classes : ( ...args : unknown[] ) => args.filter( ( a ) => typeof a === 'string' && a ).join( ' ' ),\n subclasses : ( ...args : unknown[] ) => args.filter( ( a ) => typeof a === 'string' && a ).join( ' ' ),\n resources : () => undefined,\n}\n\ntype SharedTheme = { sync? : { start? : ( o : { appearanceId? : string } ) => void } }\n\n// ONE ActiveTheme for the whole document: its constructor calls\n// firebase.initializeApp(…, 'UIActiveTheme'), which throws if run twice, and the\n// appearance CSS it injects is global (`:root` vars + a <head> stylesheet). So\n// there is a single active appearance at any moment. Stashed on globalThis so\n// HMR re-evaluating this module doesn't construct a second instance.\nexport function getSharedTheme() : SharedTheme {\n const g = globalThis as { __imgmActiveTheme? : SharedTheme }\n if ( !g.__imgmActiveTheme ) {\n g.__imgmActiveTheme = new ActiveTheme( { altTheme : FALLBACK_THEME, addWindowCommands : false } ) as SharedTheme\n }\n return g.__imgmActiveTheme\n}\n\n// Point the shared theme at an appearance id (empty -> the built-in fallback).\nexport function pointAppearance( appearanceId : string ) {\n getSharedTheme().sync?.start?.( { appearanceId : appearanceId || undefined } )\n}\n\n// Default appearance shipped with the library so prototypes are themed out of\n// the box in any consuming app, even with no Config or pasted id. Overridden, in\n// order, by a pasted gallery id, then `Config('Prototypes','baseAppearanceId')`,\n// then the app-wide appearance. Without this, the bare fallback applies no\n// variant styling and everything renders unstyled.\nexport const DEFAULT_APPEARANCE_ID = '39oo5B3KISUzzfa1gT1Va1'\n\n// The app-wide baseline appearance. The app root sets it; prototype previews\n// override the shared theme transiently and restore to this when they unmount.\nlet appAppearanceId = ''\nexport function getAppAppearanceId() : string { return appAppearanceId }\nexport function setAppAppearanceId( id : string ) {\n appAppearanceId = id || ''\n pointAppearance( appAppearanceId )\n}\n","import { useEffect, useMemo, type ReactNode } from 'react'\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\nimport { Config } from '@leverege/plugin'\n\nimport { TooltipProvider } from '../components/ui/Tooltip'\nimport { Toaster } from '../components/ui/Toaster'\nimport { ImaginariumApiProvider } from '../api/ImaginariumApiContext'\nimport { RequireAuth } from '../auth/RequireAuth'\nimport { getProviders } from '../plugins/registry'\nimport { Theme } from '../ui-elements'\nimport { getSharedTheme, setAppAppearanceId } from '../theme/activeAppearance'\nimport { AppSidebar, type AppSidebarProps, type IconRef } from './AppSidebar'\nimport { Shell, type ShellProps } from './Shell'\n\n// Applies the app-wide ui-elements appearance theme. Opt-in: when no\n// `ImaginariumApp.appearanceId` is configured, it leaves the tree untouched (no\n// ActiveTheme/Firebase init). When set, it loads that appearance as the global\n// baseline so ui-elements components across the app are themed; prototype\n// previews override it transiently and restore it on exit. The Tailwind shell\n// chrome only changes if that appearance defines the shell's CSS tokens.\nfunction AppThemeBoundary( { children } : { children : ReactNode } ) {\n const appearanceId = Config.get<string>( 'ImaginariumApp', 'appearanceId', '' )\n useEffect( () => { setAppAppearanceId( appearanceId ) }, [ appearanceId ] )\n if ( !appearanceId ) { return <>{children}</> }\n return <Theme theme={getSharedTheme() as never}>{children}</Theme>\n}\n\nfunction withProviders( tree: ReactNode ): ReactNode {\n const providers = getProviders()\n let wrapped = tree\n for ( const { component: Provider } of providers ) {\n wrapped = <Provider>{wrapped}</Provider>\n }\n return wrapped\n}\n\nexport interface ImaginariumAppProps {\n apiBaseUrl?: string\n queryClient?: QueryClient\n title?: string\n titleIcon?: IconRef\n navRightSlot?: AppSidebarProps['rightSlot']\n shellFallback?: ShellProps['fallback']\n children?: ReactNode\n}\n\nconst defaultQueryClient = new QueryClient( {\n defaultOptions: {\n queries: { retry: false, refetchOnWindowFocus: false },\n },\n} )\n\nfunction GatedShell( { title, titleIcon, navRightSlot, shellFallback, children }: {\n title?: string\n titleIcon?: IconRef\n navRightSlot?: AppSidebarProps['rightSlot']\n shellFallback?: ShellProps['fallback']\n children?: ReactNode\n} ) {\n return withProviders(\n <div className=\"flex h-screen overflow-hidden bg-background text-foreground\">\n <AppSidebar title={title} titleIcon={titleIcon} rightSlot={navRightSlot} />\n <Shell fallback={shellFallback}>{children}</Shell>\n </div>,\n )\n}\n\nexport function ImaginariumApp( {\n apiBaseUrl = '/api',\n queryClient,\n title,\n titleIcon,\n navRightSlot,\n shellFallback,\n children,\n}: ImaginariumAppProps ) {\n const qc = useMemo( () => queryClient ?? defaultQueryClient, [ queryClient ] )\n const requireAuth = Config.get<boolean>( 'ImaginariumApp', 'requireAuth', true )\n const resolvedTitleIcon = titleIcon\n ?? Config.get<IconRef | undefined>( 'ImaginariumApp', 'titleIcon', undefined )\n\n const gated = (\n <GatedShell\n title={title}\n titleIcon={resolvedTitleIcon}\n navRightSlot={navRightSlot}\n shellFallback={shellFallback}\n >\n {children}\n </GatedShell>\n )\n\n return (\n <AppThemeBoundary>\n <QueryClientProvider client={qc}>\n <TooltipProvider>\n <ImaginariumApiProvider apiBaseUrl={apiBaseUrl}>\n {requireAuth ? <RequireAuth>{gated}</RequireAuth> : gated}\n <Toaster />\n </ImaginariumApiProvider>\n </TooltipProvider>\n </QueryClientProvider>\n </AppThemeBoundary>\n )\n}\n"],"names":["PageDocsContext","createContext","PageDocsProvider","children","tabMarkdown","setTabMarkdown","useState","jsx","useRegisterTabDocs","markdown","useContext","useEffect","useActiveTabDocs","triggerClass","active","cn","TriggerIcon","DocsTrigger","href","open","onToggle","jsxs","DocsSidePanel","pageDocs","onClose","title","Component","Fragment","ReactMarkdown","mdComponents","renderPageElement","plugin","element","isValidElement","createElement","Shell","fallback","ShellContent","pages","getPages","setOpen","location","useLocation","getPageDocs","o","Switch","page","Route","groupNavItems","items","ungrouped","sectionMap","item","a","b","sections","s","d","STORAGE_COLLAPSED","STORAGE_SECTIONS","readBool","key","v","readSections","parsed","URL_RE","renderIcon","icon","className","AppSidebar","titleIcon","rightSlot","collapsed","setCollapsed","collapsedSections","setCollapsedSections","toggleSidebar","useCallback","toggleSection","label","prev","next","getNavItems","topBarItems","getTopBarItems","ChevronLeft","path","Icon","isActive","Link","section","index","isSectionCollapsed","showDivider","ChevronDown","C","ToastProvider","ToastPrimitives","ToastViewport","React","props","ref","toastVariants","cva","Toast","variant","ToastAction","ToastClose","X","ToastTitle","ToastDescription","Toaster","toasts","useToast","id","description","action","GoogleGlyph","ERROR_MESSAGES","readUrlError","code","LoginPage","loginPath","subtitle","buttonLabel","backgroundUrl","errorMessage","message","hasBackground","Card","CardHeader","CardTitle","CardDescription","CardContent","Button","RequireAuth","fetchJson","useImaginariumApi","userPath","Config","isPending","isError","useQuery","LoginComponent","appTitle","resolvedTitle","FALLBACK_THEME","_component","userProps","args","getSharedTheme","g","ActiveTheme","pointAppearance","appearanceId","_b","_a","DEFAULT_APPEARANCE_ID","appAppearanceId","getAppAppearanceId","setAppAppearanceId","AppThemeBoundary","Theme","withProviders","tree","providers","getProviders","wrapped","Provider","defaultQueryClient","QueryClient","GatedShell","navRightSlot","shellFallback","ImaginariumApp","apiBaseUrl","queryClient","qc","useMemo","requireAuth","resolvedTitleIcon","gated","QueryClientProvider","TooltipProvider","ImaginariumApiProvider"],"mappings":"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"}
1
+ {"version":3,"file":"ImaginariumApp-DAu-61PK.js","sources":["../src/docs/PageDocsContext.tsx","../src/docs/DocsPanel.tsx","../src/shell/Shell.tsx","../src/shell/groupNavItems.ts","../src/shell/AppSidebar.tsx","../src/components/ui/Toast.tsx","../src/components/ui/Toaster.tsx","../src/auth/LoginPage.tsx","../src/auth/RequireAuth.tsx","../src/theme/activeAppearance.ts","../src/shell/ImaginariumApp.tsx"],"sourcesContent":["import { createContext, useContext, useEffect, useState, type ReactNode } from 'react'\n\ninterface PageDocsContextValue {\n tabMarkdown: string | null\n setTabMarkdown: ( markdown: string | null ) => void\n}\n\nconst PageDocsContext = createContext<PageDocsContextValue>( {\n tabMarkdown: null,\n setTabMarkdown: () => {},\n} )\n\nexport function PageDocsProvider( { children }: { children: ReactNode } ) {\n const [ tabMarkdown, setTabMarkdown ] = useState<string | null>( null )\n return (\n <PageDocsContext.Provider value={{ tabMarkdown, setTabMarkdown }}>\n {children}\n </PageDocsContext.Provider>\n )\n}\n\n/**\n * Call inside a page component to register tab-specific docs.\n * When the component unmounts or markdown changes, the panel falls back\n * to the page-level docs registered via addPageDocs().\n */\nexport function useRegisterTabDocs( markdown: string ) {\n const { setTabMarkdown } = useContext( PageDocsContext )\n useEffect( () => {\n setTabMarkdown( markdown )\n return () => { setTabMarkdown( null ) }\n }, [ markdown, setTabMarkdown ] )\n}\n\nexport function useActiveTabDocs(): string | null {\n return useContext( PageDocsContext ).tabMarkdown\n}\n","import ReactMarkdown from 'react-markdown'\nimport { cn } from '../lib/utils'\nimport type { PageDocsPlugin } from '../plugins/types'\nimport { mdComponents } from './mdComponents'\n\ninterface DocsTriggerProps {\n href?: string\n open?: boolean\n onToggle?: () => void\n}\n\nconst triggerClass = ( active: boolean ) => cn(\n 'flex items-center gap-1.5 rounded-md border px-2.5 py-1 text-xs font-medium transition-colors',\n active\n ? 'border-primary/50 bg-primary/10 text-primary'\n : 'border-border bg-card text-muted-foreground hover:border-primary/30 hover:text-foreground'\n)\n\nconst TriggerIcon = () => (\n <span className=\"flex h-3.5 w-3.5 items-center justify-center rounded-full border border-current text-[9px] font-bold leading-none\">\n i\n </span>\n)\n\nexport function DocsTrigger( { href, open = false, onToggle }: DocsTriggerProps ) {\n if ( href != null ) {\n return (\n <div>\n <a href={href} target=\"_blank\" rel=\"noopener noreferrer\" className={triggerClass( false )}>\n <TriggerIcon />\n Docs\n </a>\n </div>\n )\n }\n return (\n <div>\n <button onClick={onToggle} className={triggerClass( open )}>\n <TriggerIcon />\n Docs\n </button>\n </div>\n )\n}\n\ninterface DocsSidePanelProps {\n pageDocs: PageDocsPlugin\n tabMarkdown: string | null\n onClose: () => void\n}\n\nexport function DocsSidePanel( { pageDocs, tabMarkdown, onClose }: DocsSidePanelProps ) {\n const title = pageDocs.path.replace( /^\\//, '' ) || 'docs'\n const Component = pageDocs.component\n\n return (\n <aside className=\"absolute right-0 top-0 bottom-0 z-20 w-[26rem] border-l border-border bg-card flex flex-col overflow-hidden shadow-xl\">\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-border\">\n <span className=\"text-sm font-semibold text-foreground\">{title}</span>\n <button\n onClick={onClose}\n className=\"text-xs text-muted-foreground hover:text-foreground transition-colors\"\n aria-label=\"Close docs panel\"\n >\n ✕\n </button>\n </div>\n\n <div className=\"flex-1 overflow-y-auto px-4 py-4\">\n {tabMarkdown != null && (\n <>\n <ReactMarkdown components={mdComponents}>{tabMarkdown}</ReactMarkdown>\n <hr className=\"border-border my-3\" />\n </>\n )}\n {Component != null && <Component />}\n </div>\n </aside>\n )\n}\n","import { isValidElement, createElement, useState, useEffect, type ReactNode } from 'react'\nimport { Route, Switch, useLocation } from 'wouter'\n\nimport { getPageDocs, getPages } from '../plugins/registry'\nimport { PageDocsProvider, useActiveTabDocs } from '../docs/PageDocsContext'\nimport { DocsTrigger, DocsSidePanel } from '../docs/DocsPanel'\nimport type { PagePlugin } from '../plugins/types'\n\nfunction renderPageElement( plugin: PagePlugin ): ReactNode {\n const { element } = plugin\n if ( isValidElement( element ) ) { return element }\n if ( typeof element === 'function' ) {\n return createElement( element as React.ComponentType )\n }\n return element as ReactNode\n}\n\nexport interface ShellProps {\n fallback?: ReactNode\n children?: ReactNode\n}\n\nexport function Shell( { fallback, children }: ShellProps ) {\n return (\n <PageDocsProvider>\n <ShellContent fallback={fallback}>{children}</ShellContent>\n </PageDocsProvider>\n )\n}\n\nfunction ShellContent( { fallback, children }: ShellProps ) {\n const pages = getPages()\n const [ open, setOpen ] = useState( false )\n const [ location ] = useLocation()\n const pageDocs = getPageDocs( location )\n\n useEffect( () => { setOpen( false ) }, [ location ] )\n const tabMarkdown = useActiveTabDocs()\n\n return (\n <div className=\"relative flex flex-1 overflow-hidden\">\n <main className=\"relative flex-1 overflow-y-auto\">\n {pageDocs != null && (\n <div className=\"flex justify-end px-6 pt-4\">\n {pageDocs.href != null\n ? <DocsTrigger href={pageDocs.href} />\n : <DocsTrigger open={open} onToggle={() => setOpen( ( o ) => !o )} />}\n </div>\n )}\n <div className=\"px-6 pb-6 pt-4\">\n {children}\n <Switch>\n {pages.map( ( page ) => (\n <Route key={page.path} path={page.path}>\n {renderPageElement( page )}\n </Route>\n ) )}\n <Route>{fallback ?? <div className=\"p-8 text-muted-foreground\">Not found</div>}</Route>\n </Switch>\n </div>\n </main>\n {open && pageDocs != null && pageDocs.href == null && (\n <DocsSidePanel\n pageDocs={pageDocs}\n tabMarkdown={tabMarkdown}\n onClose={() => setOpen( false )}\n />\n )}\n </div>\n )\n}\n","import type { NavItemPlugin } from '../plugins/types'\n\nexport interface NavSection {\n label: string\n sectionSort: number\n items: NavItemPlugin[]\n}\n\nexport interface GroupedNav {\n ungrouped: NavItemPlugin[]\n sections: NavSection[]\n}\n\nexport function groupNavItems( items: NavItemPlugin[] ): GroupedNav {\n const ungrouped: NavItemPlugin[] = []\n const sectionMap = new Map<string, NavSection>()\n\n for ( const item of items ) {\n if ( !item.section ) {\n ungrouped.push( item )\n continue\n }\n if ( !sectionMap.has( item.section ) ) {\n sectionMap.set( item.section, {\n label : item.section,\n sectionSort : item.sectionSort ?? item.sort ?? 0,\n items : [],\n } )\n }\n sectionMap.get( item.section )!.items.push( item )\n }\n\n ungrouped.sort( ( a, b ) => ( a.sort ?? 0 ) - ( b.sort ?? 0 ) )\n\n const sections = Array.from( sectionMap.values() )\n for ( const s of sections ) {\n s.items.sort( ( a, b ) => ( a.sort ?? 0 ) - ( b.sort ?? 0 ) )\n }\n sections.sort( ( a, b ) => {\n const d = a.sectionSort - b.sectionSort\n return d !== 0 ? d : a.label.localeCompare( b.label )\n } )\n\n return { ungrouped, sections }\n}\n","import { useState, useEffect, useCallback } from 'react'\nimport { Link, useLocation } from 'wouter'\nimport { ChevronLeft, ChevronDown } from 'lucide-react'\nimport { cn } from '../lib/utils'\nimport { getNavItems, getTopBarItems } from '../plugins/registry'\nimport { groupNavItems } from './groupNavItems'\nimport type { ComponentType } from 'react'\n\n/**\n * Accepted icon forms (anywhere we render an inline icon):\n * - React component: `Settings` from lucide-react\n * - URL string: `/logo.png`, `https://...`, `data:image/...`, `blob:...`\n * - CSS class string: `fa-solid fa-gear`, `material-icons` (rendered on a <span>)\n */\nexport type IconRef = ComponentType<{ className?: string }> | string\n\nconst STORAGE_COLLAPSED = 'imaginarium.ui.sidebar.collapsed'\nconst STORAGE_SECTIONS = 'imaginarium.ui.sidebar.sections'\n\nfunction readBool( key: string, fallback: boolean ): boolean {\n try {\n const v = localStorage.getItem( key )\n return v === null ? fallback : v === 'true'\n } catch { return fallback }\n}\n\nfunction readSections(): Set<string> {\n try {\n const v = localStorage.getItem( STORAGE_SECTIONS )\n if ( !v ) { return new Set() }\n const parsed = JSON.parse( v )\n return new Set( Array.isArray( parsed ) ? parsed as string[] : [] )\n } catch { return new Set() }\n}\n\nconst URL_RE = /^(https?:|data:|blob:|\\/|\\.\\/|\\.\\.\\/)/\n\nfunction renderIcon( icon: IconRef | undefined, className: string ) {\n if ( !icon ) { return null }\n if ( typeof icon === 'string' ) {\n if ( URL_RE.test( icon ) ) { return <img src={icon} alt=\"\" className={className} /> }\n return <span className={`${icon} ${className}`} aria-hidden=\"true\" />\n }\n const Icon = icon\n return <Icon className={className} />\n}\n\nexport interface AppSidebarProps {\n title?: string\n titleIcon?: IconRef\n rightSlot?: React.ReactNode\n}\n\nexport function AppSidebar( { title = 'Imaginarium', titleIcon, rightSlot }: AppSidebarProps ) {\n const [ location ] = useLocation()\n const [ collapsed, setCollapsed ] = useState( () => readBool( STORAGE_COLLAPSED, false ) )\n const [ collapsedSections, setCollapsedSections ] = useState<Set<string>>( readSections )\n\n useEffect( () => {\n try { localStorage.setItem( STORAGE_COLLAPSED, String( collapsed ) ) } catch { /* ignore */ }\n }, [ collapsed ] )\n\n useEffect( () => {\n try {\n localStorage.setItem( STORAGE_SECTIONS, JSON.stringify( Array.from( collapsedSections ) ) )\n } catch { /* ignore */ }\n }, [ collapsedSections ] )\n\n const toggleSidebar = useCallback( () => setCollapsed( v => !v ), [] )\n\n const toggleSection = useCallback( ( label: string ) => {\n setCollapsedSections( prev => {\n const next = new Set( prev )\n next.has( label ) ? next.delete( label ) : next.add( label )\n return next\n } )\n }, [] )\n\n const { ungrouped, sections } = groupNavItems( getNavItems() )\n const topBarItems = getTopBarItems()\n\n return (\n <aside\n className={cn(\n 'flex flex-col flex-shrink-0 border-r bg-background transition-[width] duration-200 ease-in-out overflow-hidden',\n collapsed ? 'w-[52px]' : 'w-[220px]',\n )}\n >\n {/* Header */}\n <div className=\"flex h-[52px] flex-shrink-0 items-center border-b px-2.5 gap-2\">\n {!collapsed && renderIcon( titleIcon, 'h-6 w-6' )}\n {!collapsed && (\n <span className=\"flex-1 truncate text-sm font-semibold\">{title}</span>\n )}\n <button\n onClick={toggleSidebar}\n aria-label={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}\n className={cn(\n 'flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-md border text-muted-foreground',\n 'hover:bg-accent hover:text-accent-foreground transition-colors',\n collapsed && 'mx-auto border-transparent',\n )}\n >\n <ChevronLeft\n className={cn( 'h-4 w-4 transition-transform duration-200', collapsed && 'rotate-180' )}\n />\n </button>\n </div>\n\n {/* Nav */}\n <nav className=\"flex flex-1 flex-col gap-0.5 overflow-y-auto overflow-x-hidden p-1.5\">\n {/* Ungrouped items */}\n {ungrouped.map( ( { path, label, icon: Icon } ) => {\n const isActive = location === path || location.startsWith( `${path}/` )\n return (\n <Link\n key={path}\n href={path}\n title={collapsed ? label : undefined}\n className={cn(\n 'relative flex items-center gap-2.5 rounded-md px-2 py-1.5 text-sm text-muted-foreground',\n 'hover:bg-accent hover:text-accent-foreground transition-colors whitespace-nowrap',\n isActive && 'bg-accent/50 text-accent-foreground font-medium',\n collapsed && 'justify-center px-2',\n )}\n >\n {Icon && <Icon className=\"h-4 w-4 flex-shrink-0\" />}\n {!collapsed && <span>{label}</span>}\n </Link>\n )\n } )}\n\n {/* Sections */}\n {sections.map( ( section, index ) => {\n const isSectionCollapsed = !collapsed && collapsedSections.has( section.label )\n // The divider separates a section from what's above it. Skip it for the\n // first section when nothing precedes it (no ungrouped items) so it\n // doesn't stack under the header's border-b and read as a double line.\n const showDivider = index > 0 || ungrouped.length > 0\n return (\n <div key={section.label} className=\"flex flex-col\">\n {/* Section divider + header */}\n {showDivider && <div className=\"my-1.5 h-px bg-border\" />}\n {!collapsed && (\n <button\n onClick={() => toggleSection( section.label )}\n className={cn(\n 'flex items-center justify-between px-2 pb-1 pt-2.5',\n 'text-[10px] font-semibold uppercase tracking-widest text-muted-foreground',\n 'hover:text-foreground transition-colors cursor-pointer rounded-sm',\n )}\n >\n {section.label}\n <ChevronDown\n className={cn(\n 'h-3 w-3 transition-transform duration-200',\n isSectionCollapsed && '-rotate-90',\n )}\n />\n </button>\n )}\n\n {/* Section items */}\n <div\n className={cn(\n 'flex flex-col gap-0.5 overflow-hidden transition-all duration-200',\n isSectionCollapsed ? 'max-h-0 opacity-0' : 'max-h-screen opacity-100',\n )}\n >\n {section.items.map( ( { path, label, icon: Icon } ) => {\n const isActive = location === path || location.startsWith( `${path}/` )\n return (\n <Link\n key={path}\n href={path}\n title={collapsed ? label : undefined}\n className={cn(\n 'relative flex items-center gap-2.5 rounded-md px-2 py-1.5 text-sm text-muted-foreground',\n 'hover:bg-accent hover:text-accent-foreground transition-colors whitespace-nowrap',\n isActive && 'bg-accent/50 text-accent-foreground font-medium',\n collapsed && 'justify-center px-2',\n )}\n >\n {Icon && <Icon className=\"h-4 w-4 flex-shrink-0\" />}\n {!collapsed && <span>{label}</span>}\n </Link>\n )\n } )}\n </div>\n </div>\n )\n } )}\n </nav>\n\n {/* Footer: rightSlot + TopBarItems */}\n <div className={cn(\n 'flex flex-shrink-0 items-center border-t p-1.5',\n collapsed ? 'flex-col gap-1' : 'flex-row justify-end gap-0.5',\n )}>\n {!collapsed && rightSlot}\n {topBarItems.map( ( item ) => {\n const C = item.component\n return <C key={item.id} />\n } )}\n </div>\n </aside>\n )\n}\n","import * as React from 'react'\nimport * as ToastPrimitives from '@radix-ui/react-toast'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { X } from 'lucide-react'\n\nimport { cn } from '../../lib/utils'\n\nconst ToastProvider = ToastPrimitives.Provider\n\nconst ToastViewport = React.forwardRef<\n React.ElementRef<typeof ToastPrimitives.Viewport>,\n React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport>\n>( ( { className, ...props }, ref ) => (\n <ToastPrimitives.Viewport\n ref={ref}\n className={cn(\n 'fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]',\n className,\n )}\n {...props}\n />\n) )\nToastViewport.displayName = ToastPrimitives.Viewport.displayName\n\nconst toastVariants = cva(\n 'group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full',\n {\n variants: {\n variant: {\n default: 'border bg-background text-foreground',\n destructive: 'destructive group border-destructive bg-destructive text-destructive-foreground',\n },\n },\n defaultVariants: { variant: 'default' },\n },\n)\n\nconst Toast = React.forwardRef<\n React.ElementRef<typeof ToastPrimitives.Root>,\n React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> & VariantProps<typeof toastVariants>\n>( ( { className, variant, ...props }, ref ) => (\n <ToastPrimitives.Root ref={ref} className={cn( toastVariants( { variant } ), className )} {...props} />\n) )\nToast.displayName = ToastPrimitives.Root.displayName\n\nconst ToastAction = React.forwardRef<\n React.ElementRef<typeof ToastPrimitives.Action>,\n React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>\n>( ( { className, ...props }, ref ) => (\n <ToastPrimitives.Action\n ref={ref}\n className={cn(\n 'inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',\n className,\n )}\n {...props}\n />\n) )\nToastAction.displayName = ToastPrimitives.Action.displayName\n\nconst ToastClose = React.forwardRef<\n React.ElementRef<typeof ToastPrimitives.Close>,\n React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>\n>( ( { className, ...props }, ref ) => (\n <ToastPrimitives.Close\n ref={ref}\n className={cn(\n 'absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100',\n className,\n )}\n toast-close=\"\"\n {...props}\n >\n <X className=\"h-4 w-4\" />\n </ToastPrimitives.Close>\n) )\nToastClose.displayName = ToastPrimitives.Close.displayName\n\nconst ToastTitle = React.forwardRef<\n React.ElementRef<typeof ToastPrimitives.Title>,\n React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>\n>( ( { className, ...props }, ref ) => (\n <ToastPrimitives.Title ref={ref} className={cn( 'text-sm font-semibold', className )} {...props} />\n) )\nToastTitle.displayName = ToastPrimitives.Title.displayName\n\nconst ToastDescription = React.forwardRef<\n React.ElementRef<typeof ToastPrimitives.Description>,\n React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>\n>( ( { className, ...props }, ref ) => (\n <ToastPrimitives.Description ref={ref} className={cn( 'text-sm opacity-90', className )} {...props} />\n) )\nToastDescription.displayName = ToastPrimitives.Description.displayName\n\nexport type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>\nexport type ToastActionElement = React.ReactElement<typeof ToastAction>\n\nexport {\n ToastProvider,\n ToastViewport,\n Toast,\n ToastTitle,\n ToastDescription,\n ToastClose,\n ToastAction,\n}\n","import { useToast } from '../../hooks/useToast'\nimport {\n Toast,\n ToastClose,\n ToastDescription,\n ToastProvider,\n ToastTitle,\n ToastViewport,\n} from './Toast'\n\nexport function Toaster() {\n const { toasts } = useToast()\n\n return (\n <ToastProvider>\n {toasts.map( ( { id, title, description, action, ...props } ) => (\n <Toast key={id} {...props}>\n <div className=\"grid gap-1\">\n {title && <ToastTitle>{title}</ToastTitle>}\n {description && <ToastDescription>{description}</ToastDescription>}\n </div>\n {action}\n <ToastClose />\n </Toast>\n ) )}\n <ToastViewport />\n </ToastProvider>\n )\n}\n","import { Button } from '../components/ui/Button'\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from '../components/ui/Card'\n\nexport interface LoginPageProps {\n loginPath: string\n title?: string\n subtitle?: string\n buttonLabel?: string\n /** URL of an image to show behind the sign-in card. Empty/null skips it. */\n backgroundUrl?: string\n /** Optional message shown above the button (e.g. an error from a failed prior attempt). */\n errorMessage?: string\n}\n\nfunction GoogleGlyph( { className }: { className?: string } ) {\n return (\n <svg viewBox=\"0 0 24 24\" className={className} aria-hidden=\"true\">\n <path fill=\"#4285F4\" d=\"M23.49 12.27c0-.79-.07-1.54-.19-2.27H12v4.51h6.16c-.27 1.4-1.04 2.59-2.21 3.41v2.77h3.59c2.08-1.92 3.95-4.74 3.95-8.42z\" />\n <path fill=\"#34A853\" d=\"M12 24c2.97 0 5.46-.98 7.28-2.66l-3.59-2.77c-.98.66-2.23 1.06-3.69 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 21.53 7.7 24 12 24z\" />\n <path fill=\"#FBBC05\" d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\" />\n <path fill=\"#EA4335\" d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\" />\n </svg>\n )\n}\n\nconst ERROR_MESSAGES: Record<string, string> = {\n auth_failed : 'Sign-in failed. Please try again.',\n}\n\nfunction readUrlError(): string | undefined {\n if ( typeof window === 'undefined' ) { \n return undefined \n }\n const code = new URLSearchParams( window.location.search ).get( 'error' )\n if ( !code ) { \n return undefined \n }\n return ERROR_MESSAGES[code] ?? `Sign-in error: ${code}`\n}\n\nexport function LoginPage( {\n loginPath,\n title = 'Sign in',\n subtitle,\n buttonLabel = 'Sign in with Google',\n backgroundUrl,\n errorMessage,\n}: LoginPageProps ) {\n const message = errorMessage ?? readUrlError()\n const hasBackground = Boolean( backgroundUrl )\n\n return (\n <div\n className=\"min-h-screen flex items-center justify-center bg-background bg-cover bg-center px-4\"\n style={hasBackground ? { backgroundImage: `url(${backgroundUrl})` } : undefined}\n >\n <Card className={`w-full max-w-md ${hasBackground ? 'backdrop-blur-sm bg-card/90' : ''}`}>\n <CardHeader className=\"text-center\">\n <CardTitle>{title}</CardTitle>\n {subtitle && <CardDescription>{subtitle}</CardDescription>}\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {message && (\n <div className=\"rounded-md border border-destructive bg-destructive/10 px-4 py-2 text-sm text-destructive\">\n {message}\n </div>\n )}\n <Button\n className=\"w-full\"\n variant=\"outline\"\n onClick={() => { window.location.href = loginPath }}\n >\n <GoogleGlyph className=\"h-5 w-5 mr-2\" />\n {buttonLabel}\n </Button>\n </CardContent>\n </Card>\n </div>\n )\n}\n\nexport default LoginPage\n","import { createElement, type ComponentType, type ReactNode } from 'react'\nimport { useQuery } from '@tanstack/react-query'\nimport { Config } from '@leverege/plugin'\n\nimport { useImaginariumApi } from '../api/ImaginariumApiContext'\nimport { LoginPage, type LoginPageProps } from './LoginPage'\n\nexport interface RequireAuthProps {\n children: ReactNode\n}\n\n/**\n * Wraps `children` with an authentication gate. On mount, fetches\n * `Config.get('ImaginariumApp', 'userPath', '/auth/user')` from the configured\n * API base URL. While loading, renders a small placeholder. On error, renders\n * the configured login component (defaults to the bundled `LoginPage`). On\n * success, renders `children`.\n *\n * Recognized config keys (under `'ImaginariumApp'`):\n * - `userPath` endpoint to check (default `/auth/user`)\n * - `loginPath` URL the login button navigates to (default `/api/login`)\n * - `loginPage` component to render when unauthenticated\n * - `loginTitle` default page heading\n * - `loginSubtitle` default page subtitle\n * - `loginButtonLabel` default button label\n * - `loginBackgroundUrl` URL of an image to show behind the sign-in card\n */\nexport function RequireAuth( { children }: RequireAuthProps ) {\n const { fetchJson } = useImaginariumApi()\n const userPath = Config.get<string>( 'ImaginariumApp', 'userPath', '/auth/user' )\n\n const { isPending, isError } = useQuery( {\n queryKey: [ 'imaginarium', 'auth', 'user', userPath ],\n queryFn: () => fetchJson( userPath ),\n retry: false,\n refetchOnWindowFocus: false,\n } )\n\n if ( isPending ) {\n return <div className=\"p-8 text-muted-foreground\">Checking sign-in…</div>\n }\n\n if ( isError ) {\n const LoginComponent = Config.get<ComponentType<LoginPageProps>>(\n 'ImaginariumApp', 'loginPage', LoginPage,\n )\n const title = Config.get<string | undefined>( 'ImaginariumApp', 'loginTitle', undefined )\n const subtitle = Config.get<string | undefined>( 'ImaginariumApp', 'loginSubtitle', undefined )\n const buttonLabel = Config.get<string | undefined>(\n 'ImaginariumApp', 'loginButtonLabel', undefined,\n )\n const loginPath = Config.get<string>( 'ImaginariumApp', 'loginPath', '/api/login' )\n const backgroundUrl = Config.get<string | undefined>(\n 'ImaginariumApp', 'loginBackgroundUrl', undefined,\n )\n\n const appTitle = Config.get<string>( 'ImaginariumApp', 'title', 'Imaginarium' )\n const resolvedTitle = title ?? `Sign in to ${appTitle}`\n\n return createElement( LoginComponent, {\n loginPath,\n title: resolvedTitle,\n subtitle,\n buttonLabel,\n backgroundUrl,\n } )\n }\n\n return <>{children}</>\n}\n\nexport default RequireAuth\n","import { ActiveTheme } from '../ui-elements'\n\n// ui-elements components read `theme.props`/`theme.classes` off the Theme\n// context and THROW if it is null. `ActiveTheme` provides those methods,\n// delegating to this fallback for any component an appearance doesn't define so\n// components render (unstyled) instead of crashing.\nconst FALLBACK_THEME = {\n props : ( _component : string, variant : unknown, userProps : unknown ) => {\n if ( variant && typeof variant === 'object' ) { return variant }\n return ( userProps && typeof userProps === 'object' ) ? userProps : {}\n },\n classes : ( ...args : unknown[] ) => args.filter( ( a ) => typeof a === 'string' && a ).join( ' ' ),\n subclasses : ( ...args : unknown[] ) => args.filter( ( a ) => typeof a === 'string' && a ).join( ' ' ),\n resources : () => undefined,\n}\n\ntype SharedTheme = { sync? : { start? : ( o : { appearanceId? : string } ) => void } }\n\n// ONE ActiveTheme for the whole document: its constructor calls\n// firebase.initializeApp(…, 'UIActiveTheme'), which throws if run twice, and the\n// appearance CSS it injects is global (`:root` vars + a <head> stylesheet). So\n// there is a single active appearance at any moment. Stashed on globalThis so\n// HMR re-evaluating this module doesn't construct a second instance.\nexport function getSharedTheme() : SharedTheme {\n const g = globalThis as { __imgmActiveTheme? : SharedTheme }\n if ( !g.__imgmActiveTheme ) {\n g.__imgmActiveTheme = new ActiveTheme( { altTheme : FALLBACK_THEME, addWindowCommands : false } ) as SharedTheme\n }\n return g.__imgmActiveTheme\n}\n\n// Point the shared theme at an appearance id (empty -> the built-in fallback).\nexport function pointAppearance( appearanceId : string ) {\n getSharedTheme().sync?.start?.( { appearanceId : appearanceId || undefined } )\n}\n\n// Default appearance shipped with the library: every prototype uses THIS by\n// default in any consuming app, so the variants prototypes are authored against\n// always resolve. Overridden only by a pasted gallery id (persisted in\n// localStorage) or `Config('Prototypes','baseAppearanceId')` — NOT by the host\n// app's own appearance, which must not shadow the shipped default.\nexport const DEFAULT_APPEARANCE_ID = '39oo5B3KISUzzfa1gT1Va1'\n\n// The app-wide baseline appearance. The app root sets it; prototype previews\n// override the shared theme transiently and restore to this when they unmount.\nlet appAppearanceId = ''\nexport function getAppAppearanceId() : string { return appAppearanceId }\nexport function setAppAppearanceId( id : string ) {\n appAppearanceId = id || ''\n pointAppearance( appAppearanceId )\n}\n","import { useEffect, useMemo, type ReactNode } from 'react'\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\nimport { Config } from '@leverege/plugin'\n\nimport { TooltipProvider } from '../components/ui/Tooltip'\nimport { Toaster } from '../components/ui/Toaster'\nimport { ImaginariumApiProvider } from '../api/ImaginariumApiContext'\nimport { RequireAuth } from '../auth/RequireAuth'\nimport { getProviders } from '../plugins/registry'\nimport { Theme } from '../ui-elements'\nimport { getSharedTheme, setAppAppearanceId } from '../theme/activeAppearance'\nimport { AppSidebar, type AppSidebarProps, type IconRef } from './AppSidebar'\nimport { Shell, type ShellProps } from './Shell'\n\n// Applies the app-wide ui-elements appearance theme. Opt-in: when no\n// `ImaginariumApp.appearanceId` is configured, it leaves the tree untouched (no\n// ActiveTheme/Firebase init). When set, it loads that appearance as the global\n// baseline so ui-elements components across the app are themed; prototype\n// previews override it transiently and restore it on exit. The Tailwind shell\n// chrome only changes if that appearance defines the shell's CSS tokens.\nfunction AppThemeBoundary( { children } : { children : ReactNode } ) {\n const appearanceId = Config.get<string>( 'ImaginariumApp', 'appearanceId', '' )\n useEffect( () => { setAppAppearanceId( appearanceId ) }, [ appearanceId ] )\n if ( !appearanceId ) { return <>{children}</> }\n return <Theme theme={getSharedTheme() as never}>{children}</Theme>\n}\n\nfunction withProviders( tree: ReactNode ): ReactNode {\n const providers = getProviders()\n let wrapped = tree\n for ( const { component: Provider } of providers ) {\n wrapped = <Provider>{wrapped}</Provider>\n }\n return wrapped\n}\n\nexport interface ImaginariumAppProps {\n apiBaseUrl?: string\n queryClient?: QueryClient\n title?: string\n titleIcon?: IconRef\n navRightSlot?: AppSidebarProps['rightSlot']\n shellFallback?: ShellProps['fallback']\n children?: ReactNode\n}\n\nconst defaultQueryClient = new QueryClient( {\n defaultOptions: {\n queries: { retry: false, refetchOnWindowFocus: false },\n },\n} )\n\nfunction GatedShell( { title, titleIcon, navRightSlot, shellFallback, children }: {\n title?: string\n titleIcon?: IconRef\n navRightSlot?: AppSidebarProps['rightSlot']\n shellFallback?: ShellProps['fallback']\n children?: ReactNode\n} ) {\n return withProviders(\n <div className=\"flex h-screen overflow-hidden bg-background text-foreground\">\n <AppSidebar title={title} titleIcon={titleIcon} rightSlot={navRightSlot} />\n <Shell fallback={shellFallback}>{children}</Shell>\n </div>,\n )\n}\n\nexport function ImaginariumApp( {\n apiBaseUrl = '/api',\n queryClient,\n title,\n titleIcon,\n navRightSlot,\n shellFallback,\n children,\n}: ImaginariumAppProps ) {\n const qc = useMemo( () => queryClient ?? defaultQueryClient, [ queryClient ] )\n const requireAuth = Config.get<boolean>( 'ImaginariumApp', 'requireAuth', true )\n const resolvedTitleIcon = titleIcon\n ?? Config.get<IconRef | undefined>( 'ImaginariumApp', 'titleIcon', undefined )\n\n const gated = (\n <GatedShell\n title={title}\n titleIcon={resolvedTitleIcon}\n navRightSlot={navRightSlot}\n shellFallback={shellFallback}\n >\n {children}\n </GatedShell>\n )\n\n return (\n <AppThemeBoundary>\n <QueryClientProvider client={qc}>\n <TooltipProvider>\n <ImaginariumApiProvider apiBaseUrl={apiBaseUrl}>\n {requireAuth ? <RequireAuth>{gated}</RequireAuth> : gated}\n <Toaster />\n </ImaginariumApiProvider>\n </TooltipProvider>\n </QueryClientProvider>\n </AppThemeBoundary>\n )\n}\n"],"names":["PageDocsContext","createContext","PageDocsProvider","children","tabMarkdown","setTabMarkdown","useState","jsx","useRegisterTabDocs","markdown","useContext","useEffect","useActiveTabDocs","triggerClass","active","cn","TriggerIcon","DocsTrigger","href","open","onToggle","jsxs","DocsSidePanel","pageDocs","onClose","title","Component","Fragment","ReactMarkdown","mdComponents","renderPageElement","plugin","element","isValidElement","createElement","Shell","fallback","ShellContent","pages","getPages","setOpen","location","useLocation","getPageDocs","o","Switch","page","Route","groupNavItems","items","ungrouped","sectionMap","item","a","b","sections","s","d","STORAGE_COLLAPSED","STORAGE_SECTIONS","readBool","key","v","readSections","parsed","URL_RE","renderIcon","icon","className","AppSidebar","titleIcon","rightSlot","collapsed","setCollapsed","collapsedSections","setCollapsedSections","toggleSidebar","useCallback","toggleSection","label","prev","next","getNavItems","topBarItems","getTopBarItems","ChevronLeft","path","Icon","isActive","Link","section","index","isSectionCollapsed","showDivider","ChevronDown","C","ToastProvider","ToastPrimitives","ToastViewport","React","props","ref","toastVariants","cva","Toast","variant","ToastAction","ToastClose","X","ToastTitle","ToastDescription","Toaster","toasts","useToast","id","description","action","GoogleGlyph","ERROR_MESSAGES","readUrlError","code","LoginPage","loginPath","subtitle","buttonLabel","backgroundUrl","errorMessage","message","hasBackground","Card","CardHeader","CardTitle","CardDescription","CardContent","Button","RequireAuth","fetchJson","useImaginariumApi","userPath","Config","isPending","isError","useQuery","LoginComponent","appTitle","resolvedTitle","FALLBACK_THEME","_component","userProps","args","getSharedTheme","g","ActiveTheme","pointAppearance","appearanceId","_b","_a","DEFAULT_APPEARANCE_ID","appAppearanceId","getAppAppearanceId","setAppAppearanceId","AppThemeBoundary","Theme","withProviders","tree","providers","getProviders","wrapped","Provider","defaultQueryClient","QueryClient","GatedShell","navRightSlot","shellFallback","ImaginariumApp","apiBaseUrl","queryClient","qc","useMemo","requireAuth","resolvedTitleIcon","gated","QueryClientProvider","TooltipProvider","ImaginariumApiProvider"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ImaginariumApp-DUtoZlIK.cjs","sources":["../src/docs/PageDocsContext.tsx","../src/docs/DocsPanel.tsx","../src/shell/Shell.tsx","../src/shell/groupNavItems.ts","../src/shell/AppSidebar.tsx","../src/components/ui/Toast.tsx","../src/components/ui/Toaster.tsx","../src/auth/LoginPage.tsx","../src/auth/RequireAuth.tsx","../src/theme/activeAppearance.ts","../src/shell/ImaginariumApp.tsx"],"sourcesContent":["import { createContext, useContext, useEffect, useState, type ReactNode } from 'react'\n\ninterface PageDocsContextValue {\n tabMarkdown: string | null\n setTabMarkdown: ( markdown: string | null ) => void\n}\n\nconst PageDocsContext = createContext<PageDocsContextValue>( {\n tabMarkdown: null,\n setTabMarkdown: () => {},\n} )\n\nexport function PageDocsProvider( { children }: { children: ReactNode } ) {\n const [ tabMarkdown, setTabMarkdown ] = useState<string | null>( null )\n return (\n <PageDocsContext.Provider value={{ tabMarkdown, setTabMarkdown }}>\n {children}\n </PageDocsContext.Provider>\n )\n}\n\n/**\n * Call inside a page component to register tab-specific docs.\n * When the component unmounts or markdown changes, the panel falls back\n * to the page-level docs registered via addPageDocs().\n */\nexport function useRegisterTabDocs( markdown: string ) {\n const { setTabMarkdown } = useContext( PageDocsContext )\n useEffect( () => {\n setTabMarkdown( markdown )\n return () => { setTabMarkdown( null ) }\n }, [ markdown, setTabMarkdown ] )\n}\n\nexport function useActiveTabDocs(): string | null {\n return useContext( PageDocsContext ).tabMarkdown\n}\n","import ReactMarkdown from 'react-markdown'\nimport { cn } from '../lib/utils'\nimport type { PageDocsPlugin } from '../plugins/types'\nimport { mdComponents } from './mdComponents'\n\ninterface DocsTriggerProps {\n href?: string\n open?: boolean\n onToggle?: () => void\n}\n\nconst triggerClass = ( active: boolean ) => cn(\n 'flex items-center gap-1.5 rounded-md border px-2.5 py-1 text-xs font-medium transition-colors',\n active\n ? 'border-primary/50 bg-primary/10 text-primary'\n : 'border-border bg-card text-muted-foreground hover:border-primary/30 hover:text-foreground'\n)\n\nconst TriggerIcon = () => (\n <span className=\"flex h-3.5 w-3.5 items-center justify-center rounded-full border border-current text-[9px] font-bold leading-none\">\n i\n </span>\n)\n\nexport function DocsTrigger( { href, open = false, onToggle }: DocsTriggerProps ) {\n if ( href != null ) {\n return (\n <div>\n <a href={href} target=\"_blank\" rel=\"noopener noreferrer\" className={triggerClass( false )}>\n <TriggerIcon />\n Docs\n </a>\n </div>\n )\n }\n return (\n <div>\n <button onClick={onToggle} className={triggerClass( open )}>\n <TriggerIcon />\n Docs\n </button>\n </div>\n )\n}\n\ninterface DocsSidePanelProps {\n pageDocs: PageDocsPlugin\n tabMarkdown: string | null\n onClose: () => void\n}\n\nexport function DocsSidePanel( { pageDocs, tabMarkdown, onClose }: DocsSidePanelProps ) {\n const title = pageDocs.path.replace( /^\\//, '' ) || 'docs'\n const Component = pageDocs.component\n\n return (\n <aside className=\"absolute right-0 top-0 bottom-0 z-20 w-[26rem] border-l border-border bg-card flex flex-col overflow-hidden shadow-xl\">\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-border\">\n <span className=\"text-sm font-semibold text-foreground\">{title}</span>\n <button\n onClick={onClose}\n className=\"text-xs text-muted-foreground hover:text-foreground transition-colors\"\n aria-label=\"Close docs panel\"\n >\n ✕\n </button>\n </div>\n\n <div className=\"flex-1 overflow-y-auto px-4 py-4\">\n {tabMarkdown != null && (\n <>\n <ReactMarkdown components={mdComponents}>{tabMarkdown}</ReactMarkdown>\n <hr className=\"border-border my-3\" />\n </>\n )}\n {Component != null && <Component />}\n </div>\n </aside>\n )\n}\n","import { isValidElement, createElement, useState, useEffect, type ReactNode } from 'react'\nimport { Route, Switch, useLocation } from 'wouter'\n\nimport { getPageDocs, getPages } from '../plugins/registry'\nimport { PageDocsProvider, useActiveTabDocs } from '../docs/PageDocsContext'\nimport { DocsTrigger, DocsSidePanel } from '../docs/DocsPanel'\nimport type { PagePlugin } from '../plugins/types'\n\nfunction renderPageElement( plugin: PagePlugin ): ReactNode {\n const { element } = plugin\n if ( isValidElement( element ) ) { return element }\n if ( typeof element === 'function' ) {\n return createElement( element as React.ComponentType )\n }\n return element as ReactNode\n}\n\nexport interface ShellProps {\n fallback?: ReactNode\n children?: ReactNode\n}\n\nexport function Shell( { fallback, children }: ShellProps ) {\n return (\n <PageDocsProvider>\n <ShellContent fallback={fallback}>{children}</ShellContent>\n </PageDocsProvider>\n )\n}\n\nfunction ShellContent( { fallback, children }: ShellProps ) {\n const pages = getPages()\n const [ open, setOpen ] = useState( false )\n const [ location ] = useLocation()\n const pageDocs = getPageDocs( location )\n\n useEffect( () => { setOpen( false ) }, [ location ] )\n const tabMarkdown = useActiveTabDocs()\n\n return (\n <div className=\"relative flex flex-1 overflow-hidden\">\n <main className=\"relative flex-1 overflow-y-auto\">\n {pageDocs != null && (\n <div className=\"flex justify-end px-6 pt-4\">\n {pageDocs.href != null\n ? <DocsTrigger href={pageDocs.href} />\n : <DocsTrigger open={open} onToggle={() => setOpen( ( o ) => !o )} />}\n </div>\n )}\n <div className=\"px-6 pb-6 pt-4\">\n {children}\n <Switch>\n {pages.map( ( page ) => (\n <Route key={page.path} path={page.path}>\n {renderPageElement( page )}\n </Route>\n ) )}\n <Route>{fallback ?? <div className=\"p-8 text-muted-foreground\">Not found</div>}</Route>\n </Switch>\n </div>\n </main>\n {open && pageDocs != null && pageDocs.href == null && (\n <DocsSidePanel\n pageDocs={pageDocs}\n tabMarkdown={tabMarkdown}\n onClose={() => setOpen( false )}\n />\n )}\n </div>\n )\n}\n","import type { NavItemPlugin } from '../plugins/types'\n\nexport interface NavSection {\n label: string\n sectionSort: number\n items: NavItemPlugin[]\n}\n\nexport interface GroupedNav {\n ungrouped: NavItemPlugin[]\n sections: NavSection[]\n}\n\nexport function groupNavItems( items: NavItemPlugin[] ): GroupedNav {\n const ungrouped: NavItemPlugin[] = []\n const sectionMap = new Map<string, NavSection>()\n\n for ( const item of items ) {\n if ( !item.section ) {\n ungrouped.push( item )\n continue\n }\n if ( !sectionMap.has( item.section ) ) {\n sectionMap.set( item.section, {\n label : item.section,\n sectionSort : item.sectionSort ?? item.sort ?? 0,\n items : [],\n } )\n }\n sectionMap.get( item.section )!.items.push( item )\n }\n\n ungrouped.sort( ( a, b ) => ( a.sort ?? 0 ) - ( b.sort ?? 0 ) )\n\n const sections = Array.from( sectionMap.values() )\n for ( const s of sections ) {\n s.items.sort( ( a, b ) => ( a.sort ?? 0 ) - ( b.sort ?? 0 ) )\n }\n sections.sort( ( a, b ) => {\n const d = a.sectionSort - b.sectionSort\n return d !== 0 ? d : a.label.localeCompare( b.label )\n } )\n\n return { ungrouped, sections }\n}\n","import { useState, useEffect, useCallback } from 'react'\nimport { Link, useLocation } from 'wouter'\nimport { ChevronLeft, ChevronDown } from 'lucide-react'\nimport { cn } from '../lib/utils'\nimport { getNavItems, getTopBarItems } from '../plugins/registry'\nimport { groupNavItems } from './groupNavItems'\nimport type { ComponentType } from 'react'\n\n/**\n * Accepted icon forms (anywhere we render an inline icon):\n * - React component: `Settings` from lucide-react\n * - URL string: `/logo.png`, `https://...`, `data:image/...`, `blob:...`\n * - CSS class string: `fa-solid fa-gear`, `material-icons` (rendered on a <span>)\n */\nexport type IconRef = ComponentType<{ className?: string }> | string\n\nconst STORAGE_COLLAPSED = 'imaginarium.ui.sidebar.collapsed'\nconst STORAGE_SECTIONS = 'imaginarium.ui.sidebar.sections'\n\nfunction readBool( key: string, fallback: boolean ): boolean {\n try {\n const v = localStorage.getItem( key )\n return v === null ? fallback : v === 'true'\n } catch { return fallback }\n}\n\nfunction readSections(): Set<string> {\n try {\n const v = localStorage.getItem( STORAGE_SECTIONS )\n if ( !v ) { return new Set() }\n const parsed = JSON.parse( v )\n return new Set( Array.isArray( parsed ) ? parsed as string[] : [] )\n } catch { return new Set() }\n}\n\nconst URL_RE = /^(https?:|data:|blob:|\\/|\\.\\/|\\.\\.\\/)/\n\nfunction renderIcon( icon: IconRef | undefined, className: string ) {\n if ( !icon ) { return null }\n if ( typeof icon === 'string' ) {\n if ( URL_RE.test( icon ) ) { return <img src={icon} alt=\"\" className={className} /> }\n return <span className={`${icon} ${className}`} aria-hidden=\"true\" />\n }\n const Icon = icon\n return <Icon className={className} />\n}\n\nexport interface AppSidebarProps {\n title?: string\n titleIcon?: IconRef\n rightSlot?: React.ReactNode\n}\n\nexport function AppSidebar( { title = 'Imaginarium', titleIcon, rightSlot }: AppSidebarProps ) {\n const [ location ] = useLocation()\n const [ collapsed, setCollapsed ] = useState( () => readBool( STORAGE_COLLAPSED, false ) )\n const [ collapsedSections, setCollapsedSections ] = useState<Set<string>>( readSections )\n\n useEffect( () => {\n try { localStorage.setItem( STORAGE_COLLAPSED, String( collapsed ) ) } catch { /* ignore */ }\n }, [ collapsed ] )\n\n useEffect( () => {\n try {\n localStorage.setItem( STORAGE_SECTIONS, JSON.stringify( Array.from( collapsedSections ) ) )\n } catch { /* ignore */ }\n }, [ collapsedSections ] )\n\n const toggleSidebar = useCallback( () => setCollapsed( v => !v ), [] )\n\n const toggleSection = useCallback( ( label: string ) => {\n setCollapsedSections( prev => {\n const next = new Set( prev )\n next.has( label ) ? next.delete( label ) : next.add( label )\n return next\n } )\n }, [] )\n\n const { ungrouped, sections } = groupNavItems( getNavItems() )\n const topBarItems = getTopBarItems()\n\n return (\n <aside\n className={cn(\n 'flex flex-col flex-shrink-0 border-r bg-background transition-[width] duration-200 ease-in-out overflow-hidden',\n collapsed ? 'w-[52px]' : 'w-[220px]',\n )}\n >\n {/* Header */}\n <div className=\"flex h-[52px] flex-shrink-0 items-center border-b px-2.5 gap-2\">\n {!collapsed && renderIcon( titleIcon, 'h-6 w-6' )}\n {!collapsed && (\n <span className=\"flex-1 truncate text-sm font-semibold\">{title}</span>\n )}\n <button\n onClick={toggleSidebar}\n aria-label={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}\n className={cn(\n 'flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-md border text-muted-foreground',\n 'hover:bg-accent hover:text-accent-foreground transition-colors',\n collapsed && 'mx-auto border-transparent',\n )}\n >\n <ChevronLeft\n className={cn( 'h-4 w-4 transition-transform duration-200', collapsed && 'rotate-180' )}\n />\n </button>\n </div>\n\n {/* Nav */}\n <nav className=\"flex flex-1 flex-col gap-0.5 overflow-y-auto overflow-x-hidden p-1.5\">\n {/* Ungrouped items */}\n {ungrouped.map( ( { path, label, icon: Icon } ) => {\n const isActive = location === path || location.startsWith( `${path}/` )\n return (\n <Link\n key={path}\n href={path}\n title={collapsed ? label : undefined}\n className={cn(\n 'relative flex items-center gap-2.5 rounded-md px-2 py-1.5 text-sm text-muted-foreground',\n 'hover:bg-accent hover:text-accent-foreground transition-colors whitespace-nowrap',\n isActive && 'bg-accent/50 text-accent-foreground font-medium',\n collapsed && 'justify-center px-2',\n )}\n >\n {Icon && <Icon className=\"h-4 w-4 flex-shrink-0\" />}\n {!collapsed && <span>{label}</span>}\n </Link>\n )\n } )}\n\n {/* Sections */}\n {sections.map( ( section, index ) => {\n const isSectionCollapsed = !collapsed && collapsedSections.has( section.label )\n // The divider separates a section from what's above it. Skip it for the\n // first section when nothing precedes it (no ungrouped items) so it\n // doesn't stack under the header's border-b and read as a double line.\n const showDivider = index > 0 || ungrouped.length > 0\n return (\n <div key={section.label} className=\"flex flex-col\">\n {/* Section divider + header */}\n {showDivider && <div className=\"my-1.5 h-px bg-border\" />}\n {!collapsed && (\n <button\n onClick={() => toggleSection( section.label )}\n className={cn(\n 'flex items-center justify-between px-2 pb-1 pt-2.5',\n 'text-[10px] font-semibold uppercase tracking-widest text-muted-foreground',\n 'hover:text-foreground transition-colors cursor-pointer rounded-sm',\n )}\n >\n {section.label}\n <ChevronDown\n className={cn(\n 'h-3 w-3 transition-transform duration-200',\n isSectionCollapsed && '-rotate-90',\n )}\n />\n </button>\n )}\n\n {/* Section items */}\n <div\n className={cn(\n 'flex flex-col gap-0.5 overflow-hidden transition-all duration-200',\n isSectionCollapsed ? 'max-h-0 opacity-0' : 'max-h-screen opacity-100',\n )}\n >\n {section.items.map( ( { path, label, icon: Icon } ) => {\n const isActive = location === path || location.startsWith( `${path}/` )\n return (\n <Link\n key={path}\n href={path}\n title={collapsed ? label : undefined}\n className={cn(\n 'relative flex items-center gap-2.5 rounded-md px-2 py-1.5 text-sm text-muted-foreground',\n 'hover:bg-accent hover:text-accent-foreground transition-colors whitespace-nowrap',\n isActive && 'bg-accent/50 text-accent-foreground font-medium',\n collapsed && 'justify-center px-2',\n )}\n >\n {Icon && <Icon className=\"h-4 w-4 flex-shrink-0\" />}\n {!collapsed && <span>{label}</span>}\n </Link>\n )\n } )}\n </div>\n </div>\n )\n } )}\n </nav>\n\n {/* Footer: rightSlot + TopBarItems */}\n <div className={cn(\n 'flex flex-shrink-0 items-center border-t p-1.5',\n collapsed ? 'flex-col gap-1' : 'flex-row justify-end gap-0.5',\n )}>\n {!collapsed && rightSlot}\n {topBarItems.map( ( item ) => {\n const C = item.component\n return <C key={item.id} />\n } )}\n </div>\n </aside>\n )\n}\n","import * as React from 'react'\nimport * as ToastPrimitives from '@radix-ui/react-toast'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { X } from 'lucide-react'\n\nimport { cn } from '../../lib/utils'\n\nconst ToastProvider = ToastPrimitives.Provider\n\nconst ToastViewport = React.forwardRef<\n React.ElementRef<typeof ToastPrimitives.Viewport>,\n React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport>\n>( ( { className, ...props }, ref ) => (\n <ToastPrimitives.Viewport\n ref={ref}\n className={cn(\n 'fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]',\n className,\n )}\n {...props}\n />\n) )\nToastViewport.displayName = ToastPrimitives.Viewport.displayName\n\nconst toastVariants = cva(\n 'group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full',\n {\n variants: {\n variant: {\n default: 'border bg-background text-foreground',\n destructive: 'destructive group border-destructive bg-destructive text-destructive-foreground',\n },\n },\n defaultVariants: { variant: 'default' },\n },\n)\n\nconst Toast = React.forwardRef<\n React.ElementRef<typeof ToastPrimitives.Root>,\n React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> & VariantProps<typeof toastVariants>\n>( ( { className, variant, ...props }, ref ) => (\n <ToastPrimitives.Root ref={ref} className={cn( toastVariants( { variant } ), className )} {...props} />\n) )\nToast.displayName = ToastPrimitives.Root.displayName\n\nconst ToastAction = React.forwardRef<\n React.ElementRef<typeof ToastPrimitives.Action>,\n React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>\n>( ( { className, ...props }, ref ) => (\n <ToastPrimitives.Action\n ref={ref}\n className={cn(\n 'inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',\n className,\n )}\n {...props}\n />\n) )\nToastAction.displayName = ToastPrimitives.Action.displayName\n\nconst ToastClose = React.forwardRef<\n React.ElementRef<typeof ToastPrimitives.Close>,\n React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>\n>( ( { className, ...props }, ref ) => (\n <ToastPrimitives.Close\n ref={ref}\n className={cn(\n 'absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100',\n className,\n )}\n toast-close=\"\"\n {...props}\n >\n <X className=\"h-4 w-4\" />\n </ToastPrimitives.Close>\n) )\nToastClose.displayName = ToastPrimitives.Close.displayName\n\nconst ToastTitle = React.forwardRef<\n React.ElementRef<typeof ToastPrimitives.Title>,\n React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>\n>( ( { className, ...props }, ref ) => (\n <ToastPrimitives.Title ref={ref} className={cn( 'text-sm font-semibold', className )} {...props} />\n) )\nToastTitle.displayName = ToastPrimitives.Title.displayName\n\nconst ToastDescription = React.forwardRef<\n React.ElementRef<typeof ToastPrimitives.Description>,\n React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>\n>( ( { className, ...props }, ref ) => (\n <ToastPrimitives.Description ref={ref} className={cn( 'text-sm opacity-90', className )} {...props} />\n) )\nToastDescription.displayName = ToastPrimitives.Description.displayName\n\nexport type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>\nexport type ToastActionElement = React.ReactElement<typeof ToastAction>\n\nexport {\n ToastProvider,\n ToastViewport,\n Toast,\n ToastTitle,\n ToastDescription,\n ToastClose,\n ToastAction,\n}\n","import { useToast } from '../../hooks/useToast'\nimport {\n Toast,\n ToastClose,\n ToastDescription,\n ToastProvider,\n ToastTitle,\n ToastViewport,\n} from './Toast'\n\nexport function Toaster() {\n const { toasts } = useToast()\n\n return (\n <ToastProvider>\n {toasts.map( ( { id, title, description, action, ...props } ) => (\n <Toast key={id} {...props}>\n <div className=\"grid gap-1\">\n {title && <ToastTitle>{title}</ToastTitle>}\n {description && <ToastDescription>{description}</ToastDescription>}\n </div>\n {action}\n <ToastClose />\n </Toast>\n ) )}\n <ToastViewport />\n </ToastProvider>\n )\n}\n","import { Button } from '../components/ui/Button'\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from '../components/ui/Card'\n\nexport interface LoginPageProps {\n loginPath: string\n title?: string\n subtitle?: string\n buttonLabel?: string\n /** URL of an image to show behind the sign-in card. Empty/null skips it. */\n backgroundUrl?: string\n /** Optional message shown above the button (e.g. an error from a failed prior attempt). */\n errorMessage?: string\n}\n\nfunction GoogleGlyph( { className }: { className?: string } ) {\n return (\n <svg viewBox=\"0 0 24 24\" className={className} aria-hidden=\"true\">\n <path fill=\"#4285F4\" d=\"M23.49 12.27c0-.79-.07-1.54-.19-2.27H12v4.51h6.16c-.27 1.4-1.04 2.59-2.21 3.41v2.77h3.59c2.08-1.92 3.95-4.74 3.95-8.42z\" />\n <path fill=\"#34A853\" d=\"M12 24c2.97 0 5.46-.98 7.28-2.66l-3.59-2.77c-.98.66-2.23 1.06-3.69 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 21.53 7.7 24 12 24z\" />\n <path fill=\"#FBBC05\" d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\" />\n <path fill=\"#EA4335\" d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\" />\n </svg>\n )\n}\n\nconst ERROR_MESSAGES: Record<string, string> = {\n auth_failed : 'Sign-in failed. Please try again.',\n}\n\nfunction readUrlError(): string | undefined {\n if ( typeof window === 'undefined' ) { \n return undefined \n }\n const code = new URLSearchParams( window.location.search ).get( 'error' )\n if ( !code ) { \n return undefined \n }\n return ERROR_MESSAGES[code] ?? `Sign-in error: ${code}`\n}\n\nexport function LoginPage( {\n loginPath,\n title = 'Sign in',\n subtitle,\n buttonLabel = 'Sign in with Google',\n backgroundUrl,\n errorMessage,\n}: LoginPageProps ) {\n const message = errorMessage ?? readUrlError()\n const hasBackground = Boolean( backgroundUrl )\n\n return (\n <div\n className=\"min-h-screen flex items-center justify-center bg-background bg-cover bg-center px-4\"\n style={hasBackground ? { backgroundImage: `url(${backgroundUrl})` } : undefined}\n >\n <Card className={`w-full max-w-md ${hasBackground ? 'backdrop-blur-sm bg-card/90' : ''}`}>\n <CardHeader className=\"text-center\">\n <CardTitle>{title}</CardTitle>\n {subtitle && <CardDescription>{subtitle}</CardDescription>}\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {message && (\n <div className=\"rounded-md border border-destructive bg-destructive/10 px-4 py-2 text-sm text-destructive\">\n {message}\n </div>\n )}\n <Button\n className=\"w-full\"\n variant=\"outline\"\n onClick={() => { window.location.href = loginPath }}\n >\n <GoogleGlyph className=\"h-5 w-5 mr-2\" />\n {buttonLabel}\n </Button>\n </CardContent>\n </Card>\n </div>\n )\n}\n\nexport default LoginPage\n","import { createElement, type ComponentType, type ReactNode } from 'react'\nimport { useQuery } from '@tanstack/react-query'\nimport { Config } from '@leverege/plugin'\n\nimport { useImaginariumApi } from '../api/ImaginariumApiContext'\nimport { LoginPage, type LoginPageProps } from './LoginPage'\n\nexport interface RequireAuthProps {\n children: ReactNode\n}\n\n/**\n * Wraps `children` with an authentication gate. On mount, fetches\n * `Config.get('ImaginariumApp', 'userPath', '/auth/user')` from the configured\n * API base URL. While loading, renders a small placeholder. On error, renders\n * the configured login component (defaults to the bundled `LoginPage`). On\n * success, renders `children`.\n *\n * Recognized config keys (under `'ImaginariumApp'`):\n * - `userPath` endpoint to check (default `/auth/user`)\n * - `loginPath` URL the login button navigates to (default `/api/login`)\n * - `loginPage` component to render when unauthenticated\n * - `loginTitle` default page heading\n * - `loginSubtitle` default page subtitle\n * - `loginButtonLabel` default button label\n * - `loginBackgroundUrl` URL of an image to show behind the sign-in card\n */\nexport function RequireAuth( { children }: RequireAuthProps ) {\n const { fetchJson } = useImaginariumApi()\n const userPath = Config.get<string>( 'ImaginariumApp', 'userPath', '/auth/user' )\n\n const { isPending, isError } = useQuery( {\n queryKey: [ 'imaginarium', 'auth', 'user', userPath ],\n queryFn: () => fetchJson( userPath ),\n retry: false,\n refetchOnWindowFocus: false,\n } )\n\n if ( isPending ) {\n return <div className=\"p-8 text-muted-foreground\">Checking sign-in…</div>\n }\n\n if ( isError ) {\n const LoginComponent = Config.get<ComponentType<LoginPageProps>>(\n 'ImaginariumApp', 'loginPage', LoginPage,\n )\n const title = Config.get<string | undefined>( 'ImaginariumApp', 'loginTitle', undefined )\n const subtitle = Config.get<string | undefined>( 'ImaginariumApp', 'loginSubtitle', undefined )\n const buttonLabel = Config.get<string | undefined>(\n 'ImaginariumApp', 'loginButtonLabel', undefined,\n )\n const loginPath = Config.get<string>( 'ImaginariumApp', 'loginPath', '/api/login' )\n const backgroundUrl = Config.get<string | undefined>(\n 'ImaginariumApp', 'loginBackgroundUrl', undefined,\n )\n\n const appTitle = Config.get<string>( 'ImaginariumApp', 'title', 'Imaginarium' )\n const resolvedTitle = title ?? `Sign in to ${appTitle}`\n\n return createElement( LoginComponent, {\n loginPath,\n title: resolvedTitle,\n subtitle,\n buttonLabel,\n backgroundUrl,\n } )\n }\n\n return <>{children}</>\n}\n\nexport default RequireAuth\n","import { ActiveTheme } from '../ui-elements'\n\n// ui-elements components read `theme.props`/`theme.classes` off the Theme\n// context and THROW if it is null. `ActiveTheme` provides those methods,\n// delegating to this fallback for any component an appearance doesn't define so\n// components render (unstyled) instead of crashing.\nconst FALLBACK_THEME = {\n props : ( _component : string, variant : unknown, userProps : unknown ) => {\n if ( variant && typeof variant === 'object' ) { return variant }\n return ( userProps && typeof userProps === 'object' ) ? userProps : {}\n },\n classes : ( ...args : unknown[] ) => args.filter( ( a ) => typeof a === 'string' && a ).join( ' ' ),\n subclasses : ( ...args : unknown[] ) => args.filter( ( a ) => typeof a === 'string' && a ).join( ' ' ),\n resources : () => undefined,\n}\n\ntype SharedTheme = { sync? : { start? : ( o : { appearanceId? : string } ) => void } }\n\n// ONE ActiveTheme for the whole document: its constructor calls\n// firebase.initializeApp(…, 'UIActiveTheme'), which throws if run twice, and the\n// appearance CSS it injects is global (`:root` vars + a <head> stylesheet). So\n// there is a single active appearance at any moment. Stashed on globalThis so\n// HMR re-evaluating this module doesn't construct a second instance.\nexport function getSharedTheme() : SharedTheme {\n const g = globalThis as { __imgmActiveTheme? : SharedTheme }\n if ( !g.__imgmActiveTheme ) {\n g.__imgmActiveTheme = new ActiveTheme( { altTheme : FALLBACK_THEME, addWindowCommands : false } ) as SharedTheme\n }\n return g.__imgmActiveTheme\n}\n\n// Point the shared theme at an appearance id (empty -> the built-in fallback).\nexport function pointAppearance( appearanceId : string ) {\n getSharedTheme().sync?.start?.( { appearanceId : appearanceId || undefined } )\n}\n\n// Default appearance shipped with the library so prototypes are themed out of\n// the box in any consuming app, even with no Config or pasted id. Overridden, in\n// order, by a pasted gallery id, then `Config('Prototypes','baseAppearanceId')`,\n// then the app-wide appearance. Without this, the bare fallback applies no\n// variant styling and everything renders unstyled.\nexport const DEFAULT_APPEARANCE_ID = '39oo5B3KISUzzfa1gT1Va1'\n\n// The app-wide baseline appearance. The app root sets it; prototype previews\n// override the shared theme transiently and restore to this when they unmount.\nlet appAppearanceId = ''\nexport function getAppAppearanceId() : string { return appAppearanceId }\nexport function setAppAppearanceId( id : string ) {\n appAppearanceId = id || ''\n pointAppearance( appAppearanceId )\n}\n","import { useEffect, useMemo, type ReactNode } from 'react'\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\nimport { Config } from '@leverege/plugin'\n\nimport { TooltipProvider } from '../components/ui/Tooltip'\nimport { Toaster } from '../components/ui/Toaster'\nimport { ImaginariumApiProvider } from '../api/ImaginariumApiContext'\nimport { RequireAuth } from '../auth/RequireAuth'\nimport { getProviders } from '../plugins/registry'\nimport { Theme } from '../ui-elements'\nimport { getSharedTheme, setAppAppearanceId } from '../theme/activeAppearance'\nimport { AppSidebar, type AppSidebarProps, type IconRef } from './AppSidebar'\nimport { Shell, type ShellProps } from './Shell'\n\n// Applies the app-wide ui-elements appearance theme. Opt-in: when no\n// `ImaginariumApp.appearanceId` is configured, it leaves the tree untouched (no\n// ActiveTheme/Firebase init). When set, it loads that appearance as the global\n// baseline so ui-elements components across the app are themed; prototype\n// previews override it transiently and restore it on exit. The Tailwind shell\n// chrome only changes if that appearance defines the shell's CSS tokens.\nfunction AppThemeBoundary( { children } : { children : ReactNode } ) {\n const appearanceId = Config.get<string>( 'ImaginariumApp', 'appearanceId', '' )\n useEffect( () => { setAppAppearanceId( appearanceId ) }, [ appearanceId ] )\n if ( !appearanceId ) { return <>{children}</> }\n return <Theme theme={getSharedTheme() as never}>{children}</Theme>\n}\n\nfunction withProviders( tree: ReactNode ): ReactNode {\n const providers = getProviders()\n let wrapped = tree\n for ( const { component: Provider } of providers ) {\n wrapped = <Provider>{wrapped}</Provider>\n }\n return wrapped\n}\n\nexport interface ImaginariumAppProps {\n apiBaseUrl?: string\n queryClient?: QueryClient\n title?: string\n titleIcon?: IconRef\n navRightSlot?: AppSidebarProps['rightSlot']\n shellFallback?: ShellProps['fallback']\n children?: ReactNode\n}\n\nconst defaultQueryClient = new QueryClient( {\n defaultOptions: {\n queries: { retry: false, refetchOnWindowFocus: false },\n },\n} )\n\nfunction GatedShell( { title, titleIcon, navRightSlot, shellFallback, children }: {\n title?: string\n titleIcon?: IconRef\n navRightSlot?: AppSidebarProps['rightSlot']\n shellFallback?: ShellProps['fallback']\n children?: ReactNode\n} ) {\n return withProviders(\n <div className=\"flex h-screen overflow-hidden bg-background text-foreground\">\n <AppSidebar title={title} titleIcon={titleIcon} rightSlot={navRightSlot} />\n <Shell fallback={shellFallback}>{children}</Shell>\n </div>,\n )\n}\n\nexport function ImaginariumApp( {\n apiBaseUrl = '/api',\n queryClient,\n title,\n titleIcon,\n navRightSlot,\n shellFallback,\n children,\n}: ImaginariumAppProps ) {\n const qc = useMemo( () => queryClient ?? defaultQueryClient, [ queryClient ] )\n const requireAuth = Config.get<boolean>( 'ImaginariumApp', 'requireAuth', true )\n const resolvedTitleIcon = titleIcon\n ?? Config.get<IconRef | undefined>( 'ImaginariumApp', 'titleIcon', undefined )\n\n const gated = (\n <GatedShell\n title={title}\n titleIcon={resolvedTitleIcon}\n navRightSlot={navRightSlot}\n shellFallback={shellFallback}\n >\n {children}\n </GatedShell>\n )\n\n return (\n <AppThemeBoundary>\n <QueryClientProvider client={qc}>\n <TooltipProvider>\n <ImaginariumApiProvider apiBaseUrl={apiBaseUrl}>\n {requireAuth ? <RequireAuth>{gated}</RequireAuth> : gated}\n <Toaster />\n </ImaginariumApiProvider>\n </TooltipProvider>\n </QueryClientProvider>\n </AppThemeBoundary>\n )\n}\n"],"names":["PageDocsContext","createContext","PageDocsProvider","children","tabMarkdown","setTabMarkdown","useState","jsx","useRegisterTabDocs","markdown","useContext","useEffect","useActiveTabDocs","triggerClass","active","cn","TriggerIcon","DocsTrigger","href","open","onToggle","jsxs","DocsSidePanel","pageDocs","onClose","title","Component","Fragment","ReactMarkdown","mdComponents","renderPageElement","plugin","element","isValidElement","createElement","Shell","fallback","ShellContent","pages","getPages","setOpen","location","useLocation","getPageDocs","o","Switch","page","Route","groupNavItems","items","ungrouped","sectionMap","item","a","b","sections","d","STORAGE_COLLAPSED","STORAGE_SECTIONS","readBool","key","v","readSections","parsed","URL_RE","renderIcon","icon","className","Icon","AppSidebar","titleIcon","rightSlot","collapsed","setCollapsed","collapsedSections","setCollapsedSections","toggleSidebar","useCallback","toggleSection","label","prev","next","getNavItems","topBarItems","getTopBarItems","ChevronLeft","path","isActive","Link","section","index","isSectionCollapsed","showDivider","ChevronDown","C","ToastProvider","ToastPrimitives","ToastViewport","React","props","ref","toastVariants","cva","Toast","variant","ToastAction","ToastClose","X","ToastTitle","ToastDescription","Toaster","toasts","useToast","id","description","action","GoogleGlyph","ERROR_MESSAGES","readUrlError","code","LoginPage","loginPath","subtitle","buttonLabel","backgroundUrl","errorMessage","message","hasBackground","Card","CardHeader","CardTitle","CardDescription","CardContent","Button","RequireAuth","fetchJson","useImaginariumApi","userPath","Config","isPending","isError","useQuery","LoginComponent","appTitle","resolvedTitle","FALLBACK_THEME","_component","userProps","args","getSharedTheme","g","ActiveTheme","pointAppearance","appearanceId","_b","_a","DEFAULT_APPEARANCE_ID","appAppearanceId","getAppAppearanceId","setAppAppearanceId","AppThemeBoundary","Theme","withProviders","tree","providers","getProviders","wrapped","Provider","defaultQueryClient","QueryClient","GatedShell","navRightSlot","shellFallback","ImaginariumApp","apiBaseUrl","queryClient","qc","useMemo","requireAuth","resolvedTitleIcon","gated","QueryClientProvider","TooltipProvider","ImaginariumApiProvider"],"mappings":"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"}
1
+ {"version":3,"file":"ImaginariumApp-DUtoZlIK.cjs","sources":["../src/docs/PageDocsContext.tsx","../src/docs/DocsPanel.tsx","../src/shell/Shell.tsx","../src/shell/groupNavItems.ts","../src/shell/AppSidebar.tsx","../src/components/ui/Toast.tsx","../src/components/ui/Toaster.tsx","../src/auth/LoginPage.tsx","../src/auth/RequireAuth.tsx","../src/theme/activeAppearance.ts","../src/shell/ImaginariumApp.tsx"],"sourcesContent":["import { createContext, useContext, useEffect, useState, type ReactNode } from 'react'\n\ninterface PageDocsContextValue {\n tabMarkdown: string | null\n setTabMarkdown: ( markdown: string | null ) => void\n}\n\nconst PageDocsContext = createContext<PageDocsContextValue>( {\n tabMarkdown: null,\n setTabMarkdown: () => {},\n} )\n\nexport function PageDocsProvider( { children }: { children: ReactNode } ) {\n const [ tabMarkdown, setTabMarkdown ] = useState<string | null>( null )\n return (\n <PageDocsContext.Provider value={{ tabMarkdown, setTabMarkdown }}>\n {children}\n </PageDocsContext.Provider>\n )\n}\n\n/**\n * Call inside a page component to register tab-specific docs.\n * When the component unmounts or markdown changes, the panel falls back\n * to the page-level docs registered via addPageDocs().\n */\nexport function useRegisterTabDocs( markdown: string ) {\n const { setTabMarkdown } = useContext( PageDocsContext )\n useEffect( () => {\n setTabMarkdown( markdown )\n return () => { setTabMarkdown( null ) }\n }, [ markdown, setTabMarkdown ] )\n}\n\nexport function useActiveTabDocs(): string | null {\n return useContext( PageDocsContext ).tabMarkdown\n}\n","import ReactMarkdown from 'react-markdown'\nimport { cn } from '../lib/utils'\nimport type { PageDocsPlugin } from '../plugins/types'\nimport { mdComponents } from './mdComponents'\n\ninterface DocsTriggerProps {\n href?: string\n open?: boolean\n onToggle?: () => void\n}\n\nconst triggerClass = ( active: boolean ) => cn(\n 'flex items-center gap-1.5 rounded-md border px-2.5 py-1 text-xs font-medium transition-colors',\n active\n ? 'border-primary/50 bg-primary/10 text-primary'\n : 'border-border bg-card text-muted-foreground hover:border-primary/30 hover:text-foreground'\n)\n\nconst TriggerIcon = () => (\n <span className=\"flex h-3.5 w-3.5 items-center justify-center rounded-full border border-current text-[9px] font-bold leading-none\">\n i\n </span>\n)\n\nexport function DocsTrigger( { href, open = false, onToggle }: DocsTriggerProps ) {\n if ( href != null ) {\n return (\n <div>\n <a href={href} target=\"_blank\" rel=\"noopener noreferrer\" className={triggerClass( false )}>\n <TriggerIcon />\n Docs\n </a>\n </div>\n )\n }\n return (\n <div>\n <button onClick={onToggle} className={triggerClass( open )}>\n <TriggerIcon />\n Docs\n </button>\n </div>\n )\n}\n\ninterface DocsSidePanelProps {\n pageDocs: PageDocsPlugin\n tabMarkdown: string | null\n onClose: () => void\n}\n\nexport function DocsSidePanel( { pageDocs, tabMarkdown, onClose }: DocsSidePanelProps ) {\n const title = pageDocs.path.replace( /^\\//, '' ) || 'docs'\n const Component = pageDocs.component\n\n return (\n <aside className=\"absolute right-0 top-0 bottom-0 z-20 w-[26rem] border-l border-border bg-card flex flex-col overflow-hidden shadow-xl\">\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-border\">\n <span className=\"text-sm font-semibold text-foreground\">{title}</span>\n <button\n onClick={onClose}\n className=\"text-xs text-muted-foreground hover:text-foreground transition-colors\"\n aria-label=\"Close docs panel\"\n >\n ✕\n </button>\n </div>\n\n <div className=\"flex-1 overflow-y-auto px-4 py-4\">\n {tabMarkdown != null && (\n <>\n <ReactMarkdown components={mdComponents}>{tabMarkdown}</ReactMarkdown>\n <hr className=\"border-border my-3\" />\n </>\n )}\n {Component != null && <Component />}\n </div>\n </aside>\n )\n}\n","import { isValidElement, createElement, useState, useEffect, type ReactNode } from 'react'\nimport { Route, Switch, useLocation } from 'wouter'\n\nimport { getPageDocs, getPages } from '../plugins/registry'\nimport { PageDocsProvider, useActiveTabDocs } from '../docs/PageDocsContext'\nimport { DocsTrigger, DocsSidePanel } from '../docs/DocsPanel'\nimport type { PagePlugin } from '../plugins/types'\n\nfunction renderPageElement( plugin: PagePlugin ): ReactNode {\n const { element } = plugin\n if ( isValidElement( element ) ) { return element }\n if ( typeof element === 'function' ) {\n return createElement( element as React.ComponentType )\n }\n return element as ReactNode\n}\n\nexport interface ShellProps {\n fallback?: ReactNode\n children?: ReactNode\n}\n\nexport function Shell( { fallback, children }: ShellProps ) {\n return (\n <PageDocsProvider>\n <ShellContent fallback={fallback}>{children}</ShellContent>\n </PageDocsProvider>\n )\n}\n\nfunction ShellContent( { fallback, children }: ShellProps ) {\n const pages = getPages()\n const [ open, setOpen ] = useState( false )\n const [ location ] = useLocation()\n const pageDocs = getPageDocs( location )\n\n useEffect( () => { setOpen( false ) }, [ location ] )\n const tabMarkdown = useActiveTabDocs()\n\n return (\n <div className=\"relative flex flex-1 overflow-hidden\">\n <main className=\"relative flex-1 overflow-y-auto\">\n {pageDocs != null && (\n <div className=\"flex justify-end px-6 pt-4\">\n {pageDocs.href != null\n ? <DocsTrigger href={pageDocs.href} />\n : <DocsTrigger open={open} onToggle={() => setOpen( ( o ) => !o )} />}\n </div>\n )}\n <div className=\"px-6 pb-6 pt-4\">\n {children}\n <Switch>\n {pages.map( ( page ) => (\n <Route key={page.path} path={page.path}>\n {renderPageElement( page )}\n </Route>\n ) )}\n <Route>{fallback ?? <div className=\"p-8 text-muted-foreground\">Not found</div>}</Route>\n </Switch>\n </div>\n </main>\n {open && pageDocs != null && pageDocs.href == null && (\n <DocsSidePanel\n pageDocs={pageDocs}\n tabMarkdown={tabMarkdown}\n onClose={() => setOpen( false )}\n />\n )}\n </div>\n )\n}\n","import type { NavItemPlugin } from '../plugins/types'\n\nexport interface NavSection {\n label: string\n sectionSort: number\n items: NavItemPlugin[]\n}\n\nexport interface GroupedNav {\n ungrouped: NavItemPlugin[]\n sections: NavSection[]\n}\n\nexport function groupNavItems( items: NavItemPlugin[] ): GroupedNav {\n const ungrouped: NavItemPlugin[] = []\n const sectionMap = new Map<string, NavSection>()\n\n for ( const item of items ) {\n if ( !item.section ) {\n ungrouped.push( item )\n continue\n }\n if ( !sectionMap.has( item.section ) ) {\n sectionMap.set( item.section, {\n label : item.section,\n sectionSort : item.sectionSort ?? item.sort ?? 0,\n items : [],\n } )\n }\n sectionMap.get( item.section )!.items.push( item )\n }\n\n ungrouped.sort( ( a, b ) => ( a.sort ?? 0 ) - ( b.sort ?? 0 ) )\n\n const sections = Array.from( sectionMap.values() )\n for ( const s of sections ) {\n s.items.sort( ( a, b ) => ( a.sort ?? 0 ) - ( b.sort ?? 0 ) )\n }\n sections.sort( ( a, b ) => {\n const d = a.sectionSort - b.sectionSort\n return d !== 0 ? d : a.label.localeCompare( b.label )\n } )\n\n return { ungrouped, sections }\n}\n","import { useState, useEffect, useCallback } from 'react'\nimport { Link, useLocation } from 'wouter'\nimport { ChevronLeft, ChevronDown } from 'lucide-react'\nimport { cn } from '../lib/utils'\nimport { getNavItems, getTopBarItems } from '../plugins/registry'\nimport { groupNavItems } from './groupNavItems'\nimport type { ComponentType } from 'react'\n\n/**\n * Accepted icon forms (anywhere we render an inline icon):\n * - React component: `Settings` from lucide-react\n * - URL string: `/logo.png`, `https://...`, `data:image/...`, `blob:...`\n * - CSS class string: `fa-solid fa-gear`, `material-icons` (rendered on a <span>)\n */\nexport type IconRef = ComponentType<{ className?: string }> | string\n\nconst STORAGE_COLLAPSED = 'imaginarium.ui.sidebar.collapsed'\nconst STORAGE_SECTIONS = 'imaginarium.ui.sidebar.sections'\n\nfunction readBool( key: string, fallback: boolean ): boolean {\n try {\n const v = localStorage.getItem( key )\n return v === null ? fallback : v === 'true'\n } catch { return fallback }\n}\n\nfunction readSections(): Set<string> {\n try {\n const v = localStorage.getItem( STORAGE_SECTIONS )\n if ( !v ) { return new Set() }\n const parsed = JSON.parse( v )\n return new Set( Array.isArray( parsed ) ? parsed as string[] : [] )\n } catch { return new Set() }\n}\n\nconst URL_RE = /^(https?:|data:|blob:|\\/|\\.\\/|\\.\\.\\/)/\n\nfunction renderIcon( icon: IconRef | undefined, className: string ) {\n if ( !icon ) { return null }\n if ( typeof icon === 'string' ) {\n if ( URL_RE.test( icon ) ) { return <img src={icon} alt=\"\" className={className} /> }\n return <span className={`${icon} ${className}`} aria-hidden=\"true\" />\n }\n const Icon = icon\n return <Icon className={className} />\n}\n\nexport interface AppSidebarProps {\n title?: string\n titleIcon?: IconRef\n rightSlot?: React.ReactNode\n}\n\nexport function AppSidebar( { title = 'Imaginarium', titleIcon, rightSlot }: AppSidebarProps ) {\n const [ location ] = useLocation()\n const [ collapsed, setCollapsed ] = useState( () => readBool( STORAGE_COLLAPSED, false ) )\n const [ collapsedSections, setCollapsedSections ] = useState<Set<string>>( readSections )\n\n useEffect( () => {\n try { localStorage.setItem( STORAGE_COLLAPSED, String( collapsed ) ) } catch { /* ignore */ }\n }, [ collapsed ] )\n\n useEffect( () => {\n try {\n localStorage.setItem( STORAGE_SECTIONS, JSON.stringify( Array.from( collapsedSections ) ) )\n } catch { /* ignore */ }\n }, [ collapsedSections ] )\n\n const toggleSidebar = useCallback( () => setCollapsed( v => !v ), [] )\n\n const toggleSection = useCallback( ( label: string ) => {\n setCollapsedSections( prev => {\n const next = new Set( prev )\n next.has( label ) ? next.delete( label ) : next.add( label )\n return next\n } )\n }, [] )\n\n const { ungrouped, sections } = groupNavItems( getNavItems() )\n const topBarItems = getTopBarItems()\n\n return (\n <aside\n className={cn(\n 'flex flex-col flex-shrink-0 border-r bg-background transition-[width] duration-200 ease-in-out overflow-hidden',\n collapsed ? 'w-[52px]' : 'w-[220px]',\n )}\n >\n {/* Header */}\n <div className=\"flex h-[52px] flex-shrink-0 items-center border-b px-2.5 gap-2\">\n {!collapsed && renderIcon( titleIcon, 'h-6 w-6' )}\n {!collapsed && (\n <span className=\"flex-1 truncate text-sm font-semibold\">{title}</span>\n )}\n <button\n onClick={toggleSidebar}\n aria-label={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}\n className={cn(\n 'flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-md border text-muted-foreground',\n 'hover:bg-accent hover:text-accent-foreground transition-colors',\n collapsed && 'mx-auto border-transparent',\n )}\n >\n <ChevronLeft\n className={cn( 'h-4 w-4 transition-transform duration-200', collapsed && 'rotate-180' )}\n />\n </button>\n </div>\n\n {/* Nav */}\n <nav className=\"flex flex-1 flex-col gap-0.5 overflow-y-auto overflow-x-hidden p-1.5\">\n {/* Ungrouped items */}\n {ungrouped.map( ( { path, label, icon: Icon } ) => {\n const isActive = location === path || location.startsWith( `${path}/` )\n return (\n <Link\n key={path}\n href={path}\n title={collapsed ? label : undefined}\n className={cn(\n 'relative flex items-center gap-2.5 rounded-md px-2 py-1.5 text-sm text-muted-foreground',\n 'hover:bg-accent hover:text-accent-foreground transition-colors whitespace-nowrap',\n isActive && 'bg-accent/50 text-accent-foreground font-medium',\n collapsed && 'justify-center px-2',\n )}\n >\n {Icon && <Icon className=\"h-4 w-4 flex-shrink-0\" />}\n {!collapsed && <span>{label}</span>}\n </Link>\n )\n } )}\n\n {/* Sections */}\n {sections.map( ( section, index ) => {\n const isSectionCollapsed = !collapsed && collapsedSections.has( section.label )\n // The divider separates a section from what's above it. Skip it for the\n // first section when nothing precedes it (no ungrouped items) so it\n // doesn't stack under the header's border-b and read as a double line.\n const showDivider = index > 0 || ungrouped.length > 0\n return (\n <div key={section.label} className=\"flex flex-col\">\n {/* Section divider + header */}\n {showDivider && <div className=\"my-1.5 h-px bg-border\" />}\n {!collapsed && (\n <button\n onClick={() => toggleSection( section.label )}\n className={cn(\n 'flex items-center justify-between px-2 pb-1 pt-2.5',\n 'text-[10px] font-semibold uppercase tracking-widest text-muted-foreground',\n 'hover:text-foreground transition-colors cursor-pointer rounded-sm',\n )}\n >\n {section.label}\n <ChevronDown\n className={cn(\n 'h-3 w-3 transition-transform duration-200',\n isSectionCollapsed && '-rotate-90',\n )}\n />\n </button>\n )}\n\n {/* Section items */}\n <div\n className={cn(\n 'flex flex-col gap-0.5 overflow-hidden transition-all duration-200',\n isSectionCollapsed ? 'max-h-0 opacity-0' : 'max-h-screen opacity-100',\n )}\n >\n {section.items.map( ( { path, label, icon: Icon } ) => {\n const isActive = location === path || location.startsWith( `${path}/` )\n return (\n <Link\n key={path}\n href={path}\n title={collapsed ? label : undefined}\n className={cn(\n 'relative flex items-center gap-2.5 rounded-md px-2 py-1.5 text-sm text-muted-foreground',\n 'hover:bg-accent hover:text-accent-foreground transition-colors whitespace-nowrap',\n isActive && 'bg-accent/50 text-accent-foreground font-medium',\n collapsed && 'justify-center px-2',\n )}\n >\n {Icon && <Icon className=\"h-4 w-4 flex-shrink-0\" />}\n {!collapsed && <span>{label}</span>}\n </Link>\n )\n } )}\n </div>\n </div>\n )\n } )}\n </nav>\n\n {/* Footer: rightSlot + TopBarItems */}\n <div className={cn(\n 'flex flex-shrink-0 items-center border-t p-1.5',\n collapsed ? 'flex-col gap-1' : 'flex-row justify-end gap-0.5',\n )}>\n {!collapsed && rightSlot}\n {topBarItems.map( ( item ) => {\n const C = item.component\n return <C key={item.id} />\n } )}\n </div>\n </aside>\n )\n}\n","import * as React from 'react'\nimport * as ToastPrimitives from '@radix-ui/react-toast'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { X } from 'lucide-react'\n\nimport { cn } from '../../lib/utils'\n\nconst ToastProvider = ToastPrimitives.Provider\n\nconst ToastViewport = React.forwardRef<\n React.ElementRef<typeof ToastPrimitives.Viewport>,\n React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport>\n>( ( { className, ...props }, ref ) => (\n <ToastPrimitives.Viewport\n ref={ref}\n className={cn(\n 'fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]',\n className,\n )}\n {...props}\n />\n) )\nToastViewport.displayName = ToastPrimitives.Viewport.displayName\n\nconst toastVariants = cva(\n 'group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full',\n {\n variants: {\n variant: {\n default: 'border bg-background text-foreground',\n destructive: 'destructive group border-destructive bg-destructive text-destructive-foreground',\n },\n },\n defaultVariants: { variant: 'default' },\n },\n)\n\nconst Toast = React.forwardRef<\n React.ElementRef<typeof ToastPrimitives.Root>,\n React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> & VariantProps<typeof toastVariants>\n>( ( { className, variant, ...props }, ref ) => (\n <ToastPrimitives.Root ref={ref} className={cn( toastVariants( { variant } ), className )} {...props} />\n) )\nToast.displayName = ToastPrimitives.Root.displayName\n\nconst ToastAction = React.forwardRef<\n React.ElementRef<typeof ToastPrimitives.Action>,\n React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>\n>( ( { className, ...props }, ref ) => (\n <ToastPrimitives.Action\n ref={ref}\n className={cn(\n 'inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',\n className,\n )}\n {...props}\n />\n) )\nToastAction.displayName = ToastPrimitives.Action.displayName\n\nconst ToastClose = React.forwardRef<\n React.ElementRef<typeof ToastPrimitives.Close>,\n React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>\n>( ( { className, ...props }, ref ) => (\n <ToastPrimitives.Close\n ref={ref}\n className={cn(\n 'absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100',\n className,\n )}\n toast-close=\"\"\n {...props}\n >\n <X className=\"h-4 w-4\" />\n </ToastPrimitives.Close>\n) )\nToastClose.displayName = ToastPrimitives.Close.displayName\n\nconst ToastTitle = React.forwardRef<\n React.ElementRef<typeof ToastPrimitives.Title>,\n React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>\n>( ( { className, ...props }, ref ) => (\n <ToastPrimitives.Title ref={ref} className={cn( 'text-sm font-semibold', className )} {...props} />\n) )\nToastTitle.displayName = ToastPrimitives.Title.displayName\n\nconst ToastDescription = React.forwardRef<\n React.ElementRef<typeof ToastPrimitives.Description>,\n React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>\n>( ( { className, ...props }, ref ) => (\n <ToastPrimitives.Description ref={ref} className={cn( 'text-sm opacity-90', className )} {...props} />\n) )\nToastDescription.displayName = ToastPrimitives.Description.displayName\n\nexport type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>\nexport type ToastActionElement = React.ReactElement<typeof ToastAction>\n\nexport {\n ToastProvider,\n ToastViewport,\n Toast,\n ToastTitle,\n ToastDescription,\n ToastClose,\n ToastAction,\n}\n","import { useToast } from '../../hooks/useToast'\nimport {\n Toast,\n ToastClose,\n ToastDescription,\n ToastProvider,\n ToastTitle,\n ToastViewport,\n} from './Toast'\n\nexport function Toaster() {\n const { toasts } = useToast()\n\n return (\n <ToastProvider>\n {toasts.map( ( { id, title, description, action, ...props } ) => (\n <Toast key={id} {...props}>\n <div className=\"grid gap-1\">\n {title && <ToastTitle>{title}</ToastTitle>}\n {description && <ToastDescription>{description}</ToastDescription>}\n </div>\n {action}\n <ToastClose />\n </Toast>\n ) )}\n <ToastViewport />\n </ToastProvider>\n )\n}\n","import { Button } from '../components/ui/Button'\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from '../components/ui/Card'\n\nexport interface LoginPageProps {\n loginPath: string\n title?: string\n subtitle?: string\n buttonLabel?: string\n /** URL of an image to show behind the sign-in card. Empty/null skips it. */\n backgroundUrl?: string\n /** Optional message shown above the button (e.g. an error from a failed prior attempt). */\n errorMessage?: string\n}\n\nfunction GoogleGlyph( { className }: { className?: string } ) {\n return (\n <svg viewBox=\"0 0 24 24\" className={className} aria-hidden=\"true\">\n <path fill=\"#4285F4\" d=\"M23.49 12.27c0-.79-.07-1.54-.19-2.27H12v4.51h6.16c-.27 1.4-1.04 2.59-2.21 3.41v2.77h3.59c2.08-1.92 3.95-4.74 3.95-8.42z\" />\n <path fill=\"#34A853\" d=\"M12 24c2.97 0 5.46-.98 7.28-2.66l-3.59-2.77c-.98.66-2.23 1.06-3.69 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 21.53 7.7 24 12 24z\" />\n <path fill=\"#FBBC05\" d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\" />\n <path fill=\"#EA4335\" d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\" />\n </svg>\n )\n}\n\nconst ERROR_MESSAGES: Record<string, string> = {\n auth_failed : 'Sign-in failed. Please try again.',\n}\n\nfunction readUrlError(): string | undefined {\n if ( typeof window === 'undefined' ) { \n return undefined \n }\n const code = new URLSearchParams( window.location.search ).get( 'error' )\n if ( !code ) { \n return undefined \n }\n return ERROR_MESSAGES[code] ?? `Sign-in error: ${code}`\n}\n\nexport function LoginPage( {\n loginPath,\n title = 'Sign in',\n subtitle,\n buttonLabel = 'Sign in with Google',\n backgroundUrl,\n errorMessage,\n}: LoginPageProps ) {\n const message = errorMessage ?? readUrlError()\n const hasBackground = Boolean( backgroundUrl )\n\n return (\n <div\n className=\"min-h-screen flex items-center justify-center bg-background bg-cover bg-center px-4\"\n style={hasBackground ? { backgroundImage: `url(${backgroundUrl})` } : undefined}\n >\n <Card className={`w-full max-w-md ${hasBackground ? 'backdrop-blur-sm bg-card/90' : ''}`}>\n <CardHeader className=\"text-center\">\n <CardTitle>{title}</CardTitle>\n {subtitle && <CardDescription>{subtitle}</CardDescription>}\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {message && (\n <div className=\"rounded-md border border-destructive bg-destructive/10 px-4 py-2 text-sm text-destructive\">\n {message}\n </div>\n )}\n <Button\n className=\"w-full\"\n variant=\"outline\"\n onClick={() => { window.location.href = loginPath }}\n >\n <GoogleGlyph className=\"h-5 w-5 mr-2\" />\n {buttonLabel}\n </Button>\n </CardContent>\n </Card>\n </div>\n )\n}\n\nexport default LoginPage\n","import { createElement, type ComponentType, type ReactNode } from 'react'\nimport { useQuery } from '@tanstack/react-query'\nimport { Config } from '@leverege/plugin'\n\nimport { useImaginariumApi } from '../api/ImaginariumApiContext'\nimport { LoginPage, type LoginPageProps } from './LoginPage'\n\nexport interface RequireAuthProps {\n children: ReactNode\n}\n\n/**\n * Wraps `children` with an authentication gate. On mount, fetches\n * `Config.get('ImaginariumApp', 'userPath', '/auth/user')` from the configured\n * API base URL. While loading, renders a small placeholder. On error, renders\n * the configured login component (defaults to the bundled `LoginPage`). On\n * success, renders `children`.\n *\n * Recognized config keys (under `'ImaginariumApp'`):\n * - `userPath` endpoint to check (default `/auth/user`)\n * - `loginPath` URL the login button navigates to (default `/api/login`)\n * - `loginPage` component to render when unauthenticated\n * - `loginTitle` default page heading\n * - `loginSubtitle` default page subtitle\n * - `loginButtonLabel` default button label\n * - `loginBackgroundUrl` URL of an image to show behind the sign-in card\n */\nexport function RequireAuth( { children }: RequireAuthProps ) {\n const { fetchJson } = useImaginariumApi()\n const userPath = Config.get<string>( 'ImaginariumApp', 'userPath', '/auth/user' )\n\n const { isPending, isError } = useQuery( {\n queryKey: [ 'imaginarium', 'auth', 'user', userPath ],\n queryFn: () => fetchJson( userPath ),\n retry: false,\n refetchOnWindowFocus: false,\n } )\n\n if ( isPending ) {\n return <div className=\"p-8 text-muted-foreground\">Checking sign-in…</div>\n }\n\n if ( isError ) {\n const LoginComponent = Config.get<ComponentType<LoginPageProps>>(\n 'ImaginariumApp', 'loginPage', LoginPage,\n )\n const title = Config.get<string | undefined>( 'ImaginariumApp', 'loginTitle', undefined )\n const subtitle = Config.get<string | undefined>( 'ImaginariumApp', 'loginSubtitle', undefined )\n const buttonLabel = Config.get<string | undefined>(\n 'ImaginariumApp', 'loginButtonLabel', undefined,\n )\n const loginPath = Config.get<string>( 'ImaginariumApp', 'loginPath', '/api/login' )\n const backgroundUrl = Config.get<string | undefined>(\n 'ImaginariumApp', 'loginBackgroundUrl', undefined,\n )\n\n const appTitle = Config.get<string>( 'ImaginariumApp', 'title', 'Imaginarium' )\n const resolvedTitle = title ?? `Sign in to ${appTitle}`\n\n return createElement( LoginComponent, {\n loginPath,\n title: resolvedTitle,\n subtitle,\n buttonLabel,\n backgroundUrl,\n } )\n }\n\n return <>{children}</>\n}\n\nexport default RequireAuth\n","import { ActiveTheme } from '../ui-elements'\n\n// ui-elements components read `theme.props`/`theme.classes` off the Theme\n// context and THROW if it is null. `ActiveTheme` provides those methods,\n// delegating to this fallback for any component an appearance doesn't define so\n// components render (unstyled) instead of crashing.\nconst FALLBACK_THEME = {\n props : ( _component : string, variant : unknown, userProps : unknown ) => {\n if ( variant && typeof variant === 'object' ) { return variant }\n return ( userProps && typeof userProps === 'object' ) ? userProps : {}\n },\n classes : ( ...args : unknown[] ) => args.filter( ( a ) => typeof a === 'string' && a ).join( ' ' ),\n subclasses : ( ...args : unknown[] ) => args.filter( ( a ) => typeof a === 'string' && a ).join( ' ' ),\n resources : () => undefined,\n}\n\ntype SharedTheme = { sync? : { start? : ( o : { appearanceId? : string } ) => void } }\n\n// ONE ActiveTheme for the whole document: its constructor calls\n// firebase.initializeApp(…, 'UIActiveTheme'), which throws if run twice, and the\n// appearance CSS it injects is global (`:root` vars + a <head> stylesheet). So\n// there is a single active appearance at any moment. Stashed on globalThis so\n// HMR re-evaluating this module doesn't construct a second instance.\nexport function getSharedTheme() : SharedTheme {\n const g = globalThis as { __imgmActiveTheme? : SharedTheme }\n if ( !g.__imgmActiveTheme ) {\n g.__imgmActiveTheme = new ActiveTheme( { altTheme : FALLBACK_THEME, addWindowCommands : false } ) as SharedTheme\n }\n return g.__imgmActiveTheme\n}\n\n// Point the shared theme at an appearance id (empty -> the built-in fallback).\nexport function pointAppearance( appearanceId : string ) {\n getSharedTheme().sync?.start?.( { appearanceId : appearanceId || undefined } )\n}\n\n// Default appearance shipped with the library: every prototype uses THIS by\n// default in any consuming app, so the variants prototypes are authored against\n// always resolve. Overridden only by a pasted gallery id (persisted in\n// localStorage) or `Config('Prototypes','baseAppearanceId')` — NOT by the host\n// app's own appearance, which must not shadow the shipped default.\nexport const DEFAULT_APPEARANCE_ID = '39oo5B3KISUzzfa1gT1Va1'\n\n// The app-wide baseline appearance. The app root sets it; prototype previews\n// override the shared theme transiently and restore to this when they unmount.\nlet appAppearanceId = ''\nexport function getAppAppearanceId() : string { return appAppearanceId }\nexport function setAppAppearanceId( id : string ) {\n appAppearanceId = id || ''\n pointAppearance( appAppearanceId )\n}\n","import { useEffect, useMemo, type ReactNode } from 'react'\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\nimport { Config } from '@leverege/plugin'\n\nimport { TooltipProvider } from '../components/ui/Tooltip'\nimport { Toaster } from '../components/ui/Toaster'\nimport { ImaginariumApiProvider } from '../api/ImaginariumApiContext'\nimport { RequireAuth } from '../auth/RequireAuth'\nimport { getProviders } from '../plugins/registry'\nimport { Theme } from '../ui-elements'\nimport { getSharedTheme, setAppAppearanceId } from '../theme/activeAppearance'\nimport { AppSidebar, type AppSidebarProps, type IconRef } from './AppSidebar'\nimport { Shell, type ShellProps } from './Shell'\n\n// Applies the app-wide ui-elements appearance theme. Opt-in: when no\n// `ImaginariumApp.appearanceId` is configured, it leaves the tree untouched (no\n// ActiveTheme/Firebase init). When set, it loads that appearance as the global\n// baseline so ui-elements components across the app are themed; prototype\n// previews override it transiently and restore it on exit. The Tailwind shell\n// chrome only changes if that appearance defines the shell's CSS tokens.\nfunction AppThemeBoundary( { children } : { children : ReactNode } ) {\n const appearanceId = Config.get<string>( 'ImaginariumApp', 'appearanceId', '' )\n useEffect( () => { setAppAppearanceId( appearanceId ) }, [ appearanceId ] )\n if ( !appearanceId ) { return <>{children}</> }\n return <Theme theme={getSharedTheme() as never}>{children}</Theme>\n}\n\nfunction withProviders( tree: ReactNode ): ReactNode {\n const providers = getProviders()\n let wrapped = tree\n for ( const { component: Provider } of providers ) {\n wrapped = <Provider>{wrapped}</Provider>\n }\n return wrapped\n}\n\nexport interface ImaginariumAppProps {\n apiBaseUrl?: string\n queryClient?: QueryClient\n title?: string\n titleIcon?: IconRef\n navRightSlot?: AppSidebarProps['rightSlot']\n shellFallback?: ShellProps['fallback']\n children?: ReactNode\n}\n\nconst defaultQueryClient = new QueryClient( {\n defaultOptions: {\n queries: { retry: false, refetchOnWindowFocus: false },\n },\n} )\n\nfunction GatedShell( { title, titleIcon, navRightSlot, shellFallback, children }: {\n title?: string\n titleIcon?: IconRef\n navRightSlot?: AppSidebarProps['rightSlot']\n shellFallback?: ShellProps['fallback']\n children?: ReactNode\n} ) {\n return withProviders(\n <div className=\"flex h-screen overflow-hidden bg-background text-foreground\">\n <AppSidebar title={title} titleIcon={titleIcon} rightSlot={navRightSlot} />\n <Shell fallback={shellFallback}>{children}</Shell>\n </div>,\n )\n}\n\nexport function ImaginariumApp( {\n apiBaseUrl = '/api',\n queryClient,\n title,\n titleIcon,\n navRightSlot,\n shellFallback,\n children,\n}: ImaginariumAppProps ) {\n const qc = useMemo( () => queryClient ?? defaultQueryClient, [ queryClient ] )\n const requireAuth = Config.get<boolean>( 'ImaginariumApp', 'requireAuth', true )\n const resolvedTitleIcon = titleIcon\n ?? Config.get<IconRef | undefined>( 'ImaginariumApp', 'titleIcon', undefined )\n\n const gated = (\n <GatedShell\n title={title}\n titleIcon={resolvedTitleIcon}\n navRightSlot={navRightSlot}\n shellFallback={shellFallback}\n >\n {children}\n </GatedShell>\n )\n\n return (\n <AppThemeBoundary>\n <QueryClientProvider client={qc}>\n <TooltipProvider>\n <ImaginariumApiProvider apiBaseUrl={apiBaseUrl}>\n {requireAuth ? <RequireAuth>{gated}</RequireAuth> : gated}\n <Toaster />\n </ImaginariumApiProvider>\n </TooltipProvider>\n </QueryClientProvider>\n </AppThemeBoundary>\n )\n}\n"],"names":["PageDocsContext","createContext","PageDocsProvider","children","tabMarkdown","setTabMarkdown","useState","jsx","useRegisterTabDocs","markdown","useContext","useEffect","useActiveTabDocs","triggerClass","active","cn","TriggerIcon","DocsTrigger","href","open","onToggle","jsxs","DocsSidePanel","pageDocs","onClose","title","Component","Fragment","ReactMarkdown","mdComponents","renderPageElement","plugin","element","isValidElement","createElement","Shell","fallback","ShellContent","pages","getPages","setOpen","location","useLocation","getPageDocs","o","Switch","page","Route","groupNavItems","items","ungrouped","sectionMap","item","a","b","sections","d","STORAGE_COLLAPSED","STORAGE_SECTIONS","readBool","key","v","readSections","parsed","URL_RE","renderIcon","icon","className","Icon","AppSidebar","titleIcon","rightSlot","collapsed","setCollapsed","collapsedSections","setCollapsedSections","toggleSidebar","useCallback","toggleSection","label","prev","next","getNavItems","topBarItems","getTopBarItems","ChevronLeft","path","isActive","Link","section","index","isSectionCollapsed","showDivider","ChevronDown","C","ToastProvider","ToastPrimitives","ToastViewport","React","props","ref","toastVariants","cva","Toast","variant","ToastAction","ToastClose","X","ToastTitle","ToastDescription","Toaster","toasts","useToast","id","description","action","GoogleGlyph","ERROR_MESSAGES","readUrlError","code","LoginPage","loginPath","subtitle","buttonLabel","backgroundUrl","errorMessage","message","hasBackground","Card","CardHeader","CardTitle","CardDescription","CardContent","Button","RequireAuth","fetchJson","useImaginariumApi","userPath","Config","isPending","isError","useQuery","LoginComponent","appTitle","resolvedTitle","FALLBACK_THEME","_component","userProps","args","getSharedTheme","g","ActiveTheme","pointAppearance","appearanceId","_b","_a","DEFAULT_APPEARANCE_ID","appAppearanceId","getAppAppearanceId","setAppAppearanceId","AppThemeBoundary","Theme","withProviders","tree","providers","getProviders","wrapped","Provider","defaultQueryClient","QueryClient","GatedShell","navRightSlot","shellFallback","ImaginariumApp","apiBaseUrl","queryClient","qc","useMemo","requireAuth","resolvedTitleIcon","gated","QueryClientProvider","TooltipProvider","ImaginariumApiProvider"],"mappings":"mzBAOMA,EAAkBC,EAAAA,cAAqC,CAC3D,YAAa,KACb,eAAgB,IAAM,CAAC,CACzB,CAAE,EAEK,SAASC,GAAkB,CAAE,SAAAC,GAAsC,CACxE,KAAM,CAAEC,EAAaC,CAAe,EAAIC,EAAAA,SAAyB,IAAK,EACtE,OACEC,EAAAA,IAACP,EAAgB,SAAhB,CAAyB,MAAO,CAAE,YAAAI,EAAa,eAAAC,GAC7C,SAAAF,EACH,CAEJ,CAOO,SAASK,GAAoBC,EAAmB,CACrD,KAAM,CAAE,eAAAJ,CAAA,EAAmBK,EAAAA,WAAYV,CAAgB,EACvDW,EAAAA,UAAW,KACTN,EAAgBI,CAAS,EAClB,IAAM,CAAEJ,EAAgB,IAAK,CAAE,GACrC,CAAEI,EAAUJ,CAAe,CAAE,CAClC,CAEO,SAASO,IAAkC,CAChD,OAAOF,EAAAA,WAAYV,CAAgB,EAAE,WACvC,CCzBA,MAAMa,EAAiBC,GAAqBC,EAAAA,GAC1C,gGACAD,EACI,+CACA,2FACN,EAEME,EAAc,IAClBT,EAAAA,IAAC,OAAA,CAAK,UAAU,oHAAoH,SAAA,IAEpI,EAGK,SAASU,EAAa,CAAE,KAAAC,EAAM,KAAAC,EAAO,GAAO,SAAAC,GAA+B,CAChF,OAAKF,GAAQ,KAETX,EAAAA,IAAC,MAAA,CACC,SAAAc,EAAAA,KAAC,IAAA,CAAE,KAAAH,EAAY,OAAO,SAAS,IAAI,sBAAsB,UAAWL,EAAc,EAAM,EACtF,SAAA,CAAAN,EAAAA,IAACS,EAAA,EAAY,EAAE,MAAA,CAAA,CAEjB,CAAA,CACF,EAIFT,EAAAA,IAAC,OACC,SAAAc,EAAAA,KAAC,SAAA,CAAO,QAASD,EAAU,UAAWP,EAAcM,CAAK,EACvD,SAAA,CAAAZ,EAAAA,IAACS,EAAA,EAAY,EAAE,MAAA,CAAA,CAEjB,CAAA,CACF,CAEJ,CAQO,SAASM,GAAe,CAAE,SAAAC,EAAU,YAAAnB,EAAa,QAAAoB,GAAgC,CACtF,MAAMC,EAAQF,EAAS,KAAK,QAAS,MAAO,EAAG,GAAK,OAC9CG,EAAYH,EAAS,UAE3B,OACEF,EAAAA,KAAC,QAAA,CAAM,UAAU,wHACf,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,qEACb,SAAA,CAAAd,EAAAA,IAAC,OAAA,CAAK,UAAU,wCAAyC,SAAAkB,EAAM,EAC/DlB,EAAAA,IAAC,SAAA,CACC,QAASiB,EACT,UAAU,wEACV,aAAW,mBACZ,SAAA,GAAA,CAAA,CAED,EACF,EAEAH,EAAAA,KAAC,MAAA,CAAI,UAAU,mCACZ,SAAA,CAAAjB,GAAe,MACdiB,EAAAA,KAAAM,EAAAA,SAAA,CACE,SAAA,CAAApB,EAAAA,IAACqB,EAAAA,SAAA,CAAc,WAAYC,EAAAA,aAAe,SAAAzB,EAAY,EACtDG,EAAAA,IAAC,KAAA,CAAG,UAAU,oBAAA,CAAqB,CAAA,EACrC,EAEDmB,GAAa,MAAQnB,MAACmB,EAAA,CAAA,CAAU,CAAA,CAAA,CACnC,CAAA,EACF,CAEJ,CCvEA,SAASI,GAAmBC,EAAgC,CAC1D,KAAM,CAAE,QAAAC,GAAYD,EACpB,OAAKE,EAAAA,eAAgBD,CAAQ,EAAaA,EACrC,OAAOA,GAAY,WACfE,EAAAA,cAAeF,CAA+B,EAEhDA,CACT,CAOO,SAASG,EAAO,CAAE,SAAAC,EAAU,SAAAjC,GAAyB,CAC1D,aACGD,GAAA,CACC,SAAAK,EAAAA,IAAC8B,GAAA,CAAa,SAAAD,EAAqB,SAAAjC,EAAS,EAC9C,CAEJ,CAEA,SAASkC,GAAc,CAAE,SAAAD,EAAU,SAAAjC,GAAyB,CAC1D,MAAMmC,EAAQC,EAAAA,SAAA,EACR,CAAEpB,EAAMqB,CAAQ,EAAIlC,EAAAA,SAAU,EAAM,EACpC,CAAEmC,CAAS,EAAIC,cAAA,EACfnB,EAAWoB,EAAAA,YAAaF,CAAS,EAEvC9B,EAAAA,UAAW,IAAM,CAAE6B,EAAS,EAAM,CAAE,EAAG,CAAEC,CAAS,CAAE,EACpD,MAAMrC,EAAcQ,GAAA,EAEpB,OACES,EAAAA,KAAC,MAAA,CAAI,UAAU,uCACb,SAAA,CAAAA,EAAAA,KAAC,OAAA,CAAK,UAAU,kCACb,SAAA,CAAAE,GAAY,MACXhB,EAAAA,IAAC,MAAA,CAAI,UAAU,6BACZ,WAAS,MAAQ,KACdA,EAAAA,IAACU,EAAA,CAAY,KAAMM,EAAS,KAAM,EAClChB,EAAAA,IAACU,EAAA,CAAY,KAAAE,EAAY,SAAU,IAAMqB,EAAWI,GAAO,CAACA,CAAE,CAAA,CAAG,CAAA,CACvE,EAEFvB,EAAAA,KAAC,MAAA,CAAI,UAAU,iBACZ,SAAA,CAAAlB,SACA0C,EAAAA,OAAA,CACE,SAAA,CAAAP,EAAM,IAAOQ,GACZvC,EAAAA,IAACwC,EAAAA,MAAA,CAAsB,KAAMD,EAAK,KAC/B,SAAAhB,GAAmBgB,CAAK,CAAA,EADfA,EAAK,IAEjB,CACA,EACFvC,EAAAA,IAACwC,EAAAA,OAAO,SAAAX,GAAY7B,EAAAA,IAAC,OAAI,UAAU,4BAA4B,qBAAS,CAAA,CAAO,CAAA,CAAA,CACjF,CAAA,CAAA,CACF,CAAA,EACF,EACCY,GAAQI,GAAY,MAAQA,EAAS,MAAQ,MAC5ChB,EAAAA,IAACe,GAAA,CACC,SAAAC,EACA,YAAAnB,EACA,QAAS,IAAMoC,EAAS,EAAM,CAAA,CAAA,CAChC,EAEJ,CAEJ,CCzDO,SAASQ,GAAeC,EAAqC,CAClE,MAAMC,EAA6B,CAAA,EAC7BC,MAAiB,IAEvB,UAAYC,KAAQH,EAAQ,CAC1B,GAAK,CAACG,EAAK,QAAU,CACnBF,EAAU,KAAME,CAAK,EACrB,QACF,CACMD,EAAW,IAAKC,EAAK,OAAQ,GACjCD,EAAW,IAAKC,EAAK,QAAS,CAC5B,MAAQA,EAAK,QACb,YAAcA,EAAK,aAAeA,EAAK,MAAQ,EAC/C,MAAQ,CAAA,CAAC,CACT,EAEJD,EAAW,IAAKC,EAAK,OAAQ,EAAG,MAAM,KAAMA,CAAK,CACnD,CAEAF,EAAU,KAAM,CAAEG,EAAGC,KAASD,EAAE,MAAQ,IAAQC,EAAE,MAAQ,EAAI,EAE9D,MAAMC,EAAW,MAAM,KAAMJ,EAAW,QAAS,EACjD,UAAY,KAAKI,EACf,EAAE,MAAM,KAAM,CAAEF,EAAGC,KAASD,EAAE,MAAQ,IAAQC,EAAE,MAAQ,EAAI,EAE9D,OAAAC,EAAS,KAAM,CAAEF,EAAGC,IAAO,CACzB,MAAME,EAAIH,EAAE,YAAcC,EAAE,YAC5B,OAAOE,IAAM,EAAIA,EAAIH,EAAE,MAAM,cAAeC,EAAE,KAAM,CACtD,CAAE,EAEK,CAAE,UAAAJ,EAAW,SAAAK,CAAA,CACtB,CC5BA,MAAME,EAAoB,mCACpBC,EAAqB,kCAE3B,SAASC,GAAUC,EAAaxB,EAA6B,CAC3D,GAAI,CACF,MAAMyB,EAAI,aAAa,QAASD,CAAI,EACpC,OAAOC,IAAM,KAAOzB,EAAWyB,IAAM,MACvC,MAAQ,CAAE,OAAOzB,CAAS,CAC5B,CAEA,SAAS0B,IAA4B,CACnC,GAAI,CACF,MAAMD,EAAI,aAAa,QAASH,CAAiB,EACjD,GAAK,CAACG,EAAM,WAAW,IACvB,MAAME,EAAS,KAAK,MAAOF,CAAE,EAC7B,OAAO,IAAI,IAAK,MAAM,QAASE,CAAO,EAAIA,EAAqB,EAAG,CACpE,MAAQ,CAAE,WAAW,GAAM,CAC7B,CAEA,MAAMC,GAAS,wCAEf,SAASC,GAAYC,EAA2BC,EAAoB,CAClE,GAAK,CAACD,EAAS,OAAO,KACtB,GAAK,OAAOA,GAAS,SACnB,OAAKF,GAAO,KAAME,CAAK,QAAc,MAAA,CAAI,IAAKA,EAAM,IAAI,GAAG,UAAAC,EAAsB,EAC1E5D,MAAC,QAAK,UAAW,GAAG2D,CAAI,IAAIC,CAAS,GAAI,cAAY,MAAA,CAAO,EAErE,MAAMC,EAAOF,EACb,OAAO3D,MAAC6D,GAAK,UAAAD,EAAsB,CACrC,CAQO,SAASE,EAAY,CAAE,MAAA5C,EAAQ,cAAe,UAAA6C,EAAW,UAAAC,GAA+B,CAC7F,KAAM,CAAE9B,CAAS,EAAIC,cAAA,EACf,CAAE8B,EAAWC,CAAa,EAAInE,EAAAA,SAAU,IAAMqD,GAAUF,EAAmB,EAAM,CAAE,EACnF,CAAEiB,EAAmBC,CAAqB,EAAIrE,EAAAA,SAAuBwD,EAAa,EAExFnD,EAAAA,UAAW,IAAM,CACf,GAAI,CAAE,aAAa,QAAS8C,EAAmB,OAAQe,CAAU,CAAE,CAAE,MAAQ,CAAe,CAC9F,EAAG,CAAEA,CAAU,CAAE,EAEjB7D,EAAAA,UAAW,IAAM,CACf,GAAI,CACF,aAAa,QAAS+C,EAAkB,KAAK,UAAW,MAAM,KAAMgB,CAAkB,CAAE,CAAE,CAC5F,MAAQ,CAAe,CACzB,EAAG,CAAEA,CAAkB,CAAE,EAEzB,MAAME,EAAgBC,EAAAA,YAAa,IAAMJ,KAAmB,CAACZ,CAAE,EAAG,EAAG,EAE/DiB,EAAgBD,cAAeE,GAAmB,CACtDJ,EAAsBK,GAAQ,CAC5B,MAAMC,EAAO,IAAI,IAAKD,CAAK,EAC3B,OAAAC,EAAK,IAAKF,CAAM,EAAIE,EAAK,OAAQF,CAAM,EAAIE,EAAK,IAAKF,CAAM,EACpDE,CACT,CAAE,CACJ,EAAG,CAAA,CAAG,EAEA,CAAE,UAAA/B,EAAW,SAAAK,CAAA,EAAaP,GAAekC,EAAAA,aAAc,EACvDC,EAAcC,EAAAA,eAAA,EAEpB,OACE/D,EAAAA,KAAC,QAAA,CACC,UAAWN,EAAAA,GACT,iHACAyD,EAAY,WAAa,WAAA,EAI3B,SAAA,CAAAnD,EAAAA,KAAC,MAAA,CAAI,UAAU,iEACZ,SAAA,CAAA,CAACmD,GAAaP,GAAYK,EAAW,SAAU,EAC/C,CAACE,GACAjE,EAAAA,IAAC,OAAA,CAAK,UAAU,wCAAyC,SAAAkB,EAAM,EAEjElB,EAAAA,IAAC,SAAA,CACC,QAASqE,EACT,aAAYJ,EAAY,iBAAmB,mBAC3C,UAAWzD,EAAAA,GACT,iGACA,iEACAyD,GAAa,4BAAA,EAGf,SAAAjE,EAAAA,IAAC8E,EAAAA,YAAA,CACC,UAAWtE,EAAAA,GAAI,4CAA6CyD,GAAa,YAAa,CAAA,CAAA,CACxF,CAAA,CACF,EACF,EAGAnD,EAAAA,KAAC,MAAA,CAAI,UAAU,uEAEZ,SAAA,CAAA6B,EAAU,IAAK,CAAE,CAAE,KAAAoC,EAAM,MAAAP,EAAO,KAAMX,KAAY,CACjD,MAAMmB,EAAW9C,IAAa6C,GAAQ7C,EAAS,WAAY,GAAG6C,CAAI,GAAI,EACtE,OACEjE,EAAAA,KAACmE,EAAAA,KAAA,CAEC,KAAMF,EACN,MAAOd,EAAYO,EAAQ,OAC3B,UAAWhE,EAAAA,GACT,0FACA,mFACAwE,GAAY,kDACZf,GAAa,qBAAA,EAGd,SAAA,CAAAJ,GAAQ7D,EAAAA,IAAC6D,EAAA,CAAK,UAAU,uBAAA,CAAwB,EAChD,CAACI,GAAajE,EAAAA,IAAC,OAAA,CAAM,SAAAwE,CAAA,CAAM,CAAA,CAAA,EAXvBO,CAAA,CAcX,CAAE,EAGD/B,EAAS,IAAK,CAAEkC,EAASC,IAAW,CACnC,MAAMC,EAAqB,CAACnB,GAAaE,EAAkB,IAAKe,EAAQ,KAAM,EAIxEG,EAAcF,EAAQ,GAAKxC,EAAU,OAAS,EACpD,OACE7B,EAAAA,KAAC,MAAA,CAAwB,UAAU,gBAEhC,SAAA,CAAAuE,GAAerF,EAAAA,IAAC,MAAA,CAAI,UAAU,uBAAA,CAAwB,EACtD,CAACiE,GACAnD,EAAAA,KAAC,SAAA,CACC,QAAS,IAAMyD,EAAeW,EAAQ,KAAM,EAC5C,UAAW1E,EAAAA,GACT,qDACA,4EACA,mEAAA,EAGD,SAAA,CAAA0E,EAAQ,MACTlF,EAAAA,IAACsF,EAAAA,YAAA,CACC,UAAW9E,EAAAA,GACT,4CACA4E,GAAsB,YAAA,CACxB,CAAA,CACF,CAAA,CAAA,EAKJpF,EAAAA,IAAC,MAAA,CACC,UAAWQ,EAAAA,GACT,oEACA4E,EAAqB,oBAAsB,0BAAA,EAG5C,SAAAF,EAAQ,MAAM,IAAK,CAAE,CAAE,KAAAH,EAAM,MAAAP,EAAO,KAAMX,KAAY,CACrD,MAAMmB,GAAW9C,IAAa6C,GAAQ7C,EAAS,WAAY,GAAG6C,CAAI,GAAI,EACtE,OACEjE,EAAAA,KAACmE,EAAAA,KAAA,CAEC,KAAMF,EACN,MAAOd,EAAYO,EAAQ,OAC3B,UAAWhE,EAAAA,GACT,0FACA,mFACAwE,IAAY,kDACZf,GAAa,qBAAA,EAGd,SAAA,CAAAJ,GAAQ7D,EAAAA,IAAC6D,EAAA,CAAK,UAAU,uBAAA,CAAwB,EAChD,CAACI,GAAajE,EAAAA,IAAC,OAAA,CAAM,SAAAwE,CAAA,CAAM,CAAA,CAAA,EAXvBO,CAAA,CAcX,CAAE,CAAA,CAAA,CACJ,CAAA,EAhDQG,EAAQ,KAiDlB,CAEJ,CAAE,CAAA,EACJ,EAGApE,OAAC,OAAI,UAAWN,EAAAA,GACd,iDACAyD,EAAY,iBAAmB,8BAAA,EAE9B,SAAA,CAAA,CAACA,GAAaD,EACdY,EAAY,IAAO/B,GAAU,CAC5B,MAAM0C,EAAI1C,EAAK,UACf,OAAO7C,EAAAA,IAACuF,EAAA,GAAO1C,EAAK,EAAI,CAC1B,CAAE,CAAA,CAAA,CACJ,CAAA,CAAA,CAAA,CAGN,CCxMA,MAAM2C,EAAgBC,EAAgB,SAEhCC,EAAgBC,EAAM,WAGzB,CAAE,CAAE,UAAA/B,EAAW,GAAGgC,CAAA,EAASC,IAC5B7F,EAAAA,IAACyF,EAAgB,SAAhB,CACC,IAAAI,EACA,UAAWrF,EAAAA,GACT,oIACAoD,CAAA,EAED,GAAGgC,CAAA,CACN,CACA,EACFF,EAAc,YAAcD,EAAgB,SAAS,YAErD,MAAMK,GAAgBC,GAAAA,IACpB,4lBACA,CACE,SAAU,CACR,QAAS,CACP,QAAS,uCACT,YAAa,iFAAA,CACf,EAEF,gBAAiB,CAAE,QAAS,SAAA,CAAU,CAE1C,EAEMC,EAAQL,EAAM,WAGjB,CAAE,CAAE,UAAA/B,EAAW,QAAAqC,EAAS,GAAGL,CAAA,EAASC,IACrC7F,EAAAA,IAACyF,EAAgB,KAAhB,CAAqB,IAAAI,EAAU,UAAWrF,EAAAA,GAAIsF,GAAe,CAAE,QAAAG,CAAA,CAAU,EAAGrC,CAAU,EAAI,GAAGgC,EAAO,CACrG,EACFI,EAAM,YAAcP,EAAgB,KAAK,YAEzC,MAAMS,EAAcP,EAAM,WAGvB,CAAE,CAAE,UAAA/B,EAAW,GAAGgC,CAAA,EAASC,IAC5B7F,EAAAA,IAACyF,EAAgB,OAAhB,CACC,IAAAI,EACA,UAAWrF,EAAAA,GACT,kSACAoD,CAAA,EAED,GAAGgC,CAAA,CACN,CACA,EACFM,EAAY,YAAcT,EAAgB,OAAO,YAEjD,MAAMU,EAAaR,EAAM,WAGtB,CAAE,CAAE,UAAA/B,EAAW,GAAGgC,CAAA,EAASC,IAC5B7F,EAAAA,IAACyF,EAAgB,MAAhB,CACC,IAAAI,EACA,UAAWrF,EAAAA,GACT,wLACAoD,CAAA,EAEF,cAAY,GACX,GAAGgC,EAEJ,SAAA5F,EAAAA,IAACoG,EAAAA,EAAA,CAAE,UAAU,SAAA,CAAU,CAAA,CACzB,CACA,EACFD,EAAW,YAAcV,EAAgB,MAAM,YAE/C,MAAMY,EAAaV,EAAM,WAGtB,CAAE,CAAE,UAAA/B,EAAW,GAAGgC,CAAA,EAASC,IAC5B7F,EAAAA,IAACyF,EAAgB,MAAhB,CAAsB,IAAAI,EAAU,UAAWrF,EAAAA,GAAI,wBAAyBoD,CAAU,EAAI,GAAGgC,EAAO,CACjG,EACFS,EAAW,YAAcZ,EAAgB,MAAM,YAE/C,MAAMa,EAAmBX,EAAM,WAG5B,CAAE,CAAE,UAAA/B,EAAW,GAAGgC,CAAA,EAASC,IAC5B7F,EAAAA,IAACyF,EAAgB,YAAhB,CAA4B,IAAAI,EAAU,UAAWrF,EAAAA,GAAI,qBAAsBoD,CAAU,EAAI,GAAGgC,EAAO,CACpG,EACFU,EAAiB,YAAcb,EAAgB,YAAY,YClFpD,SAASc,GAAU,CACxB,KAAM,CAAE,OAAAC,CAAA,EAAWC,WAAA,EAEnB,cACGjB,EAAA,CACE,SAAA,CAAAgB,EAAO,IAAK,CAAE,CAAE,GAAAE,EAAI,MAAAxF,EAAO,YAAAyF,EAAa,OAAAC,EAAQ,GAAGhB,CAAA,IAClD9E,EAAAA,KAACkF,EAAA,CAAgB,GAAGJ,EAClB,SAAA,CAAA9E,EAAAA,KAAC,MAAA,CAAI,UAAU,aACZ,SAAA,CAAAI,GAASlB,EAAAA,IAACqG,GAAY,SAAAnF,CAAA,CAAM,EAC5ByF,GAAe3G,EAAAA,IAACsG,EAAA,CAAkB,SAAAK,CAAA,CAAY,CAAA,EACjD,EACCC,QACAT,EAAA,CAAA,CAAW,CAAA,CAAA,EANFO,CAOZ,CACA,QACDhB,EAAA,CAAA,CAAc,CAAA,EACjB,CAEJ,CCRA,SAASmB,GAAa,CAAE,UAAAjD,GAAsC,CAC5D,cACG,MAAA,CAAI,QAAQ,YAAY,UAAAA,EAAsB,cAAY,OACzD,SAAA,CAAA5D,EAAAA,IAAC,OAAA,CAAK,KAAK,UAAU,EAAE,0HAA0H,EACjJA,EAAAA,IAAC,OAAA,CAAK,KAAK,UAAU,EAAE,wIAAwI,EAC/JA,EAAAA,IAAC,OAAA,CAAK,KAAK,UAAU,EAAE,gIAAgI,EACvJA,EAAAA,IAAC,OAAA,CAAK,KAAK,UAAU,EAAE,qIAAA,CAAsI,CAAA,EAC/J,CAEJ,CAEA,MAAM8G,GAAyC,CAC7C,YAAc,mCAChB,EAEA,SAASC,IAAmC,CAC1C,GAAK,OAAO,OAAW,IACrB,OAEF,MAAMC,EAAO,IAAI,gBAAiB,OAAO,SAAS,MAAO,EAAE,IAAK,OAAQ,EACxE,GAAMA,EAGN,OAAOF,GAAeE,CAAI,GAAK,kBAAkBA,CAAI,EACvD,CAEO,SAASC,EAAW,CACzB,UAAAC,EACA,MAAAhG,EAAQ,UACR,SAAAiG,EACA,YAAAC,EAAc,sBACd,cAAAC,EACA,aAAAC,CACF,EAAoB,CAClB,MAAMC,EAAUD,GAAgBP,GAAA,EAC1BS,EAAgB,EAASH,EAE/B,OACErH,EAAAA,IAAC,MAAA,CACC,UAAU,sFACV,MAAOwH,EAAgB,CAAE,gBAAiB,OAAOH,CAAa,KAAQ,OAEtE,gBAACI,OAAA,CAAK,UAAW,mBAAmBD,EAAgB,8BAAgC,EAAE,GACpF,SAAA,CAAA1G,EAAAA,KAAC4G,EAAAA,WAAA,CAAW,UAAU,cACpB,SAAA,CAAA1H,EAAAA,IAAC2H,EAAAA,WAAW,SAAAzG,CAAA,CAAM,EACjBiG,GAAYnH,EAAAA,IAAC4H,EAAAA,gBAAA,CAAiB,SAAAT,CAAA,CAAS,CAAA,EAC1C,EACArG,EAAAA,KAAC+G,EAAAA,YAAA,CAAY,UAAU,YACpB,SAAA,CAAAN,GACCvH,EAAAA,IAAC,MAAA,CAAI,UAAU,4FACZ,SAAAuH,EACH,EAEFzG,EAAAA,KAACgH,EAAAA,OAAA,CACC,UAAU,SACV,QAAQ,UACR,QAAS,IAAM,CAAE,OAAO,SAAS,KAAOZ,CAAU,EAElD,SAAA,CAAAlH,EAAAA,IAAC6G,GAAA,CAAY,UAAU,cAAA,CAAe,EACrCO,CAAA,CAAA,CAAA,CACH,CAAA,CACF,CAAA,CAAA,CACF,CAAA,CAAA,CAGN,CC1DO,SAASW,EAAa,CAAE,SAAAnI,GAA+B,CAC5D,KAAM,CAAE,UAAAoI,CAAA,EAAcC,oBAAA,EAChBC,EAAWC,EAAAA,OAAO,IAAa,iBAAkB,WAAY,YAAa,EAE1E,CAAE,UAAAC,EAAW,QAAAC,CAAA,EAAYC,WAAU,CACvC,SAAU,CAAE,cAAe,OAAQ,OAAQJ,CAAS,EACpD,QAAS,IAAMF,EAAWE,CAAS,EACnC,MAAO,GACP,qBAAsB,EAAA,CACtB,EAEF,GAAKE,EACH,OAAOpI,EAAAA,IAAC,MAAA,CAAI,UAAU,4BAA4B,SAAA,oBAAiB,EAGrE,GAAKqI,EAAU,CACb,MAAME,EAAiBJ,EAAAA,OAAO,IAC5B,iBAAkB,YAAalB,CAAA,EAE3B/F,EAAQiH,EAAAA,OAAO,IAAyB,iBAAkB,aAAc,MAAU,EAClFhB,EAAWgB,EAAAA,OAAO,IAAyB,iBAAkB,gBAAiB,MAAU,EACxFf,EAAce,EAAAA,OAAO,IACzB,iBAAkB,mBAAoB,MAAA,EAElCjB,EAAYiB,EAAAA,OAAO,IAAa,iBAAkB,YAAa,YAAa,EAC5Ed,EAAgBc,EAAAA,OAAO,IAC3B,iBAAkB,qBAAsB,MAAA,EAGpCK,EAAWL,EAAAA,OAAO,IAAa,iBAAkB,QAAS,aAAc,EACxEM,EAAgBvH,GAAS,cAAcsH,CAAQ,GAErD,OAAO7G,EAAAA,cAAe4G,EAAgB,CACpC,UAAArB,EACA,MAAOuB,EACP,SAAAtB,EACA,YAAAC,EACA,cAAAC,CAAA,CACA,CACJ,CAEA,yBAAU,SAAAzH,EAAS,CACrB,CC/DA,MAAM8I,GAAiB,CACrB,MAAQ,CAAEC,EAAqB1C,EAAmB2C,IAC3C3C,GAAW,OAAOA,GAAY,SAAoBA,EAC9C2C,GAAa,OAAOA,GAAc,SAAaA,EAAY,CAAA,EAEtE,QAAU,IAAKC,IAAsBA,EAAK,OAAU/F,GAAO,OAAOA,GAAM,UAAYA,CAAE,EAAE,KAAM,GAAI,EAClG,WAAa,IAAK+F,IAAsBA,EAAK,OAAU/F,GAAO,OAAOA,GAAM,UAAYA,CAAE,EAAE,KAAM,GAAI,EACrG,UAAY,IAAA,EACd,EASO,SAASgG,GAA+B,CAC7C,MAAMC,EAAI,WACV,OAAMA,EAAE,oBACNA,EAAE,kBAAoB,IAAIC,GAAa,CAAE,SAAWN,GAAgB,kBAAoB,GAAQ,GAE3FK,EAAE,iBACX,CAGO,SAASE,EAAiBC,EAAwB,UACvDC,GAAAC,EAAAN,EAAA,EAAiB,OAAjB,YAAAM,EAAuB,QAAvB,MAAAD,EAAA,KAAAC,EAAgC,CAAE,aAAeF,GAAgB,QACnE,CAOO,MAAMG,GAAwB,yBAIrC,IAAIC,EAAkB,GACf,SAASC,IAA8B,CAAE,OAAOD,CAAgB,CAChE,SAASE,GAAoB9C,EAAc,CAChD4C,EAAkB5C,GAAM,GACxBuC,EAAiBK,CAAgB,CACnC,CC9BA,SAASG,GAAkB,CAAE,SAAA7J,GAAwC,CACnE,MAAMsJ,EAAef,EAAAA,OAAO,IAAa,iBAAkB,eAAgB,EAAG,EAE9E,OADA/H,EAAAA,UAAW,IAAM,CAAEoJ,GAAoBN,CAAa,CAAE,EAAG,CAAEA,CAAa,CAAE,EACpEA,EACClJ,EAAAA,IAAC0J,GAAAA,MAAA,CAAM,MAAOZ,EAAA,EAA4B,SAAAlJ,EAAS,oBADzB,SAAAA,EAAS,CAE5C,CAEA,SAAS+J,GAAeC,EAA6B,CACnD,MAAMC,EAAYC,EAAAA,aAAA,EAClB,IAAIC,EAAUH,EACd,SAAY,CAAE,UAAWI,CAAA,IAAcH,EACrCE,EAAU/J,EAAAA,IAACgK,GAAU,SAAAD,CAAA,CAAQ,EAE/B,OAAOA,CACT,CAYA,MAAME,GAAqB,IAAIC,EAAAA,YAAa,CAC1C,eAAgB,CACd,QAAS,CAAE,MAAO,GAAO,qBAAsB,EAAA,CAAM,CAEzD,CAAE,EAEF,SAASC,GAAY,CAAE,MAAAjJ,EAAO,UAAA6C,EAAW,aAAAqG,EAAc,cAAAC,EAAe,SAAAzK,GAMlE,CACF,OAAO+J,GACL7I,EAAAA,KAAC,MAAA,CAAI,UAAU,8DACb,SAAA,CAAAd,EAAAA,IAAC8D,EAAA,CAAW,MAAA5C,EAAc,UAAA6C,EAAsB,UAAWqG,EAAc,EACzEpK,EAAAA,IAAC4B,EAAA,CAAM,SAAUyI,EAAgB,SAAAzK,CAAA,CAAS,CAAA,CAAA,CAC5C,CAAA,CAEJ,CAEO,SAAS0K,GAAgB,CAC9B,WAAAC,EAAa,OACb,YAAAC,EACA,MAAAtJ,EACA,UAAA6C,EACA,aAAAqG,EACA,cAAAC,EACA,SAAAzK,CACF,EAAyB,CACvB,MAAM6K,EAAKC,EAAAA,QAAS,IAAMF,GAAeP,GAAoB,CAAEO,CAAY,CAAE,EACvEG,EAAcxC,EAAAA,OAAO,IAAc,iBAAkB,cAAe,EAAK,EACzEyC,EAAoB7G,GACrBoE,EAAAA,OAAO,IAA0B,iBAAkB,YAAa,MAAU,EAEzE0C,EACJ7K,EAAAA,IAACmK,GAAA,CACC,MAAAjJ,EACA,UAAW0J,EACX,aAAAR,EACA,cAAAC,EAEC,SAAAzK,CAAA,CAAA,EAIL,OACEI,EAAAA,IAACyJ,GAAA,CACC,SAAAzJ,EAAAA,IAAC8K,EAAAA,oBAAA,CAAoB,OAAQL,EAC3B,SAAAzK,EAAAA,IAAC+K,GAAAA,gBAAA,CACC,SAAAjK,EAAAA,KAACkK,yBAAA,CAAuB,WAAAT,EACrB,SAAA,CAAAI,EAAc3K,EAAAA,IAAC+H,EAAA,CAAa,SAAA8C,CAAA,CAAM,EAAiBA,QACnDtE,EAAA,CAAA,CAAQ,CAAA,EACX,CAAA,CACF,EACF,EACF,CAEJ"}