@leverege/imaginarium-ui 1.2.1 → 1.2.2

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.
@@ -389,7 +389,7 @@ const ke = new F({
389
389
  });
390
390
  function Pe({ title: e, titleIcon: t, navRightSlot: n, shellFallback: a, children: o }) {
391
391
  return Te(
392
- /* @__PURE__ */ i("div", { className: "flex min-h-screen bg-background text-foreground", children: [
392
+ /* @__PURE__ */ i("div", { className: "flex h-screen overflow-hidden bg-background text-foreground", children: [
393
393
  /* @__PURE__ */ r(xe, { title: e, titleIcon: t, rightSlot: n }),
394
394
  /* @__PURE__ */ r(ue, { fallback: a, children: o })
395
395
  ] })
@@ -434,4 +434,4 @@ export {
434
434
  B as f,
435
435
  ye as g
436
436
  };
437
- //# sourceMappingURL=ImaginariumApp-DJ0f2GWB.js.map
437
+ //# sourceMappingURL=ImaginariumApp-Bp1toCAd.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ImaginariumApp-DJ0f2GWB.js","sources":["../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/shell/ImaginariumApp.tsx"],"sourcesContent":["import { isValidElement, createElement, type ReactNode } from 'react'\nimport { Route, Switch } from 'wouter'\n\nimport { getPages } from '../plugins/registry'\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 const pages = getPages()\n\n return (\n <main className=\"flex-1 overflow-y-auto px-6 py-6\">\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 </main>\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 ) => {\n const isSectionCollapsed = !collapsed && collapsedSections.has( section.label )\n return (\n <div key={section.label} className=\"flex flex-col\">\n {/* Section divider + header */}\n <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 { 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 { AppSidebar, type AppSidebarProps, type IconRef } from './AppSidebar'\nimport { Shell, type ShellProps } from './Shell'\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 min-h-screen 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 <QueryClientProvider client={qc}>\n <TooltipProvider>\n <ImaginariumApiProvider apiBaseUrl={apiBaseUrl}>\n {requireAuth ? <RequireAuth>{gated}</RequireAuth> : gated}\n <Toaster />\n </ImaginariumApiProvider>\n </TooltipProvider>\n </QueryClientProvider>\n )\n}\n"],"names":["renderPageElement","plugin","element","isValidElement","createElement","Shell","fallback","children","pages","getPages","jsxs","Switch","page","jsx","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","title","titleIcon","rightSlot","location","useLocation","collapsed","setCollapsed","useState","collapsedSections","setCollapsedSections","useEffect","toggleSidebar","useCallback","toggleSection","label","prev","next","getNavItems","topBarItems","getTopBarItems","cn","ChevronLeft","path","Icon","isActive","Link","section","isSectionCollapsed","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","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-Bp1toCAd.js","sources":["../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/shell/ImaginariumApp.tsx"],"sourcesContent":["import { isValidElement, createElement, type ReactNode } from 'react'\nimport { Route, Switch } from 'wouter'\n\nimport { getPages } from '../plugins/registry'\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 const pages = getPages()\n\n return (\n <main className=\"flex-1 overflow-y-auto px-6 py-6\">\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 </main>\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 ) => {\n const isSectionCollapsed = !collapsed && collapsedSections.has( section.label )\n return (\n <div key={section.label} className=\"flex flex-col\">\n {/* Section divider + header */}\n <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 { 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 { AppSidebar, type AppSidebarProps, type IconRef } from './AppSidebar'\nimport { Shell, type ShellProps } from './Shell'\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 <QueryClientProvider client={qc}>\n <TooltipProvider>\n <ImaginariumApiProvider apiBaseUrl={apiBaseUrl}>\n {requireAuth ? <RequireAuth>{gated}</RequireAuth> : gated}\n <Toaster />\n </ImaginariumApiProvider>\n </TooltipProvider>\n </QueryClientProvider>\n )\n}\n"],"names":["renderPageElement","plugin","element","isValidElement","createElement","Shell","fallback","children","pages","getPages","jsxs","Switch","page","jsx","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","title","titleIcon","rightSlot","location","useLocation","collapsed","setCollapsed","useState","collapsedSections","setCollapsedSections","useEffect","toggleSidebar","useCallback","toggleSection","label","prev","next","getNavItems","topBarItems","getTopBarItems","cn","ChevronLeft","path","Icon","isActive","Link","section","isSectionCollapsed","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","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,2 +1,2 @@
1
- "use strict";const e=require("react/jsx-runtime"),m=require("react"),A=require("@tanstack/react-query"),f=require("@leverege/plugin"),F=require("./Tooltip-DQn1fHhM.cjs"),i=require("./Card-CHVaz_7u.cjs"),Q=require("@radix-ui/react-toast"),H=require("class-variance-authority"),C=require("lucide-react"),y=require("./registry-CHzOVHAg.cjs"),h=require("wouter");function O(t){const r=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t){for(const n in t)if(n!=="default"){const o=Object.getOwnPropertyDescriptor(t,n);Object.defineProperty(r,n,o.get?o:{enumerable:!0,get:()=>t[n]})}}return r.default=t,Object.freeze(r)}const v=O(m),d=O(Q);function U(t){const{element:r}=t;return m.isValidElement(r)?r:typeof r=="function"?m.createElement(r):r}function L({fallback:t,children:r}){const n=y.getPages();return e.jsxs("main",{className:"flex-1 overflow-y-auto px-6 py-6",children:[r,e.jsxs(h.Switch,{children:[n.map(o=>e.jsx(h.Route,{path:o.path,children:U(o)},o.path)),e.jsx(h.Route,{children:t??e.jsx("div",{className:"p-8 text-muted-foreground",children:"Not found"})})]})]})}function W(t){const r=[],n=new Map;for(const s of t){if(!s.section){r.push(s);continue}n.has(s.section)||n.set(s.section,{label:s.section,sectionSort:s.sectionSort??s.sort??0,items:[]}),n.get(s.section).items.push(s)}r.sort((s,c)=>(s.sort??0)-(c.sort??0));const o=Array.from(n.values());for(const s of o)s.items.sort((c,l)=>(c.sort??0)-(l.sort??0));return o.sort((s,c)=>{const l=s.sectionSort-c.sectionSort;return l!==0?l:s.label.localeCompare(c.label)}),{ungrouped:r,sections:o}}const E="imaginarium.ui.sidebar.collapsed",B="imaginarium.ui.sidebar.sections";function J(t,r){try{const n=localStorage.getItem(t);return n===null?r:n==="true"}catch{return r}}function K(){try{const t=localStorage.getItem(B);if(!t)return new Set;const r=JSON.parse(t);return new Set(Array.isArray(r)?r:[])}catch{return new Set}}const X=/^(https?:|data:|blob:|\/|\.\/|\.\.\/)/;function Y(t,r){if(!t)return null;if(typeof t=="string")return X.test(t)?e.jsx("img",{src:t,alt:"",className:r}):e.jsx("span",{className:`${t} ${r}`,"aria-hidden":"true"});const n=t;return e.jsx(n,{className:r})}function _({title:t="Imaginarium",titleIcon:r,rightSlot:n}){const[o]=h.useLocation(),[s,c]=m.useState(()=>J(E,!1)),[l,g]=m.useState(K);m.useEffect(()=>{try{localStorage.setItem(E,String(s))}catch{}},[s]),m.useEffect(()=>{try{localStorage.setItem(B,JSON.stringify(Array.from(l)))}catch{}},[l]);const j=m.useCallback(()=>c(a=>!a),[]),b=m.useCallback(a=>{g(p=>{const u=new Set(p);return u.has(a)?u.delete(a):u.add(a),u})},[]),{ungrouped:x,sections:N}=W(y.getNavItems()),S=y.getTopBarItems();return e.jsxs("aside",{className:i.cn("flex flex-col flex-shrink-0 border-r bg-background transition-[width] duration-200 ease-in-out overflow-hidden",s?"w-[52px]":"w-[220px]"),children:[e.jsxs("div",{className:"flex h-[52px] flex-shrink-0 items-center border-b px-2.5 gap-2",children:[!s&&Y(r,"h-6 w-6"),!s&&e.jsx("span",{className:"flex-1 truncate text-sm font-semibold",children:t}),e.jsx("button",{onClick:j,"aria-label":s?"Expand sidebar":"Collapse sidebar",className:i.cn("flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-md border text-muted-foreground","hover:bg-accent hover:text-accent-foreground transition-colors",s&&"mx-auto border-transparent"),children:e.jsx(C.ChevronLeft,{className:i.cn("h-4 w-4 transition-transform duration-200",s&&"rotate-180")})})]}),e.jsxs("nav",{className:"flex flex-1 flex-col gap-0.5 overflow-y-auto overflow-x-hidden p-1.5",children:[x.map(({path:a,label:p,icon:u})=>{const w=o===a||o.startsWith(`${a}/`);return e.jsxs(h.Link,{href:a,title:s?p:void 0,className:i.cn("relative flex items-center gap-2.5 rounded-md px-2 py-1.5 text-sm text-muted-foreground","hover:bg-accent hover:text-accent-foreground transition-colors whitespace-nowrap",w&&"bg-accent/50 text-accent-foreground font-medium",s&&"justify-center px-2"),children:[u&&e.jsx(u,{className:"h-4 w-4 flex-shrink-0"}),!s&&e.jsx("span",{children:p})]},a)}),N.map(a=>{const p=!s&&l.has(a.label);return e.jsxs("div",{className:"flex flex-col",children:[e.jsx("div",{className:"my-1.5 h-px bg-border"}),!s&&e.jsxs("button",{onClick:()=>b(a.label),className:i.cn("flex items-center justify-between px-2 pb-1 pt-2.5","text-[10px] font-semibold uppercase tracking-widest text-muted-foreground","hover:text-foreground transition-colors cursor-pointer rounded-sm"),children:[a.label,e.jsx(C.ChevronDown,{className:i.cn("h-3 w-3 transition-transform duration-200",p&&"-rotate-90")})]}),e.jsx("div",{className:i.cn("flex flex-col gap-0.5 overflow-hidden transition-all duration-200",p?"max-h-0 opacity-0":"max-h-screen opacity-100"),children:a.items.map(({path:u,label:w,icon:q})=>{const z=o===u||o.startsWith(`${u}/`);return e.jsxs(h.Link,{href:u,title:s?w:void 0,className:i.cn("relative flex items-center gap-2.5 rounded-md px-2 py-1.5 text-sm text-muted-foreground","hover:bg-accent hover:text-accent-foreground transition-colors whitespace-nowrap",z&&"bg-accent/50 text-accent-foreground font-medium",s&&"justify-center px-2"),children:[q&&e.jsx(q,{className:"h-4 w-4 flex-shrink-0"}),!s&&e.jsx("span",{children:w})]},u)})})]},a.label)})]}),e.jsxs("div",{className:i.cn("flex flex-shrink-0 items-center border-t p-1.5",s?"flex-col gap-1":"flex-row justify-end gap-0.5"),children:[!s&&n,S.map(a=>{const p=a.component;return e.jsx(p,{},a.id)})]})]})}const D=d.Provider,T=v.forwardRef(({className:t,...r},n)=>e.jsx(d.Viewport,{ref:n,className:i.cn("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]",t),...r}));T.displayName=d.Viewport.displayName;const Z=H.cva("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",{variants:{variant:{default:"border bg-background text-foreground",destructive:"destructive group border-destructive bg-destructive text-destructive-foreground"}},defaultVariants:{variant:"default"}}),I=v.forwardRef(({className:t,variant:r,...n},o)=>e.jsx(d.Root,{ref:o,className:i.cn(Z({variant:r}),t),...n}));I.displayName=d.Root.displayName;const M=v.forwardRef(({className:t,...r},n)=>e.jsx(d.Action,{ref:n,className:i.cn("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",t),...r}));M.displayName=d.Action.displayName;const k=v.forwardRef(({className:t,...r},n)=>e.jsx(d.Close,{ref:n,className:i.cn("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",t),"toast-close":"",...r,children:e.jsx(C.X,{className:"h-4 w-4"})}));k.displayName=d.Close.displayName;const P=v.forwardRef(({className:t,...r},n)=>e.jsx(d.Title,{ref:n,className:i.cn("text-sm font-semibold",t),...r}));P.displayName=d.Title.displayName;const R=v.forwardRef(({className:t,...r},n)=>e.jsx(d.Description,{ref:n,className:i.cn("text-sm opacity-90",t),...r}));R.displayName=d.Description.displayName;function V(){const{toasts:t}=i.useToast();return e.jsxs(D,{children:[t.map(({id:r,title:n,description:o,action:s,...c})=>e.jsxs(I,{...c,children:[e.jsxs("div",{className:"grid gap-1",children:[n&&e.jsx(P,{children:n}),o&&e.jsx(R,{children:o})]}),s,e.jsx(k,{})]},r)),e.jsx(T,{})]})}function ee({className:t}){return e.jsxs("svg",{viewBox:"0 0 24 24",className:t,"aria-hidden":"true",children:[e.jsx("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"}),e.jsx("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"}),e.jsx("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"}),e.jsx("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"})]})}const te={auth_failed:"Sign-in failed. Please try again."};function re(){if(typeof window>"u")return;const t=new URLSearchParams(window.location.search).get("error");if(t)return te[t]??`Sign-in error: ${t}`}function $({loginPath:t,title:r="Sign in",subtitle:n,buttonLabel:o="Sign in with Google",backgroundUrl:s,errorMessage:c}){const l=c??re(),g=!!s;return e.jsx("div",{className:"min-h-screen flex items-center justify-center bg-background bg-cover bg-center px-4",style:g?{backgroundImage:`url(${s})`}:void 0,children:e.jsxs(i.Card,{className:`w-full max-w-md ${g?"backdrop-blur-sm bg-card/90":""}`,children:[e.jsxs(i.CardHeader,{className:"text-center",children:[e.jsx(i.CardTitle,{children:r}),n&&e.jsx(i.CardDescription,{children:n})]}),e.jsxs(i.CardContent,{className:"space-y-4",children:[l&&e.jsx("div",{className:"rounded-md border border-destructive bg-destructive/10 px-4 py-2 text-sm text-destructive",children:l}),e.jsxs(i.Button,{className:"w-full",variant:"outline",onClick:()=>{window.location.href=t},children:[e.jsx(ee,{className:"h-5 w-5 mr-2"}),o]})]})]})})}function G({children:t}){const{fetchJson:r}=i.useImaginariumApi(),n=f.Config.get("ImaginariumApp","userPath","/auth/user"),{isPending:o,isError:s}=A.useQuery({queryKey:["imaginarium","auth","user",n],queryFn:()=>r(n),retry:!1,refetchOnWindowFocus:!1});if(o)return e.jsx("div",{className:"p-8 text-muted-foreground",children:"Checking sign-in…"});if(s){const c=f.Config.get("ImaginariumApp","loginPage",$),l=f.Config.get("ImaginariumApp","loginTitle",void 0),g=f.Config.get("ImaginariumApp","loginSubtitle",void 0),j=f.Config.get("ImaginariumApp","loginButtonLabel",void 0),b=f.Config.get("ImaginariumApp","loginPath","/api/login"),x=f.Config.get("ImaginariumApp","loginBackgroundUrl",void 0),N=f.Config.get("ImaginariumApp","title","Imaginarium"),S=l??`Sign in to ${N}`;return m.createElement(c,{loginPath:b,title:S,subtitle:g,buttonLabel:j,backgroundUrl:x})}return e.jsx(e.Fragment,{children:t})}function ne(t){const r=y.getProviders();let n=t;for(const{component:o}of r)n=e.jsx(o,{children:n});return n}const se=new A.QueryClient({defaultOptions:{queries:{retry:!1,refetchOnWindowFocus:!1}}});function oe({title:t,titleIcon:r,navRightSlot:n,shellFallback:o,children:s}){return ne(e.jsxs("div",{className:"flex min-h-screen bg-background text-foreground",children:[e.jsx(_,{title:t,titleIcon:r,rightSlot:n}),e.jsx(L,{fallback:o,children:s})]}))}function ie({apiBaseUrl:t="/api",queryClient:r,title:n,titleIcon:o,navRightSlot:s,shellFallback:c,children:l}){const g=m.useMemo(()=>r??se,[r]),j=f.Config.get("ImaginariumApp","requireAuth",!0),b=o??f.Config.get("ImaginariumApp","titleIcon",void 0),x=e.jsx(oe,{title:n,titleIcon:b,navRightSlot:s,shellFallback:c,children:l});return e.jsx(A.QueryClientProvider,{client:g,children:e.jsx(F.TooltipProvider,{children:e.jsxs(i.ImaginariumApiProvider,{apiBaseUrl:t,children:[j?e.jsx(G,{children:x}):x,e.jsx(V,{})]})})})}exports.AppSidebar=_;exports.ImaginariumApp=ie;exports.LoginPage=$;exports.RequireAuth=G;exports.Shell=L;exports.Toast=I;exports.ToastAction=M;exports.ToastClose=k;exports.ToastDescription=R;exports.ToastProvider=D;exports.ToastTitle=P;exports.ToastViewport=T;exports.Toaster=V;
2
- //# sourceMappingURL=ImaginariumApp-B7Vlrxfd.cjs.map
1
+ "use strict";const e=require("react/jsx-runtime"),m=require("react"),A=require("@tanstack/react-query"),f=require("@leverege/plugin"),F=require("./Tooltip-DQn1fHhM.cjs"),i=require("./Card-CHVaz_7u.cjs"),Q=require("@radix-ui/react-toast"),H=require("class-variance-authority"),C=require("lucide-react"),y=require("./registry-CHzOVHAg.cjs"),h=require("wouter");function O(t){const r=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t){for(const n in t)if(n!=="default"){const o=Object.getOwnPropertyDescriptor(t,n);Object.defineProperty(r,n,o.get?o:{enumerable:!0,get:()=>t[n]})}}return r.default=t,Object.freeze(r)}const v=O(m),d=O(Q);function U(t){const{element:r}=t;return m.isValidElement(r)?r:typeof r=="function"?m.createElement(r):r}function L({fallback:t,children:r}){const n=y.getPages();return e.jsxs("main",{className:"flex-1 overflow-y-auto px-6 py-6",children:[r,e.jsxs(h.Switch,{children:[n.map(o=>e.jsx(h.Route,{path:o.path,children:U(o)},o.path)),e.jsx(h.Route,{children:t??e.jsx("div",{className:"p-8 text-muted-foreground",children:"Not found"})})]})]})}function W(t){const r=[],n=new Map;for(const s of t){if(!s.section){r.push(s);continue}n.has(s.section)||n.set(s.section,{label:s.section,sectionSort:s.sectionSort??s.sort??0,items:[]}),n.get(s.section).items.push(s)}r.sort((s,c)=>(s.sort??0)-(c.sort??0));const o=Array.from(n.values());for(const s of o)s.items.sort((c,l)=>(c.sort??0)-(l.sort??0));return o.sort((s,c)=>{const l=s.sectionSort-c.sectionSort;return l!==0?l:s.label.localeCompare(c.label)}),{ungrouped:r,sections:o}}const E="imaginarium.ui.sidebar.collapsed",B="imaginarium.ui.sidebar.sections";function J(t,r){try{const n=localStorage.getItem(t);return n===null?r:n==="true"}catch{return r}}function K(){try{const t=localStorage.getItem(B);if(!t)return new Set;const r=JSON.parse(t);return new Set(Array.isArray(r)?r:[])}catch{return new Set}}const X=/^(https?:|data:|blob:|\/|\.\/|\.\.\/)/;function Y(t,r){if(!t)return null;if(typeof t=="string")return X.test(t)?e.jsx("img",{src:t,alt:"",className:r}):e.jsx("span",{className:`${t} ${r}`,"aria-hidden":"true"});const n=t;return e.jsx(n,{className:r})}function _({title:t="Imaginarium",titleIcon:r,rightSlot:n}){const[o]=h.useLocation(),[s,c]=m.useState(()=>J(E,!1)),[l,g]=m.useState(K);m.useEffect(()=>{try{localStorage.setItem(E,String(s))}catch{}},[s]),m.useEffect(()=>{try{localStorage.setItem(B,JSON.stringify(Array.from(l)))}catch{}},[l]);const j=m.useCallback(()=>c(a=>!a),[]),b=m.useCallback(a=>{g(p=>{const u=new Set(p);return u.has(a)?u.delete(a):u.add(a),u})},[]),{ungrouped:x,sections:N}=W(y.getNavItems()),S=y.getTopBarItems();return e.jsxs("aside",{className:i.cn("flex flex-col flex-shrink-0 border-r bg-background transition-[width] duration-200 ease-in-out overflow-hidden",s?"w-[52px]":"w-[220px]"),children:[e.jsxs("div",{className:"flex h-[52px] flex-shrink-0 items-center border-b px-2.5 gap-2",children:[!s&&Y(r,"h-6 w-6"),!s&&e.jsx("span",{className:"flex-1 truncate text-sm font-semibold",children:t}),e.jsx("button",{onClick:j,"aria-label":s?"Expand sidebar":"Collapse sidebar",className:i.cn("flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-md border text-muted-foreground","hover:bg-accent hover:text-accent-foreground transition-colors",s&&"mx-auto border-transparent"),children:e.jsx(C.ChevronLeft,{className:i.cn("h-4 w-4 transition-transform duration-200",s&&"rotate-180")})})]}),e.jsxs("nav",{className:"flex flex-1 flex-col gap-0.5 overflow-y-auto overflow-x-hidden p-1.5",children:[x.map(({path:a,label:p,icon:u})=>{const w=o===a||o.startsWith(`${a}/`);return e.jsxs(h.Link,{href:a,title:s?p:void 0,className:i.cn("relative flex items-center gap-2.5 rounded-md px-2 py-1.5 text-sm text-muted-foreground","hover:bg-accent hover:text-accent-foreground transition-colors whitespace-nowrap",w&&"bg-accent/50 text-accent-foreground font-medium",s&&"justify-center px-2"),children:[u&&e.jsx(u,{className:"h-4 w-4 flex-shrink-0"}),!s&&e.jsx("span",{children:p})]},a)}),N.map(a=>{const p=!s&&l.has(a.label);return e.jsxs("div",{className:"flex flex-col",children:[e.jsx("div",{className:"my-1.5 h-px bg-border"}),!s&&e.jsxs("button",{onClick:()=>b(a.label),className:i.cn("flex items-center justify-between px-2 pb-1 pt-2.5","text-[10px] font-semibold uppercase tracking-widest text-muted-foreground","hover:text-foreground transition-colors cursor-pointer rounded-sm"),children:[a.label,e.jsx(C.ChevronDown,{className:i.cn("h-3 w-3 transition-transform duration-200",p&&"-rotate-90")})]}),e.jsx("div",{className:i.cn("flex flex-col gap-0.5 overflow-hidden transition-all duration-200",p?"max-h-0 opacity-0":"max-h-screen opacity-100"),children:a.items.map(({path:u,label:w,icon:q})=>{const z=o===u||o.startsWith(`${u}/`);return e.jsxs(h.Link,{href:u,title:s?w:void 0,className:i.cn("relative flex items-center gap-2.5 rounded-md px-2 py-1.5 text-sm text-muted-foreground","hover:bg-accent hover:text-accent-foreground transition-colors whitespace-nowrap",z&&"bg-accent/50 text-accent-foreground font-medium",s&&"justify-center px-2"),children:[q&&e.jsx(q,{className:"h-4 w-4 flex-shrink-0"}),!s&&e.jsx("span",{children:w})]},u)})})]},a.label)})]}),e.jsxs("div",{className:i.cn("flex flex-shrink-0 items-center border-t p-1.5",s?"flex-col gap-1":"flex-row justify-end gap-0.5"),children:[!s&&n,S.map(a=>{const p=a.component;return e.jsx(p,{},a.id)})]})]})}const D=d.Provider,T=v.forwardRef(({className:t,...r},n)=>e.jsx(d.Viewport,{ref:n,className:i.cn("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]",t),...r}));T.displayName=d.Viewport.displayName;const Z=H.cva("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",{variants:{variant:{default:"border bg-background text-foreground",destructive:"destructive group border-destructive bg-destructive text-destructive-foreground"}},defaultVariants:{variant:"default"}}),I=v.forwardRef(({className:t,variant:r,...n},o)=>e.jsx(d.Root,{ref:o,className:i.cn(Z({variant:r}),t),...n}));I.displayName=d.Root.displayName;const M=v.forwardRef(({className:t,...r},n)=>e.jsx(d.Action,{ref:n,className:i.cn("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",t),...r}));M.displayName=d.Action.displayName;const k=v.forwardRef(({className:t,...r},n)=>e.jsx(d.Close,{ref:n,className:i.cn("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",t),"toast-close":"",...r,children:e.jsx(C.X,{className:"h-4 w-4"})}));k.displayName=d.Close.displayName;const P=v.forwardRef(({className:t,...r},n)=>e.jsx(d.Title,{ref:n,className:i.cn("text-sm font-semibold",t),...r}));P.displayName=d.Title.displayName;const R=v.forwardRef(({className:t,...r},n)=>e.jsx(d.Description,{ref:n,className:i.cn("text-sm opacity-90",t),...r}));R.displayName=d.Description.displayName;function V(){const{toasts:t}=i.useToast();return e.jsxs(D,{children:[t.map(({id:r,title:n,description:o,action:s,...c})=>e.jsxs(I,{...c,children:[e.jsxs("div",{className:"grid gap-1",children:[n&&e.jsx(P,{children:n}),o&&e.jsx(R,{children:o})]}),s,e.jsx(k,{})]},r)),e.jsx(T,{})]})}function ee({className:t}){return e.jsxs("svg",{viewBox:"0 0 24 24",className:t,"aria-hidden":"true",children:[e.jsx("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"}),e.jsx("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"}),e.jsx("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"}),e.jsx("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"})]})}const te={auth_failed:"Sign-in failed. Please try again."};function re(){if(typeof window>"u")return;const t=new URLSearchParams(window.location.search).get("error");if(t)return te[t]??`Sign-in error: ${t}`}function $({loginPath:t,title:r="Sign in",subtitle:n,buttonLabel:o="Sign in with Google",backgroundUrl:s,errorMessage:c}){const l=c??re(),g=!!s;return e.jsx("div",{className:"min-h-screen flex items-center justify-center bg-background bg-cover bg-center px-4",style:g?{backgroundImage:`url(${s})`}:void 0,children:e.jsxs(i.Card,{className:`w-full max-w-md ${g?"backdrop-blur-sm bg-card/90":""}`,children:[e.jsxs(i.CardHeader,{className:"text-center",children:[e.jsx(i.CardTitle,{children:r}),n&&e.jsx(i.CardDescription,{children:n})]}),e.jsxs(i.CardContent,{className:"space-y-4",children:[l&&e.jsx("div",{className:"rounded-md border border-destructive bg-destructive/10 px-4 py-2 text-sm text-destructive",children:l}),e.jsxs(i.Button,{className:"w-full",variant:"outline",onClick:()=>{window.location.href=t},children:[e.jsx(ee,{className:"h-5 w-5 mr-2"}),o]})]})]})})}function G({children:t}){const{fetchJson:r}=i.useImaginariumApi(),n=f.Config.get("ImaginariumApp","userPath","/auth/user"),{isPending:o,isError:s}=A.useQuery({queryKey:["imaginarium","auth","user",n],queryFn:()=>r(n),retry:!1,refetchOnWindowFocus:!1});if(o)return e.jsx("div",{className:"p-8 text-muted-foreground",children:"Checking sign-in…"});if(s){const c=f.Config.get("ImaginariumApp","loginPage",$),l=f.Config.get("ImaginariumApp","loginTitle",void 0),g=f.Config.get("ImaginariumApp","loginSubtitle",void 0),j=f.Config.get("ImaginariumApp","loginButtonLabel",void 0),b=f.Config.get("ImaginariumApp","loginPath","/api/login"),x=f.Config.get("ImaginariumApp","loginBackgroundUrl",void 0),N=f.Config.get("ImaginariumApp","title","Imaginarium"),S=l??`Sign in to ${N}`;return m.createElement(c,{loginPath:b,title:S,subtitle:g,buttonLabel:j,backgroundUrl:x})}return e.jsx(e.Fragment,{children:t})}function ne(t){const r=y.getProviders();let n=t;for(const{component:o}of r)n=e.jsx(o,{children:n});return n}const se=new A.QueryClient({defaultOptions:{queries:{retry:!1,refetchOnWindowFocus:!1}}});function oe({title:t,titleIcon:r,navRightSlot:n,shellFallback:o,children:s}){return ne(e.jsxs("div",{className:"flex h-screen overflow-hidden bg-background text-foreground",children:[e.jsx(_,{title:t,titleIcon:r,rightSlot:n}),e.jsx(L,{fallback:o,children:s})]}))}function ie({apiBaseUrl:t="/api",queryClient:r,title:n,titleIcon:o,navRightSlot:s,shellFallback:c,children:l}){const g=m.useMemo(()=>r??se,[r]),j=f.Config.get("ImaginariumApp","requireAuth",!0),b=o??f.Config.get("ImaginariumApp","titleIcon",void 0),x=e.jsx(oe,{title:n,titleIcon:b,navRightSlot:s,shellFallback:c,children:l});return e.jsx(A.QueryClientProvider,{client:g,children:e.jsx(F.TooltipProvider,{children:e.jsxs(i.ImaginariumApiProvider,{apiBaseUrl:t,children:[j?e.jsx(G,{children:x}):x,e.jsx(V,{})]})})})}exports.AppSidebar=_;exports.ImaginariumApp=ie;exports.LoginPage=$;exports.RequireAuth=G;exports.Shell=L;exports.Toast=I;exports.ToastAction=M;exports.ToastClose=k;exports.ToastDescription=R;exports.ToastProvider=D;exports.ToastTitle=P;exports.ToastViewport=T;exports.Toaster=V;
2
+ //# sourceMappingURL=ImaginariumApp-DpQNMjG_.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ImaginariumApp-B7Vlrxfd.cjs","sources":["../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/shell/ImaginariumApp.tsx"],"sourcesContent":["import { isValidElement, createElement, type ReactNode } from 'react'\nimport { Route, Switch } from 'wouter'\n\nimport { getPages } from '../plugins/registry'\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 const pages = getPages()\n\n return (\n <main className=\"flex-1 overflow-y-auto px-6 py-6\">\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 </main>\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 ) => {\n const isSectionCollapsed = !collapsed && collapsedSections.has( section.label )\n return (\n <div key={section.label} className=\"flex flex-col\">\n {/* Section divider + header */}\n <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 { 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 { AppSidebar, type AppSidebarProps, type IconRef } from './AppSidebar'\nimport { Shell, type ShellProps } from './Shell'\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 min-h-screen 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 <QueryClientProvider client={qc}>\n <TooltipProvider>\n <ImaginariumApiProvider apiBaseUrl={apiBaseUrl}>\n {requireAuth ? <RequireAuth>{gated}</RequireAuth> : gated}\n <Toaster />\n </ImaginariumApiProvider>\n </TooltipProvider>\n </QueryClientProvider>\n )\n}\n"],"names":["renderPageElement","plugin","element","isValidElement","createElement","Shell","fallback","children","pages","getPages","jsxs","Switch","page","jsx","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","title","titleIcon","rightSlot","location","useLocation","collapsed","setCollapsed","useState","collapsedSections","setCollapsedSections","useEffect","toggleSidebar","useCallback","toggleSection","label","prev","next","getNavItems","topBarItems","getTopBarItems","cn","ChevronLeft","path","isActive","Link","section","isSectionCollapsed","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","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-DpQNMjG_.cjs","sources":["../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/shell/ImaginariumApp.tsx"],"sourcesContent":["import { isValidElement, createElement, type ReactNode } from 'react'\nimport { Route, Switch } from 'wouter'\n\nimport { getPages } from '../plugins/registry'\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 const pages = getPages()\n\n return (\n <main className=\"flex-1 overflow-y-auto px-6 py-6\">\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 </main>\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 ) => {\n const isSectionCollapsed = !collapsed && collapsedSections.has( section.label )\n return (\n <div key={section.label} className=\"flex flex-col\">\n {/* Section divider + header */}\n <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 { 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 { AppSidebar, type AppSidebarProps, type IconRef } from './AppSidebar'\nimport { Shell, type ShellProps } from './Shell'\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 <QueryClientProvider client={qc}>\n <TooltipProvider>\n <ImaginariumApiProvider apiBaseUrl={apiBaseUrl}>\n {requireAuth ? <RequireAuth>{gated}</RequireAuth> : gated}\n <Toaster />\n </ImaginariumApiProvider>\n </TooltipProvider>\n </QueryClientProvider>\n )\n}\n"],"names":["renderPageElement","plugin","element","isValidElement","createElement","Shell","fallback","children","pages","getPages","jsxs","Switch","page","jsx","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","title","titleIcon","rightSlot","location","useLocation","collapsed","setCollapsed","useState","collapsedSections","setCollapsedSections","useEffect","toggleSidebar","useCallback","toggleSection","label","prev","next","getNavItems","topBarItems","getTopBarItems","cn","ChevronLeft","path","isActive","Link","section","isSectionCollapsed","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","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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"}
package/lib/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const m=require("./PluginTypes-C4a2lmPj.cjs"),w=require("./registry-CHzOVHAg.cjs"),s=require("./ImaginariumApp-B7Vlrxfd.cjs"),p=require("./PluginSetup-3m6kjRze.cjs"),g=require("./SystemConfigsContext-yOuS10VO.cjs"),t=require("react/jsx-runtime"),z=require("react-dom/client"),u=require("@leverege/plugin"),S=require("lucide-react"),i=require("./Card-CHVaz_7u.cjs"),I=require("react"),U=require("@radix-ui/react-dropdown-menu"),x=require("./PluginSetup-CQPpS_Js.cjs"),V=require("./PluginSetup-DoIf-dYR.cjs"),l=require("./Label-BhnvyUcc.cjs"),P=require("./Tooltip-DQn1fHhM.cjs");function j(e){const o=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const n in e)if(n!=="default"){const r=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(o,n,r.get?r:{enumerable:!0,get:()=>e[n]})}}return o.default=e,Object.freeze(o)}const h=j(I),a=j(U);function G(){if(!u.Config.get("ImaginariumApp","requireAuth",!0))return null;const o=u.Config.get("ImaginariumApp","logoutPath","/api/logout");return t.jsx(i.Button,{variant:"ghost",size:"sm","aria-label":"Sign out",onClick:()=>{window.location.href=o},children:t.jsx(S.LogOut,{className:"h-4 w-4"})})}const N={id:"imaginarium.ui.LogoutItem",sort:100,component:G},M="imaginarium.ui.theme";function H(){if(typeof window>"u")return"light";const e=window.localStorage.getItem(M);return e==="light"||e==="dark"?e:window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}function _(){const[e,o]=I.useState(H);I.useEffect(()=>{document.documentElement.classList.toggle("dark",e==="dark"),window.localStorage.setItem(M,e)},[e]);const n=e==="dark"?"light":"dark";return t.jsx(i.Button,{variant:"ghost",size:"sm","aria-label":`Switch to ${n} mode`,onClick:()=>o(n),children:e==="dark"?t.jsx(S.Sun,{className:"h-4 w-4"}):t.jsx(S.Moon,{className:"h-4 w-4"})})}const k={id:"imaginarium.ui.UIModeItem",sort:90,component:_},R=a.Root,A=a.Trigger,E=a.Group,$=a.Portal,K=a.Sub,Y=a.RadioGroup,F=h.forwardRef(({className:e,inset:o,children:n,...r},f)=>t.jsxs(a.SubTrigger,{ref:f,className:i.cn("flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent",o&&"pl-8",e),...r,children:[n,t.jsx(S.ChevronRight,{className:"ml-auto h-4 w-4"})]}));F.displayName=a.SubTrigger.displayName;const q=h.forwardRef(({className:e,...o},n)=>t.jsx(a.SubContent,{ref:n,className:i.cn("z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",e),...o}));q.displayName=a.SubContent.displayName;const b=h.forwardRef(({className:e,sideOffset:o=4,...n},r)=>t.jsx(a.Portal,{children:t.jsx(a.Content,{ref:r,sideOffset:o,className:i.cn("z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",e),...n})}));b.displayName=a.Content.displayName;const v=h.forwardRef(({className:e,inset:o,...n},r)=>t.jsx(a.Item,{ref:r,className:i.cn("relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",o&&"pl-8",e),...n}));v.displayName=a.Item.displayName;const C=h.forwardRef(({className:e,children:o,checked:n,...r},f)=>t.jsxs(a.CheckboxItem,{ref:f,className:i.cn("relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",e),checked:n,...r,children:[t.jsx("span",{className:"absolute left-2 flex h-3.5 w-3.5 items-center justify-center",children:t.jsx(a.ItemIndicator,{children:t.jsx(S.Check,{className:"h-4 w-4"})})}),o]}));C.displayName=a.CheckboxItem.displayName;const B=h.forwardRef(({className:e,children:o,...n},r)=>t.jsxs(a.RadioItem,{ref:r,className:i.cn("relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",e),...n,children:[t.jsx("span",{className:"absolute left-2 flex h-3.5 w-3.5 items-center justify-center",children:t.jsx(a.ItemIndicator,{children:t.jsx(S.Circle,{className:"h-2 w-2 fill-current"})})}),o]}));B.displayName=a.RadioItem.displayName;const D=h.forwardRef(({className:e,inset:o,...n},r)=>t.jsx(a.Label,{ref:r,className:i.cn("px-2 py-1.5 text-sm font-semibold",o&&"pl-8",e),...n}));D.displayName=a.Label.displayName;const T=h.forwardRef(({className:e,...o},n)=>t.jsx(a.Separator,{ref:n,className:i.cn("-mx-1 my-1 h-px bg-muted",e),...o}));T.displayName=a.Separator.displayName;const O=({className:e,...o})=>t.jsx("span",{className:i.cn("ml-auto text-xs tracking-widest opacity-60",e),...o});O.displayName="DropdownMenuShortcut";function J(){const e=g.useFilters(),o=new Set(e.hiddenSystemConfigTypes),n=new Set(e.hiddenSystemConfigTags),r=e.knownSystemConfigTypes.length>0,f=e.knownSystemConfigTags.length>0,y=e.hiddenSystemConfigTypes.length+e.hiddenSystemConfigTags.length,c=!e.showDev||y>0;return t.jsxs(R,{children:[t.jsx(A,{asChild:!0,children:t.jsxs(i.Button,{variant:c?"secondary":"ghost",size:"sm","aria-label":e.filteredOutCount>0?`Filter (${e.filteredOutCount} hidden)`:"Filter",children:[t.jsx(S.Filter,{className:"h-4 w-4"}),e.filteredOutCount>0?t.jsx("span",{className:"ml-1 inline-flex min-w-4 items-center justify-center rounded-full bg-primary px-1 py-0 text-[0.625rem] font-medium leading-4 text-primary-foreground",children:e.filteredOutCount}):null]})}),t.jsxs(b,{align:"end",className:"min-w-48",children:[t.jsx(C,{checked:e.showDev,onCheckedChange:e.setShowDev,children:"Show Development"}),r?t.jsxs(I.Fragment,{children:[t.jsx(T,{}),t.jsx(D,{children:"Types"}),e.knownSystemConfigTypes.map(d=>t.jsx(C,{checked:!o.has(d),onCheckedChange:()=>e.toggleSystemConfigType(d),children:d},d))]}):null,f?t.jsxs(I.Fragment,{children:[t.jsx(T,{}),t.jsx(D,{children:"Tags"}),e.knownSystemConfigTags.map(d=>t.jsx(C,{checked:!n.has(d),onCheckedChange:()=>e.toggleSystemConfigTag(d),children:d},d))]}):null,y>0?t.jsxs(I.Fragment,{children:[t.jsx(T,{}),t.jsx(v,{onClick:e.clearHidden,children:"Clear filters"})]}):null]})]})}const L={id:"imaginarium.ui.SystemConfigFilterItem",sort:80,component:J},Q={install(e){V.ReleaseSetup.install(e)}},W={install(e){p.SystemSetup.install(e),x.SecretSetup.install(e),Q.install(e),e.addPlugin(m.ProviderType,{id:"imaginarium.ui.FilterProvider",sort:50,component:g.FilterProvider}),e.addPlugin(m.ProviderType,{id:"imaginarium.ui.SystemConfigsProvider",sort:40,component:g.SystemConfigsProvider}),e.addPlugin(m.TopBarItemType,L),e.addPlugin(m.TopBarItemType,k),e.addPlugin(m.TopBarItemType,N),console.log("Installing built-in plugin setup!!"),e.addPlugin(m.PageType,{id:"imaginarium.RootRedirect",path:"/",element:()=>(console.log("Redirecting from / to /system-config"),window.location.replace(u.Config.get("ImaginariumApp","rootRedirect","/system-config")),null)})}},X={init(e,o){const n=e??{},r=n.config??{};for(const y of Object.keys(r)){const c=r[y];if(c)for(const d of Object.keys(c))u.Config.set(y,d,c[d])}const f=new Set(n.excludes??[]);f.size>0&&u.Plugins.addMutator((y,c)=>c&&typeof c=="object"&&f.has(c.id??"")?null:c);for(const y of n.mutators??[])u.Plugins.addMutator(y);console.log("Installing built-in plugin setup..."),W.install(u.Plugins),o.install(u.Plugins)},create(){const e=u.Config.get("ImaginariumApp","rootElement","#root"),o=u.Config.get("ImaginariumApp","apiBaseUrl","/api"),n=u.Config.get("ImaginariumApp","title","Imaginarium"),r=typeof e=="string"?document.querySelector(e):e;if(!r)throw new Error(`ImaginariumUI.create: root element not found (${String(e)})`);z.createRoot(r).render(t.jsx(s.ImaginariumApp,{apiBaseUrl:o,title:n}))}};exports.NavItemType=m.NavItemType;exports.PageType=m.PageType;exports.ProviderType=m.ProviderType;exports.TopBarItemType=m.TopBarItemType;exports.addNavItem=w.addNavItem;exports.addPage=w.addPage;exports.addProvider=w.addProvider;exports.getNavItems=w.getNavItems;exports.getPages=w.getPages;exports.getProviders=w.getProviders;exports.AppSidebar=s.AppSidebar;exports.ImaginariumApp=s.ImaginariumApp;exports.LoginPage=s.LoginPage;exports.RequireAuth=s.RequireAuth;exports.Shell=s.Shell;exports.Toast=s.Toast;exports.ToastAction=s.ToastAction;exports.ToastClose=s.ToastClose;exports.ToastDescription=s.ToastDescription;exports.ToastProvider=s.ToastProvider;exports.ToastTitle=s.ToastTitle;exports.ToastViewport=s.ToastViewport;exports.Toaster=s.Toaster;exports.ImagineSystemNavItem=p.ImagineSystemNavItem;exports.ImagineSystemNavItemId=p.ImagineSystemNavItemId;exports.ImagineSystemPage=p.ImagineSystemPage;exports.ImagineSystemPageId=p.ImagineSystemPageId;exports.ImagineSystemView=p.ImagineSystemView;exports.SystemSetup=p.SystemSetup;exports.SystemSetupDefault=p.SystemSetup;exports.TagInput=p.TagInput;exports.FilterProvider=g.FilterProvider;exports.SystemConfigsProvider=g.SystemConfigsProvider;exports.applyConfigFilters=g.applyConfigFilters;exports.isDevConfig=g.isDevConfig;exports.useFilters=g.useFilters;exports.useSystemConfigs=g.useSystemConfigs;exports.Button=i.Button;exports.Card=i.Card;exports.CardContent=i.CardContent;exports.CardDescription=i.CardDescription;exports.CardFooter=i.CardFooter;exports.CardHeader=i.CardHeader;exports.CardTitle=i.CardTitle;exports.ImaginariumApiProvider=i.ImaginariumApiProvider;exports.buttonVariants=i.buttonVariants;exports.cn=i.cn;exports.toast=i.toast;exports.useImaginariumApi=i.useImaginariumApi;exports.useToast=i.useToast;exports.SecretNavItem=x.SecretNavItem;exports.SecretPage=x.SecretPage;exports.SecretSetup=x.SecretSetup;exports.SecretView=x.SecretView;exports.Dialog=l.Dialog;exports.DialogClose=l.DialogClose;exports.DialogContent=l.DialogContent;exports.DialogDescription=l.DialogDescription;exports.DialogFooter=l.DialogFooter;exports.DialogHeader=l.DialogHeader;exports.DialogOverlay=l.DialogOverlay;exports.DialogPortal=l.DialogPortal;exports.DialogTitle=l.DialogTitle;exports.DialogTrigger=l.DialogTrigger;exports.Input=l.Input;exports.Label=l.Label;exports.Tooltip=P.Tooltip;exports.TooltipContent=P.TooltipContent;exports.TooltipProvider=P.TooltipProvider;exports.TooltipTrigger=P.TooltipTrigger;exports.DropdownMenu=R;exports.DropdownMenuCheckboxItem=C;exports.DropdownMenuContent=b;exports.DropdownMenuGroup=E;exports.DropdownMenuItem=v;exports.DropdownMenuLabel=D;exports.DropdownMenuPortal=$;exports.DropdownMenuRadioGroup=Y;exports.DropdownMenuRadioItem=B;exports.DropdownMenuSeparator=T;exports.DropdownMenuShortcut=O;exports.DropdownMenuSub=K;exports.DropdownMenuSubContent=q;exports.DropdownMenuSubTrigger=F;exports.DropdownMenuTrigger=A;exports.ImaginariumUI=X;exports.LogoutItem=N;exports.SystemConfigFilterItem=L;exports.UIModeItem=k;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const m=require("./PluginTypes-C4a2lmPj.cjs"),w=require("./registry-CHzOVHAg.cjs"),s=require("./ImaginariumApp-DpQNMjG_.cjs"),p=require("./PluginSetup-3m6kjRze.cjs"),g=require("./SystemConfigsContext-yOuS10VO.cjs"),t=require("react/jsx-runtime"),z=require("react-dom/client"),u=require("@leverege/plugin"),S=require("lucide-react"),i=require("./Card-CHVaz_7u.cjs"),I=require("react"),U=require("@radix-ui/react-dropdown-menu"),x=require("./PluginSetup-CQPpS_Js.cjs"),V=require("./PluginSetup-DoIf-dYR.cjs"),l=require("./Label-BhnvyUcc.cjs"),P=require("./Tooltip-DQn1fHhM.cjs");function j(e){const o=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const n in e)if(n!=="default"){const r=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(o,n,r.get?r:{enumerable:!0,get:()=>e[n]})}}return o.default=e,Object.freeze(o)}const h=j(I),a=j(U);function G(){if(!u.Config.get("ImaginariumApp","requireAuth",!0))return null;const o=u.Config.get("ImaginariumApp","logoutPath","/api/logout");return t.jsx(i.Button,{variant:"ghost",size:"sm","aria-label":"Sign out",onClick:()=>{window.location.href=o},children:t.jsx(S.LogOut,{className:"h-4 w-4"})})}const N={id:"imaginarium.ui.LogoutItem",sort:100,component:G},M="imaginarium.ui.theme";function H(){if(typeof window>"u")return"light";const e=window.localStorage.getItem(M);return e==="light"||e==="dark"?e:window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}function _(){const[e,o]=I.useState(H);I.useEffect(()=>{document.documentElement.classList.toggle("dark",e==="dark"),window.localStorage.setItem(M,e)},[e]);const n=e==="dark"?"light":"dark";return t.jsx(i.Button,{variant:"ghost",size:"sm","aria-label":`Switch to ${n} mode`,onClick:()=>o(n),children:e==="dark"?t.jsx(S.Sun,{className:"h-4 w-4"}):t.jsx(S.Moon,{className:"h-4 w-4"})})}const k={id:"imaginarium.ui.UIModeItem",sort:90,component:_},R=a.Root,A=a.Trigger,E=a.Group,$=a.Portal,K=a.Sub,Y=a.RadioGroup,F=h.forwardRef(({className:e,inset:o,children:n,...r},f)=>t.jsxs(a.SubTrigger,{ref:f,className:i.cn("flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent",o&&"pl-8",e),...r,children:[n,t.jsx(S.ChevronRight,{className:"ml-auto h-4 w-4"})]}));F.displayName=a.SubTrigger.displayName;const q=h.forwardRef(({className:e,...o},n)=>t.jsx(a.SubContent,{ref:n,className:i.cn("z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",e),...o}));q.displayName=a.SubContent.displayName;const b=h.forwardRef(({className:e,sideOffset:o=4,...n},r)=>t.jsx(a.Portal,{children:t.jsx(a.Content,{ref:r,sideOffset:o,className:i.cn("z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",e),...n})}));b.displayName=a.Content.displayName;const v=h.forwardRef(({className:e,inset:o,...n},r)=>t.jsx(a.Item,{ref:r,className:i.cn("relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",o&&"pl-8",e),...n}));v.displayName=a.Item.displayName;const C=h.forwardRef(({className:e,children:o,checked:n,...r},f)=>t.jsxs(a.CheckboxItem,{ref:f,className:i.cn("relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",e),checked:n,...r,children:[t.jsx("span",{className:"absolute left-2 flex h-3.5 w-3.5 items-center justify-center",children:t.jsx(a.ItemIndicator,{children:t.jsx(S.Check,{className:"h-4 w-4"})})}),o]}));C.displayName=a.CheckboxItem.displayName;const B=h.forwardRef(({className:e,children:o,...n},r)=>t.jsxs(a.RadioItem,{ref:r,className:i.cn("relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",e),...n,children:[t.jsx("span",{className:"absolute left-2 flex h-3.5 w-3.5 items-center justify-center",children:t.jsx(a.ItemIndicator,{children:t.jsx(S.Circle,{className:"h-2 w-2 fill-current"})})}),o]}));B.displayName=a.RadioItem.displayName;const D=h.forwardRef(({className:e,inset:o,...n},r)=>t.jsx(a.Label,{ref:r,className:i.cn("px-2 py-1.5 text-sm font-semibold",o&&"pl-8",e),...n}));D.displayName=a.Label.displayName;const T=h.forwardRef(({className:e,...o},n)=>t.jsx(a.Separator,{ref:n,className:i.cn("-mx-1 my-1 h-px bg-muted",e),...o}));T.displayName=a.Separator.displayName;const O=({className:e,...o})=>t.jsx("span",{className:i.cn("ml-auto text-xs tracking-widest opacity-60",e),...o});O.displayName="DropdownMenuShortcut";function J(){const e=g.useFilters(),o=new Set(e.hiddenSystemConfigTypes),n=new Set(e.hiddenSystemConfigTags),r=e.knownSystemConfigTypes.length>0,f=e.knownSystemConfigTags.length>0,y=e.hiddenSystemConfigTypes.length+e.hiddenSystemConfigTags.length,c=!e.showDev||y>0;return t.jsxs(R,{children:[t.jsx(A,{asChild:!0,children:t.jsxs(i.Button,{variant:c?"secondary":"ghost",size:"sm","aria-label":e.filteredOutCount>0?`Filter (${e.filteredOutCount} hidden)`:"Filter",children:[t.jsx(S.Filter,{className:"h-4 w-4"}),e.filteredOutCount>0?t.jsx("span",{className:"ml-1 inline-flex min-w-4 items-center justify-center rounded-full bg-primary px-1 py-0 text-[0.625rem] font-medium leading-4 text-primary-foreground",children:e.filteredOutCount}):null]})}),t.jsxs(b,{align:"end",className:"min-w-48",children:[t.jsx(C,{checked:e.showDev,onCheckedChange:e.setShowDev,children:"Show Development"}),r?t.jsxs(I.Fragment,{children:[t.jsx(T,{}),t.jsx(D,{children:"Types"}),e.knownSystemConfigTypes.map(d=>t.jsx(C,{checked:!o.has(d),onCheckedChange:()=>e.toggleSystemConfigType(d),children:d},d))]}):null,f?t.jsxs(I.Fragment,{children:[t.jsx(T,{}),t.jsx(D,{children:"Tags"}),e.knownSystemConfigTags.map(d=>t.jsx(C,{checked:!n.has(d),onCheckedChange:()=>e.toggleSystemConfigTag(d),children:d},d))]}):null,y>0?t.jsxs(I.Fragment,{children:[t.jsx(T,{}),t.jsx(v,{onClick:e.clearHidden,children:"Clear filters"})]}):null]})]})}const L={id:"imaginarium.ui.SystemConfigFilterItem",sort:80,component:J},Q={install(e){V.ReleaseSetup.install(e)}},W={install(e){p.SystemSetup.install(e),x.SecretSetup.install(e),Q.install(e),e.addPlugin(m.ProviderType,{id:"imaginarium.ui.FilterProvider",sort:50,component:g.FilterProvider}),e.addPlugin(m.ProviderType,{id:"imaginarium.ui.SystemConfigsProvider",sort:40,component:g.SystemConfigsProvider}),e.addPlugin(m.TopBarItemType,L),e.addPlugin(m.TopBarItemType,k),e.addPlugin(m.TopBarItemType,N),console.log("Installing built-in plugin setup!!"),e.addPlugin(m.PageType,{id:"imaginarium.RootRedirect",path:"/",element:()=>(console.log("Redirecting from / to /system-config"),window.location.replace(u.Config.get("ImaginariumApp","rootRedirect","/system-config")),null)})}},X={init(e,o){const n=e??{},r=n.config??{};for(const y of Object.keys(r)){const c=r[y];if(c)for(const d of Object.keys(c))u.Config.set(y,d,c[d])}const f=new Set(n.excludes??[]);f.size>0&&u.Plugins.addMutator((y,c)=>c&&typeof c=="object"&&f.has(c.id??"")?null:c);for(const y of n.mutators??[])u.Plugins.addMutator(y);console.log("Installing built-in plugin setup..."),W.install(u.Plugins),o.install(u.Plugins)},create(){const e=u.Config.get("ImaginariumApp","rootElement","#root"),o=u.Config.get("ImaginariumApp","apiBaseUrl","/api"),n=u.Config.get("ImaginariumApp","title","Imaginarium"),r=typeof e=="string"?document.querySelector(e):e;if(!r)throw new Error(`ImaginariumUI.create: root element not found (${String(e)})`);z.createRoot(r).render(t.jsx(s.ImaginariumApp,{apiBaseUrl:o,title:n}))}};exports.NavItemType=m.NavItemType;exports.PageType=m.PageType;exports.ProviderType=m.ProviderType;exports.TopBarItemType=m.TopBarItemType;exports.addNavItem=w.addNavItem;exports.addPage=w.addPage;exports.addProvider=w.addProvider;exports.getNavItems=w.getNavItems;exports.getPages=w.getPages;exports.getProviders=w.getProviders;exports.AppSidebar=s.AppSidebar;exports.ImaginariumApp=s.ImaginariumApp;exports.LoginPage=s.LoginPage;exports.RequireAuth=s.RequireAuth;exports.Shell=s.Shell;exports.Toast=s.Toast;exports.ToastAction=s.ToastAction;exports.ToastClose=s.ToastClose;exports.ToastDescription=s.ToastDescription;exports.ToastProvider=s.ToastProvider;exports.ToastTitle=s.ToastTitle;exports.ToastViewport=s.ToastViewport;exports.Toaster=s.Toaster;exports.ImagineSystemNavItem=p.ImagineSystemNavItem;exports.ImagineSystemNavItemId=p.ImagineSystemNavItemId;exports.ImagineSystemPage=p.ImagineSystemPage;exports.ImagineSystemPageId=p.ImagineSystemPageId;exports.ImagineSystemView=p.ImagineSystemView;exports.SystemSetup=p.SystemSetup;exports.SystemSetupDefault=p.SystemSetup;exports.TagInput=p.TagInput;exports.FilterProvider=g.FilterProvider;exports.SystemConfigsProvider=g.SystemConfigsProvider;exports.applyConfigFilters=g.applyConfigFilters;exports.isDevConfig=g.isDevConfig;exports.useFilters=g.useFilters;exports.useSystemConfigs=g.useSystemConfigs;exports.Button=i.Button;exports.Card=i.Card;exports.CardContent=i.CardContent;exports.CardDescription=i.CardDescription;exports.CardFooter=i.CardFooter;exports.CardHeader=i.CardHeader;exports.CardTitle=i.CardTitle;exports.ImaginariumApiProvider=i.ImaginariumApiProvider;exports.buttonVariants=i.buttonVariants;exports.cn=i.cn;exports.toast=i.toast;exports.useImaginariumApi=i.useImaginariumApi;exports.useToast=i.useToast;exports.SecretNavItem=x.SecretNavItem;exports.SecretPage=x.SecretPage;exports.SecretSetup=x.SecretSetup;exports.SecretView=x.SecretView;exports.Dialog=l.Dialog;exports.DialogClose=l.DialogClose;exports.DialogContent=l.DialogContent;exports.DialogDescription=l.DialogDescription;exports.DialogFooter=l.DialogFooter;exports.DialogHeader=l.DialogHeader;exports.DialogOverlay=l.DialogOverlay;exports.DialogPortal=l.DialogPortal;exports.DialogTitle=l.DialogTitle;exports.DialogTrigger=l.DialogTrigger;exports.Input=l.Input;exports.Label=l.Label;exports.Tooltip=P.Tooltip;exports.TooltipContent=P.TooltipContent;exports.TooltipProvider=P.TooltipProvider;exports.TooltipTrigger=P.TooltipTrigger;exports.DropdownMenu=R;exports.DropdownMenuCheckboxItem=C;exports.DropdownMenuContent=b;exports.DropdownMenuGroup=E;exports.DropdownMenuItem=v;exports.DropdownMenuLabel=D;exports.DropdownMenuPortal=$;exports.DropdownMenuRadioGroup=Y;exports.DropdownMenuRadioItem=B;exports.DropdownMenuSeparator=T;exports.DropdownMenuShortcut=O;exports.DropdownMenuSub=K;exports.DropdownMenuSubContent=q;exports.DropdownMenuSubTrigger=F;exports.DropdownMenuTrigger=A;exports.ImaginariumUI=X;exports.LogoutItem=N;exports.SystemConfigFilterItem=L;exports.UIModeItem=k;
2
2
  //# sourceMappingURL=index.cjs.map
package/lib/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { a as C, T as y, P as N } from "./PluginTypes-DsLT43Y8.js";
2
2
  import { N as Te } from "./PluginTypes-DsLT43Y8.js";
3
3
  import { a as Ne, b as ve, c as De, g as Pe, d as ke, e as Me } from "./registry-8kQ494RA.js";
4
- import { I as v } from "./ImaginariumApp-DJ0f2GWB.js";
5
- import { A as Ae, L as Fe, R as Le, S as ze, T as Be, a as Oe, b as je, c as Ue, d as Ee, e as qe, f as Ge, g as He } from "./ImaginariumApp-DJ0f2GWB.js";
4
+ import { I as v } from "./ImaginariumApp-Bp1toCAd.js";
5
+ import { A as Ae, L as Fe, R as Le, S as ze, T as Be, a as Oe, b as je, c as Ue, d as Ee, e as qe, f as Ge, g as He } from "./ImaginariumApp-Bp1toCAd.js";
6
6
  import { S as D } from "./PluginSetup-NL8jYfpN.js";
7
7
  import { I as $e, a as _e, b as Ke, c as Ye, d as Je, T as Qe } from "./PluginSetup-NL8jYfpN.js";
8
8
  import { a as P, F as k, S as M } from "./SystemConfigsContext-D0hXRSH-.js";
package/lib/shell.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./ImaginariumApp-B7Vlrxfd.cjs");exports.AppSidebar=e.AppSidebar;exports.ImaginariumApp=e.ImaginariumApp;exports.Shell=e.Shell;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./ImaginariumApp-DpQNMjG_.cjs");exports.AppSidebar=e.AppSidebar;exports.ImaginariumApp=e.ImaginariumApp;exports.Shell=e.Shell;
2
2
  //# sourceMappingURL=shell.cjs.map
package/lib/shell.js CHANGED
@@ -1,4 +1,4 @@
1
- import { A as r, I as e, S as i } from "./ImaginariumApp-DJ0f2GWB.js";
1
+ import { A as r, I as e, S as i } from "./ImaginariumApp-Bp1toCAd.js";
2
2
  export {
3
3
  r as AppSidebar,
4
4
  e as ImaginariumApp,
@@ -61,8 +61,8 @@
61
61
  --popover: 0 0% 14%;
62
62
  --popover-foreground: 0 0% 95%;
63
63
  --popover-border: 0 0% 17%;
64
- --primary: 217 91% 35%;
65
- --primary-foreground: 217 91% 98%;
64
+ --primary: 217 91% 62%;
65
+ --primary-foreground: 217 40% 12%;
66
66
  --secondary: 0 0% 17%;
67
67
  --secondary-foreground: 0 0% 95%;
68
68
  --muted: 0 0% 16%;
@@ -72,7 +72,7 @@
72
72
  --destructive: 0 84% 35%;
73
73
  --destructive-foreground: 0 84% 98%;
74
74
  --input: 0 0% 24%;
75
- --ring: 217 91% 45%;
75
+ --ring: 217 91% 62%;
76
76
 
77
77
  --primary-border: hsl(var(--primary));
78
78
  --primary-border: hsl(from hsl(var(--primary)) h s calc(l + var(--opaque-button-border-intensity)) / alpha);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leverege/imaginarium-ui",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "description": "Reusable UI library and plugin framework for Imaginarium apps",
5
5
  "type": "module",
6
6
  "main": "./lib/index.cjs",
@@ -43,7 +43,7 @@ function GatedShell( { title, titleIcon, navRightSlot, shellFallback, children }
43
43
  children?: ReactNode
44
44
  } ) {
45
45
  return withProviders(
46
- <div className="flex min-h-screen bg-background text-foreground">
46
+ <div className="flex h-screen overflow-hidden bg-background text-foreground">
47
47
  <AppSidebar title={title} titleIcon={titleIcon} rightSlot={navRightSlot} />
48
48
  <Shell fallback={shellFallback}>{children}</Shell>
49
49
  </div>,
@@ -61,8 +61,8 @@
61
61
  --popover: 0 0% 14%;
62
62
  --popover-foreground: 0 0% 95%;
63
63
  --popover-border: 0 0% 17%;
64
- --primary: 217 91% 35%;
65
- --primary-foreground: 217 91% 98%;
64
+ --primary: 217 91% 62%;
65
+ --primary-foreground: 217 40% 12%;
66
66
  --secondary: 0 0% 17%;
67
67
  --secondary-foreground: 0 0% 95%;
68
68
  --muted: 0 0% 16%;
@@ -72,7 +72,7 @@
72
72
  --destructive: 0 84% 35%;
73
73
  --destructive-foreground: 0 84% 98%;
74
74
  --input: 0 0% 24%;
75
- --ring: 217 91% 45%;
75
+ --ring: 217 91% 62%;
76
76
 
77
77
  --primary-border: hsl(var(--primary));
78
78
  --primary-border: hsl(from hsl(var(--primary)) h s calc(l + var(--opaque-button-border-intensity)) / alpha);