@petrarca/sonnet-shell 0.2.0 → 0.4.0

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.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/AppShell.tsx","../src/ConfirmDialog.tsx","../src/TopBar.tsx","../src/IconRail.tsx","../src/shellModules.ts","../src/SubNavPanel.tsx","../src/hooks.ts","../src/api.ts","../src/eventBus.ts","../src/SidePane.tsx","../src/sidePaneState.ts","../src/CommandMenu.tsx","../src/shellConfig.ts","../src/RootLayout.tsx","../src/ShellConfigProvider.tsx","../src/PlaceholderPage.tsx","../src/SearchTrigger.tsx","../src/UserMenu.tsx","../src/createModuleRegistry.ts","../src/OverviewCard.tsx"],"sourcesContent":["import React, {\n useState,\n useEffect,\n useCallback,\n useRef,\n useMemo,\n} from \"react\";\nimport { Outlet, useLocation, useNavigate } from \"react-router-dom\";\nimport { TooltipProvider } from \"@petrarca/sonnet-ui\";\nimport { ScrollArea } from \"@petrarca/sonnet-ui\";\nimport {\n Sheet,\n SheetContent,\n SheetHeader,\n SheetTitle,\n SheetDescription,\n SheetBody,\n} from \"@petrarca/sonnet-ui\";\nimport { ConfirmDialog } from \"./ConfirmDialog\";\nimport TopBar from \"./TopBar\";\nimport IconRail from \"./IconRail\";\nimport SubNavPanel from \"./SubNavPanel\";\nimport SidePane from \"./SidePane\";\nimport CommandMenu from \"./CommandMenu\";\nimport {\n initNavigation,\n initFeatureNav,\n initPanel,\n initDialog,\n initFullscreen,\n initSidePane,\n type PanelOptions,\n type ConfirmOptions,\n type FullscreenOptions,\n} from \"./api\";\nimport type { ModuleRegistry } from \"./createModuleRegistry\";\nimport { ShellModulesContext } from \"./shellModules\";\nimport { useShellConfig } from \"./shellConfig\";\nimport { SidePaneContext, type SidePaneOptions } from \"./sidePaneState\";\nimport type { ServiceModule } from \"./types\";\n\n// Maps PanelOptions.width tokens to Tailwind width classes.\nconst PANEL_WIDTH_CLASS: Record<string, string> = {\n narrow: \"w-[480px]\",\n default: \"w-[640px]\",\n wide: \"w-[800px]\",\n half: \"w-[50vw]\",\n full: \"w-screen\",\n // legacy aliases\n lg: \"w-[640px]\",\n \"1/3\": \"w-[33vw]\",\n \"1/2\": \"w-[50vw]\",\n};\n\n// -- Helpers extracted to reduce AppShell complexity --\n\nfunction isSidePaneModule(service: {\n sidePane?: unknown;\n navigation: unknown[];\n}): boolean {\n return !!service.sidePane && service.navigation.length === 0;\n}\n\nfunction selectSidePaneModule(\n service: {\n id: string;\n basePath: string;\n routes: unknown[];\n sidePane?: {\n defaultWidth?: number;\n minWidth?: number;\n maxWidth?: number;\n contentFactory?: () => React.ReactNode;\n };\n },\n current: SidePaneOptions | null,\n setSidePaneState: (s: SidePaneOptions | null) => void,\n navigate: (path: string) => void,\n): void {\n if (current?.moduleId === service.id) {\n setSidePaneState(null);\n } else {\n setSidePaneState({\n moduleId: service.id,\n content: service.sidePane?.contentFactory?.() ?? null,\n defaultWidth: service.sidePane?.defaultWidth,\n minWidth: service.sidePane?.minWidth,\n maxWidth: service.sidePane?.maxWidth,\n });\n // Only navigate if the module has routes — pane-only modules\n // (routes: []) have no registered path, navigating would 404.\n if (service.routes.length > 0) {\n navigate(service.basePath);\n }\n }\n}\n\nfunction selectNavModule(\n service: {\n basePath: string;\n navigation: Array<{ links: Array<{ path: string }> }>;\n },\n navigate: (path: string) => void,\n setSubNavCollapsed: (v: boolean) => void,\n closeSidePane: () => void,\n): void {\n closeSidePane();\n setSubNavCollapsed(false);\n const target = service.navigation[0]?.links[0]?.path ?? service.basePath;\n navigate(target);\n}\n\n// Wire all imperative shell APIs once on mount.\nfunction useShellApiInit(deps: {\n navigate: ReturnType<typeof useNavigate>;\n openCommandMenu: () => void;\n handlePanelOpen: (opts: PanelOptions) => void;\n handlePanelClose: () => void;\n handleFullscreenEnter: (opts: FullscreenOptions) => void;\n handleFullscreenExit: () => void;\n handleSidePaneOpen: (opts: SidePaneOptions) => void;\n handleSidePaneClose: () => void;\n handleSidePaneIsOpen: () => boolean;\n handleSidePaneActiveModuleId: () => string | null;\n handleSidePaneSetFullWidth: (fullWidth: boolean) => void;\n setDialogState: React.Dispatch<React.SetStateAction<DialogState | null>>;\n featureLookup: (featureId: string) => string | null;\n}) {\n const stableRefs = useRef(deps);\n useEffect(() => {\n const r = stableRefs.current;\n initNavigation(r.navigate, r.openCommandMenu);\n initFeatureNav(r.featureLookup);\n initPanel(r.handlePanelOpen, r.handlePanelClose);\n initFullscreen(r.handleFullscreenEnter, r.handleFullscreenExit);\n initSidePane(\n r.handleSidePaneOpen,\n r.handleSidePaneClose,\n r.handleSidePaneIsOpen,\n r.handleSidePaneActiveModuleId,\n r.handleSidePaneSetFullWidth,\n );\n initDialog(\n (opts: ConfirmOptions) =>\n new Promise<boolean>((resolve) => r.setDialogState({ opts, resolve })),\n );\n }, []);\n}\n\ninterface AppShellProps {\n registry: ModuleRegistry;\n}\n\ninterface DialogState {\n opts: ConfirmOptions;\n resolve: (confirmed: boolean) => void;\n}\n\n/**\n * AppShell -- the main layout skeleton.\n *\n * Owns the panel (slide-over) -- modules request it via panel.open(),\n * the shell renders the provided content inside a Sheet.\n *\n * Receives its module registry as a prop so it has no dependency on\n * app-specific module lists.\n */\n// Hook: track which service is active based on URL.\nfunction useActiveService(modules: ModuleRegistry[\"modules\"]) {\n const location = useLocation();\n const serviceByBasePath = useMemo(\n () =>\n new Map(\n modules\n .filter((m) => !m.hidden && m.basePath !== \"/\")\n .map((m) => [m.basePath, m.id]),\n ),\n [modules],\n );\n const resolveServiceFromPath = useCallback(\n (pathname: string): string | null => {\n for (const [basePath, id] of serviceByBasePath) {\n if (pathname.startsWith(basePath)) return id;\n }\n return null;\n },\n [serviceByBasePath],\n );\n const [selectedServiceId, setSelectedServiceId] = useState<string | null>(\n () => resolveServiceFromPath(location.pathname),\n );\n useEffect(\n () => setSelectedServiceId(resolveServiceFromPath(location.pathname)),\n [location.pathname, resolveServiceFromPath],\n );\n const activeService = selectedServiceId\n ? (modules.find((s) => s.id === selectedServiceId) ?? null)\n : null;\n return { activeService, selectedServiceId, setSelectedServiceId };\n}\n\n// Hook: side pane state and handlers.\nfunction useSidePaneState() {\n const [sidePaneState, setSidePaneState] = useState<SidePaneOptions | null>(\n null,\n );\n const handleOpen = useCallback(\n (opts: SidePaneOptions) => setSidePaneState(opts),\n [],\n );\n const handleClose = useCallback(() => setSidePaneState(null), []);\n const handleIsOpen = useCallback(\n () => sidePaneState !== null,\n [sidePaneState],\n );\n const handleActiveModuleId = useCallback(\n () => sidePaneState?.moduleId ?? null,\n [sidePaneState],\n );\n const handleSetFullWidth = useCallback((fullWidth: boolean) => {\n setSidePaneState((prev) => (prev ? { ...prev, fullWidth } : prev));\n }, []);\n return {\n sidePaneState,\n setSidePaneState,\n handleOpen,\n handleClose,\n handleIsOpen,\n handleActiveModuleId,\n handleSetFullWidth,\n };\n}\n\n// Hook: slide-over panel state and handlers.\nfunction usePanelState() {\n const [panelState, setPanelState] = useState<PanelOptions | null>(null);\n const panelOnCloseRef = useRef<(() => void) | undefined>(undefined);\n const handleOpen = useCallback(\n (opts: PanelOptions) => setPanelState(opts),\n [],\n );\n const handleClose = useCallback(() => {\n panelOnCloseRef.current = panelState?.onClose;\n setPanelState(null);\n }, [panelState]);\n const panelWidth =\n PANEL_WIDTH_CLASS[panelState?.width ?? \"default\"] ??\n PANEL_WIDTH_CLASS.default;\n const panelOffsetTop = panelState?.coverage === \"full\" ? \"0px\" : \"3rem\";\n return {\n panelState,\n panelOnCloseRef,\n handleOpen,\n handleClose,\n panelWidth,\n panelOffsetTop,\n };\n}\n\n// Hook: confirm dialog state and handlers.\nfunction useDialogState() {\n const [dialogState, setDialogState] = useState<DialogState | null>(null);\n const handleConfirm = useCallback(() => {\n dialogState?.resolve(true);\n setDialogState(null);\n }, [dialogState]);\n const handleCancel = useCallback(() => {\n dialogState?.resolve(false);\n setDialogState(null);\n }, [dialogState]);\n return { dialogState, setDialogState, handleConfirm, handleCancel };\n}\n\n// Build a stable feature id -> path lookup from the module registry.\nfunction useFeatureLookup(modules: ModuleRegistry[\"modules\"]) {\n return useMemo(() => {\n const map = new Map<string, string>();\n for (const m of modules) {\n for (const group of m.navigation) {\n for (const link of group.links) {\n if (link.id) map.set(link.id, link.path);\n }\n }\n }\n return (featureId: string) => map.get(featureId) ?? null;\n }, [modules]);\n}\n\nexport default function AppShell({ registry }: AppShellProps) {\n const navigate = useNavigate();\n const config = useShellConfig();\n const { modules } = registry;\n\n const { activeService, setSelectedServiceId } = useActiveService(modules);\n const [subNavCollapsed, setSubNavCollapsed] = useState(false);\n const [commandMenuOpen, setCommandMenuOpen] = useState(false);\n const openCommandMenu = useCallback(() => setCommandMenuOpen(true), []);\n const [fullscreenState, setFullscreenState] =\n useState<FullscreenOptions | null>(null);\n const handleFullscreenEnter = useCallback(\n (opts: FullscreenOptions) => setFullscreenState(opts),\n [],\n );\n const handleFullscreenExit = useCallback(() => setFullscreenState(null), []);\n\n const sidePane = useSidePaneState();\n const panel = usePanelState();\n const dialog = useDialogState();\n const featureLookup = useFeatureLookup(modules);\n\n useShellApiInit({\n navigate,\n openCommandMenu,\n handlePanelOpen: panel.handleOpen,\n handlePanelClose: panel.handleClose,\n handleFullscreenEnter,\n handleFullscreenExit,\n handleSidePaneOpen: sidePane.handleOpen,\n handleSidePaneClose: sidePane.handleClose,\n handleSidePaneIsOpen: sidePane.handleIsOpen,\n handleSidePaneActiveModuleId: sidePane.handleActiveModuleId,\n handleSidePaneSetFullWidth: sidePane.handleSetFullWidth,\n setDialogState: dialog.setDialogState,\n featureLookup,\n });\n\n const handleServiceSelect = useCallback(\n (serviceId: string) => {\n const service = modules.find((s) => s.id === serviceId);\n if (!service) return;\n if (isSidePaneModule(service)) {\n selectSidePaneModule(\n service,\n sidePane.sidePaneState,\n sidePane.setSidePaneState,\n navigate,\n );\n // Don't change activeService for pane-only modules — the content\n // area still shows the previous route and needs its layout mode.\n // Collapse SubNavPanel by default so it doesn't linger from a nav module.\n // Consumers can opt out via sidePane.collapseSubNav: false.\n if (service.sidePane?.collapseSubNav !== false) {\n setSubNavCollapsed(true);\n }\n } else {\n selectNavModule(\n service,\n navigate,\n setSubNavCollapsed,\n sidePane.handleClose,\n );\n setSelectedServiceId(serviceId);\n }\n },\n [\n modules,\n sidePane.sidePaneState,\n sidePane.setSidePaneState,\n sidePane.handleClose,\n navigate,\n setSelectedServiceId,\n setSubNavCollapsed,\n ],\n );\n\n const sidePaneContextValue = useMemo(\n () => ({\n pane: sidePane.sidePaneState,\n open: sidePane.handleOpen,\n close: sidePane.handleClose,\n toggle: (opts: SidePaneOptions) => {\n if (sidePane.sidePaneState?.moduleId === opts.moduleId) {\n sidePane.setSidePaneState(null);\n } else {\n sidePane.setSidePaneState(opts);\n }\n },\n setFullWidth: sidePane.handleSetFullWidth,\n }),\n [sidePane],\n );\n\n return (\n <ShellModulesContext.Provider value={registry}>\n <SidePaneContext.Provider value={sidePaneContextValue}>\n <TooltipProvider>\n <div className=\"flex h-screen w-screen flex-col overflow-hidden\">\n {/* TopBar */}\n <TopBar>{config.topBar}</TopBar>\n\n {/* CommandMenu (Cmd+K) */}\n <CommandMenu\n open={commandMenuOpen}\n onOpenChange={setCommandMenuOpen}\n />\n\n {/* Body: IconRail + SubNavPanel + SidePane + Content Area */}\n <ShellBody\n activeService={activeService}\n sidePaneFullWidth={sidePane.sidePaneState?.fullWidth}\n sidePaneModuleId={sidePane.sidePaneState?.moduleId ?? null}\n subNavCollapsed={subNavCollapsed}\n onToggleSubNav={() => setSubNavCollapsed((c) => !c)}\n onServiceSelect={handleServiceSelect}\n />\n\n {/* Confirm Dialog */}\n {dialog.dialogState && (\n <ConfirmDialog\n open={true}\n title={dialog.dialogState.opts.title}\n description={dialog.dialogState.opts.description}\n confirmLabel={dialog.dialogState.opts.confirmLabel}\n cancelLabel={dialog.dialogState.opts.cancelLabel}\n variant={dialog.dialogState.opts.variant}\n onConfirm={dialog.handleConfirm}\n onCancel={dialog.handleCancel}\n />\n )}\n\n {/* Fullscreen overlay -- covers all shell chrome */}\n {fullscreenState && (\n <div className=\"fixed inset-0 z-50 bg-background overflow-auto\">\n {fullscreenState.content}\n </div>\n )}\n\n {/* Slide-over Panel */}\n <SlideOverPanel\n panelState={panel.panelState}\n panelWidth={panel.panelWidth}\n panelOffsetTop={panel.panelOffsetTop}\n panelOnCloseRef={panel.panelOnCloseRef}\n onClose={panel.handleClose}\n />\n </div>\n </TooltipProvider>\n </SidePaneContext.Provider>\n </ShellModulesContext.Provider>\n );\n}\n\n// -- Sub-components extracted to reduce AppShell complexity --\n\ninterface SlideOverPanelProps {\n panelState: PanelOptions | null;\n panelWidth: string;\n panelOffsetTop: string;\n panelOnCloseRef: React.MutableRefObject<(() => void) | undefined>;\n onClose: () => void;\n}\n\nfunction SlideOverPanel({\n panelState,\n panelWidth,\n panelOffsetTop,\n panelOnCloseRef,\n onClose,\n}: SlideOverPanelProps) {\n return (\n <Sheet\n open={panelState !== null}\n onOpenChange={(open) => {\n if (!open) onClose();\n }}\n >\n <SheetContent\n side=\"right\"\n className={`${panelWidth} max-w-[90vw]`}\n offsetTop={panelOffsetTop}\n onCloseAutoFocus={(e) => {\n if (panelOnCloseRef.current) {\n e.preventDefault();\n panelOnCloseRef.current();\n }\n }}\n {...(!panelState?.description && {\n \"aria-describedby\": undefined,\n })}\n >\n {panelState && <PanelContent state={panelState} />}\n </SheetContent>\n </Sheet>\n );\n}\n\nfunction ShellBody({\n activeService,\n sidePaneFullWidth,\n sidePaneModuleId,\n subNavCollapsed,\n onToggleSubNav,\n onServiceSelect,\n}: {\n activeService: ServiceModule | null;\n sidePaneFullWidth?: boolean;\n sidePaneModuleId: string | null;\n subNavCollapsed: boolean;\n onToggleSubNav: () => void;\n onServiceSelect: (id: string) => void;\n}) {\n return (\n <div className=\"flex flex-1 overflow-hidden\">\n <IconRail\n activeServiceId={activeService?.id ?? null}\n activeSidePaneModuleId={sidePaneModuleId}\n onServiceSelect={onServiceSelect}\n />\n\n {activeService && activeService.navigation.length > 0 && (\n <SubNavPanel\n service={activeService}\n collapsed={subNavCollapsed}\n onToggleCollapse={onToggleSubNav}\n />\n )}\n\n <SidePane />\n\n {sidePaneFullWidth !== true && (\n <div className=\"flex-1 min-w-0 h-full overflow-hidden\">\n <ContentArea layout={activeService?.layout} />\n </div>\n )}\n </div>\n );\n}\n\nfunction ContentArea({ layout }: { layout?: \"default\" | \"full\" }) {\n if (layout === \"full\") {\n return (\n <div className=\"h-full w-full overflow-hidden\">\n <Outlet />\n </div>\n );\n }\n return (\n <ScrollArea className=\"h-full\">\n <main className=\"p-6\">\n <Outlet />\n </main>\n </ScrollArea>\n );\n}\n\nfunction PanelContent({ state }: { state: PanelOptions }) {\n return (\n <>\n {state.title ? (\n <SheetHeader>\n <SheetTitle>{state.title}</SheetTitle>\n {state.description && (\n <SheetDescription>{state.description}</SheetDescription>\n )}\n </SheetHeader>\n ) : (\n <SheetTitle className=\"sr-only\">Panel</SheetTitle>\n )}\n <SheetBody>{state.content}</SheetBody>\n </>\n );\n}\n","/**\n * Confirm Dialog\n *\n * Reusable confirmation dialog for actions that require user confirmation.\n * Used for discard changes, delete actions, etc.\n *\n * Wired into the shell via `initDialog` in `shell/api.ts` so modules can\n * trigger it imperatively with `dialog.confirm(opts)`.\n *\n * @module components/Common/ConfirmDialog\n */\n\nimport React from \"react\";\nimport { AlertTriangle } from \"lucide-react\";\nimport { Button } from \"@petrarca/sonnet-ui\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from \"@petrarca/sonnet-ui\";\n\nexport interface ConfirmDialogProps {\n /** Whether the dialog is open */\n open: boolean;\n\n /** Dialog title */\n title: string;\n\n /** Description shown below the title */\n description?: string;\n\n /** Confirm button label (default: \"Confirm\") */\n confirmLabel?: string;\n\n /** Cancel button label (default: \"Cancel\") */\n cancelLabel?: string;\n\n /**\n * Controls confirm button appearance.\n * \"destructive\" for irreversible actions (delete, revoke, etc.)\n */\n variant?: \"default\" | \"destructive\";\n\n /** Callback when user confirms */\n onConfirm: () => void;\n\n /** Callback when user cancels or closes dialog */\n onCancel: () => void;\n}\n\n/**\n * ConfirmDialog Component\n *\n * A reusable confirmation dialog backed by shadcn Dialog primitives.\n */\nexport function ConfirmDialog({\n open,\n title,\n description,\n confirmLabel = \"Confirm\",\n cancelLabel = \"Cancel\",\n variant = \"default\",\n onConfirm,\n onCancel,\n}: ConfirmDialogProps): React.ReactElement {\n return (\n <Dialog open={open} onOpenChange={(isOpen) => !isOpen && onCancel()}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>{title}</DialogTitle>\n {description && <DialogDescription>{description}</DialogDescription>}\n </DialogHeader>\n\n {variant === \"destructive\" && (\n <div className=\"flex gap-2 items-start\">\n <AlertTriangle\n size={20}\n className=\"text-destructive flex-shrink-0 mt-0.5\"\n />\n <p className=\"flex-1 text-sm text-muted-foreground\">\n This action cannot be undone.\n </p>\n </div>\n )}\n\n <DialogFooter>\n <Button variant=\"outline\" onClick={onCancel}>\n {cancelLabel}\n </Button>\n <Button variant={variant} onClick={onConfirm}>\n {confirmLabel}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n","import type { ReactNode } from \"react\";\n\n/**\n * TopBar -- persistent header across the entire application.\n *\n * A pure layout container. The shell provides the `<header>` element with\n * its sizing, background, and border. The consumer owns all content via\n * the `children` prop (composed through `ShellConfig.topBar`).\n */\ninterface TopBarProps {\n children?: ReactNode;\n}\n\nexport default function TopBar({ children }: TopBarProps) {\n return (\n <header className=\"h-12 shrink-0 border-b border-border flex items-center justify-between px-3 bg-background z-20\">\n {children}\n </header>\n );\n}\n","import { cn } from \"@petrarca/sonnet-core\";\nimport { Button } from \"@petrarca/sonnet-ui\";\nimport { Separator } from \"@petrarca/sonnet-ui\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"@petrarca/sonnet-ui\";\nimport { useShellModules } from \"./shellModules\";\nimport type { ServiceModule } from \"./types\";\n\ninterface IconRailProps {\n activeServiceId: string | null;\n /** moduleId of the module whose side pane is currently open, or null. */\n activeSidePaneModuleId: string | null;\n onServiceSelect: (serviceId: string) => void;\n}\n\n/**\n * IconRail -- narrow vertical bar with service domain icons.\n *\n * Main services scroll in the center, settings/playground pinned at bottom.\n * Tooltips show service labels on hover.\n */\nexport default function IconRail({\n activeServiceId,\n activeSidePaneModuleId,\n onServiceSelect,\n}: IconRailProps) {\n const { mainModules, bottomModules } = useShellModules();\n\n const isActive = (id: string) =>\n activeServiceId === id || activeSidePaneModuleId === id;\n\n return (\n <nav className=\"w-14 shrink-0 border-r bg-muted flex flex-col items-center py-2 gap-1\">\n {/* Main service icons */}\n <div className=\"flex-1 flex flex-col items-center gap-1 overflow-y-auto\">\n {mainModules.map((service) => (\n <RailIcon\n key={service.id}\n service={service}\n isActive={isActive(service.id)}\n onClick={() => onServiceSelect(service.id)}\n />\n ))}\n </div>\n\n {/* Bottom-pinned icons */}\n <Separator className=\"w-6 my-1\" />\n <div className=\"flex flex-col items-center gap-1\">\n {bottomModules.map((service) => (\n <RailIcon\n key={service.id}\n service={service}\n isActive={isActive(service.id)}\n onClick={() => onServiceSelect(service.id)}\n />\n ))}\n </div>\n </nav>\n );\n}\n\n// Single rail icon button\n\ninterface RailIconProps {\n service: ServiceModule;\n isActive: boolean;\n onClick: () => void;\n}\n\nfunction RailIcon({ service, isActive, onClick }: RailIconProps) {\n const Icon = service.icon;\n\n return (\n <Tooltip delayDuration={0}>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"compact\"\n onClick={onClick}\n className={cn(\n \"h-10 w-10 rounded-lg transition-colors\",\n isActive\n ? \"bg-accent text-accent-foreground\"\n : \"text-muted-foreground hover:text-foreground\",\n )}\n >\n <Icon className=\"h-5 w-5\" />\n <span className=\"sr-only\">{service.label}</span>\n </Button>\n </TooltipTrigger>\n <TooltipContent side=\"right\" sideOffset={8}>\n {service.label}\n </TooltipContent>\n </Tooltip>\n );\n}\n","/**\n * Shell modules context.\n *\n * Provides the module registry to shell components (IconRail,\n * CommandMenu, hooks) without requiring them to import from the\n * app-specific modules/registry.ts. AppShell injects the registry;\n * children consume it via useShellModules().\n */\nimport { createContext, useContext } from \"react\";\nimport type { ModuleRegistry } from \"./createModuleRegistry\";\n\nexport const ShellModulesContext = createContext<ModuleRegistry | null>(null);\n\n/**\n * Read the module registry from context.\n * Must be called within an AppShell (which provides the context).\n */\nexport function useShellModules(): ModuleRegistry {\n const registry = useContext(ShellModulesContext);\n if (!registry) {\n throw new Error(\"useShellModules must be used within an AppShell\");\n }\n return registry;\n}\n","import { useMemo } from \"react\";\nimport { useLocation, Link } from \"react-router-dom\";\nimport { ChevronsLeft, ChevronsRight } from \"lucide-react\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport { ScrollArea } from \"@petrarca/sonnet-ui\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"@petrarca/sonnet-ui\";\nimport type { ServiceModule, NavGroup } from \"./types\";\nimport { useExtensionPoint } from \"./hooks\";\n\ninterface SubNavPanelProps {\n service: ServiceModule;\n collapsed: boolean;\n onToggleCollapse: () => void;\n}\n\n/**\n * Merge contributed nav links from other modules.\n *\n * Contributions targeting \"<moduleId>.nav\" are appended as an additional\n * nav group after the module's own groups, sorted by contribution order.\n * The contribution mechanism is pre-sorted by createModuleRegistry.\n */\nfunction useMergedNavigation(service: ServiceModule): NavGroup[] {\n const contributions = useExtensionPoint(`${service.id}.nav`);\n return useMemo(() => {\n if (contributions.length === 0) return service.navigation;\n\n const contributed: NavGroup = {\n id: `${service.id}-contributed`,\n links: contributions.map((c) => ({\n id: c.extensionPoint + \".\" + c.label.toLowerCase().replace(/\\s+/g, \"-\"),\n label: c.label,\n path: c.path,\n })),\n };\n\n return [...service.navigation, contributed];\n }, [service, contributions]);\n}\n\n/**\n * SubNavPanel -- contextual secondary navigation for the selected service domain.\n *\n * Shows the service label at top, then grouped nav links. If other modules\n * contribute links via the \"<moduleId>.nav\" extension point, they are\n * appended as an additional group.\n */\nexport default function SubNavPanel({\n service,\n collapsed,\n onToggleCollapse,\n}: SubNavPanelProps) {\n const { pathname } = useLocation();\n const mergedNavigation = useMergedNavigation(service);\n\n if (collapsed) {\n return (\n <aside className=\"shrink-0 border-r bg-background flex flex-col items-center pt-2.5\">\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n className=\"text-muted-foreground/50 hover:text-muted-foreground transition-colors p-1\"\n onClick={onToggleCollapse}\n >\n <ChevronsRight className=\"h-4 w-4\" />\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"right\">Expand navigation</TooltipContent>\n </Tooltip>\n </aside>\n );\n }\n\n return (\n <aside className=\"w-52 shrink-0 border-r bg-background flex flex-col\">\n {/* Service header with collapse toggle */}\n <div className=\"h-10 shrink-0 flex items-center justify-between px-4\">\n <span className=\"text-xs font-medium text-muted-foreground uppercase tracking-wider\">\n {service.label}\n </span>\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n className=\"text-muted-foreground/40 hover:text-muted-foreground transition-colors p-0.5\"\n onClick={onToggleCollapse}\n >\n <ChevronsLeft className=\"h-3.5 w-3.5\" />\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"right\">Collapse navigation</TooltipContent>\n </Tooltip>\n </div>\n\n {/* Nav groups */}\n <ScrollArea className=\"flex-1\">\n <nav className=\"px-2 pb-4\">\n {mergedNavigation.map((group, gi) => (\n <div key={group.id} className={cn(gi > 0 && \"mt-4\")}>\n {/* heading-meta style: mono uppercase metadata label */}\n {group.heading && (\n <h6 className=\"text-xs font-medium font-mono uppercase tracking-wider text-muted-foreground px-2 mb-1\">\n {group.heading}\n </h6>\n )}\n <ul className=\"space-y-0.5\">\n {group.links.map((link) => {\n const isActive = pathname === link.path;\n return (\n <li key={link.path}>\n <Link\n to={link.path}\n className={cn(\n \"flex items-center rounded-md px-2 py-1.5 text-sm transition-colors\",\n isActive\n ? \"bg-accent text-accent-foreground font-medium\"\n : \"text-muted-foreground hover:text-foreground hover:bg-accent/50\",\n )}\n >\n {link.label}\n </Link>\n </li>\n );\n })}\n </ul>\n </div>\n ))}\n </nav>\n </ScrollArea>\n </aside>\n );\n}\n","/**\n * Shell hooks -- reactive APIs for modules.\n *\n * Import path: @/shell/hooks\n */\nimport { useEffect, useMemo, useRef } from \"react\";\nimport { events } from \"./api\";\nimport { useShellModules } from \"./shellModules\";\nimport type { Contribution, ServiceModule, ShellEventMap } from \"./types\";\n\n/**\n * Get sorted contributions for a named extension point.\n *\n * Returns all contributions registered by any module for the given\n * extension point, sorted by `order` (ascending).\n *\n * @example\n * ```tsx\n * const tabs = useExtensionPoint(\"organization-detail\");\n * ```\n */\nexport function useExtensionPoint(name: string): Contribution[] {\n const { getExtensionPoint } = useShellModules();\n return useMemo(() => getExtensionPoint(name), [getExtensionPoint, name]);\n}\n\n/**\n * Get the list of visible service modules (excludes hidden and bottom-pinned).\n *\n * Useful for building overviews like the home page.\n */\nexport function useMainModules(): ServiceModule[] {\n const { mainModules } = useShellModules();\n return mainModules;\n}\n\n/**\n * Subscribe to a shell event, auto-unsubscribing on unmount.\n *\n * The handler reference is stabilized via useRef so that the\n * subscription is not torn down and recreated on every render.\n *\n * @example\n * ```tsx\n * useShellEvent(\"schema-definition:changed\", (payload) => {\n * queryClient.invalidateQueries({ queryKey: [\"my-key\"] });\n * });\n * ```\n */\nexport function useShellEvent<K extends keyof ShellEventMap>(\n key: K,\n handler: (payload: ShellEventMap[K]) => void,\n): void {\n const handlerRef = useRef(handler);\n handlerRef.current = handler;\n\n useEffect(() => {\n return events.on(key, (payload) => handlerRef.current(payload));\n }, [key]);\n}\n","/**\n * Shell API -- imperative domain capabilities for modules.\n *\n * Import path: @/shell/api\n *\n * Grouped by domain: notification, dialog, navigation, panel, events.\n */\nimport type { ReactNode } from \"react\";\nimport { toast } from \"sonner\";\nimport { warnLog } from \"@petrarca/sonnet-core\";\nimport type { ShellEventMap } from \"./types\";\nimport * as eventBus from \"./eventBus\";\n\n// notification\n\ninterface PromiseOptions<T> {\n loading: string;\n success: string | ((data: T) => string);\n error: string | ((err: unknown) => string);\n}\n\nexport const notification = {\n success(message: string) {\n toast.success(message);\n },\n error(message: string) {\n toast.error(message);\n },\n warning(message: string) {\n toast.warning(message);\n },\n info(message: string) {\n toast.info(message);\n },\n promise<T>(promise: Promise<T>, opts: PromiseOptions<T>) {\n return toast.promise(promise, opts);\n },\n dismiss(id?: string | number) {\n toast.dismiss(id);\n },\n};\n\n// dialog\n\n// The shell mounts a single ConfirmDialog instance in AppShell and injects\n// its open function here via initDialog(). Modules call dialog.confirm()\n// without knowing where the implementation lives -- federation-safe, same\n// pattern as navigation and panel.\n\nexport interface ConfirmOptions {\n title: string;\n description?: string;\n confirmLabel?: string;\n cancelLabel?: string;\n variant?: \"default\" | \"destructive\";\n}\n\ntype DialogConfirmFn = (opts: ConfirmOptions) => Promise<boolean>;\n\nlet _dialogConfirm: DialogConfirmFn | null = null;\n\n/**\n * Called by the shell during initialization to inject the confirm dialog.\n * Not part of the public module API -- only the shell calls this.\n */\nexport function initDialog(confirmFn: DialogConfirmFn) {\n _dialogConfirm = confirmFn;\n}\n\nexport const dialog = {\n /**\n * Show a confirmation dialog. Returns true if confirmed, false if cancelled.\n */\n confirm(opts: ConfirmOptions): Promise<boolean> {\n if (_dialogConfirm) {\n return _dialogConfirm(opts);\n }\n warnLog(\"dialog.confirm: shell not initialized yet.\");\n return Promise.resolve(false);\n },\n};\n\n// navigation\n\n// The shell injects the navigate function and command menu opener at startup\n// via initNavigation(). Modules call navigation.goTo() etc. without knowing\n// where the implementation comes from -- works with both monorepo and\n// Module Federation (host provides the injector, remotes consume the API).\n\ntype NavigateFn = (path: string) => void;\ntype CommandMenuFn = () => void;\ntype FeatureLookupFn = (featureId: string) => string | null;\n\nlet _navigate: NavigateFn | null = null;\nlet _openCommandMenu: CommandMenuFn | null = null;\nlet _lookupFeature: FeatureLookupFn | null = null;\n\n/**\n * Called by the shell during initialization to inject router + command menu.\n * Not part of the public module API -- only the shell calls this.\n */\nexport function initNavigation(\n navigateFn: NavigateFn,\n openCommandMenuFn: CommandMenuFn,\n) {\n _navigate = navigateFn;\n _openCommandMenu = openCommandMenuFn;\n}\n\n/**\n * Called by the shell during initialization to inject the feature lookup.\n * Resolves a stable feature id (e.g. \"auditing.audit-events\") to a path.\n * Not part of the public module API -- only the shell calls this.\n */\nexport function initFeatureNav(lookupFn: FeatureLookupFn) {\n _lookupFeature = lookupFn;\n}\n\nexport const navigation = {\n /** Navigate to a path within the shell. */\n goTo(path: string) {\n if (_navigate) {\n _navigate(path);\n } else {\n warnLog(\"navigation.goTo: shell not initialized yet.\");\n }\n },\n /**\n * Navigate to a feature by its stable identifier (e.g. \"auditing.audit-events\").\n * The path is resolved from the module registry at call time, so it stays\n * correct even if routes are reorganised.\n */\n goToFeature(featureId: string) {\n if (!_navigate || !_lookupFeature) {\n warnLog(\"navigation.goToFeature: shell not initialized yet.\");\n return;\n }\n const path = _lookupFeature(featureId);\n if (path) {\n _navigate(path);\n } else {\n warnLog(\"navigation.goToFeature: unknown feature id '{}'.\", featureId);\n }\n },\n /** Open the Cmd+K command menu. */\n openCommandMenu() {\n if (_openCommandMenu) {\n _openCommandMenu();\n } else {\n warnLog(\"navigation.openCommandMenu: shell not initialized yet.\");\n }\n },\n /** Go back in browser history. */\n back() {\n window.history.back();\n },\n};\n\n// panel\n\n// The shell owns the slide-over panel (Sheet). Modules request it via\n// panel.open() with content to render. The shell renders that content inside\n// the panel. Same injection pattern as navigation -- federation-safe.\n\nexport interface PanelOptions {\n /**\n * Title shown in the panel header. When omitted the header is visually\n * hidden (the content owns its own header) but a screen-reader-only\n * title is still rendered for accessibility.\n */\n title?: string;\n /** React content to render inside the panel */\n content: ReactNode;\n /** Optional description below the title */\n description?: string;\n /**\n * Panel width token.\n *\n * - \"narrow\" -- 480px -- quick actions, simple single-field forms\n * - \"default\" -- 640px -- standard entity forms (default when omitted)\n * - \"wide\" -- 800px -- forms with embedded tables or complex layouts\n * - \"half\" -- 50vw -- split-screen inspection, side-by-side context\n * - \"full\" -- 100vw -- immersive editing, full-width canvases\n *\n * Legacy values \"lg\", \"1/3\", \"1/2\" are kept for backward compatibility\n * and map to \"default\" (640px), 33vw, and \"half\" (50vw) respectively.\n */\n width?:\n | \"narrow\"\n | \"default\"\n | \"wide\"\n | \"half\"\n | \"full\"\n | \"lg\"\n | \"1/3\"\n | \"1/2\";\n /**\n * Vertical coverage of the panel.\n * - \"below-header\" (default): panel starts below the TopBar, keeping it visible.\n * - \"full\": panel covers the full viewport height including the TopBar.\n */\n coverage?: \"below-header\" | \"full\";\n /** Called after the panel finishes closing. Use to restore focus to the triggering element. */\n onClose?: () => void;\n}\n\ntype PanelOpenFn = (opts: PanelOptions) => void;\ntype PanelCloseFn = () => void;\n\nlet _panelOpen: PanelOpenFn | null = null;\nlet _panelClose: PanelCloseFn | null = null;\n\n/**\n * Called by the shell during initialization to inject panel controls.\n * Not part of the public module API -- only the shell calls this.\n */\nexport function initPanel(openFn: PanelOpenFn, closeFn: PanelCloseFn) {\n _panelOpen = openFn;\n _panelClose = closeFn;\n}\n\nexport const panel = {\n /** Open the shell panel with content rendered inside. */\n open(opts: PanelOptions) {\n if (_panelOpen) {\n _panelOpen(opts);\n } else {\n warnLog(\"panel.open: shell not initialized yet.\");\n }\n },\n /** Close the panel. */\n close() {\n if (_panelClose) {\n _panelClose();\n } else {\n warnLog(\"panel.close: shell not initialized yet.\");\n }\n },\n};\n\n// sidePane\n\n// The shell owns the side pane (SidePane component in AppShell). Modules\n// request it via sidePane.open() with content and sizing options. The pane\n// sits inline beside the content area -- the main view shrinks rather than\n// being overlaid. Same injection pattern as panel -- federation-safe.\n\nimport type { SidePaneOptions } from \"./sidePaneState\";\nexport type { SidePaneOptions };\n\ntype SidePaneOpenFn = (opts: SidePaneOptions) => void;\ntype SidePaneCloseFn = () => void;\ntype SidePaneIsOpenFn = () => boolean;\ntype SidePaneActiveModuleIdFn = () => string | null;\ntype SidePaneSetFullWidthFn = (fullWidth: boolean) => void;\n\nlet _sidePaneOpen: SidePaneOpenFn | null = null;\nlet _sidePaneClose: SidePaneCloseFn | null = null;\nlet _sidePaneIsOpen: SidePaneIsOpenFn | null = null;\nlet _sidePaneActiveModuleId: SidePaneActiveModuleIdFn | null = null;\nlet _sidePaneSetFullWidth: SidePaneSetFullWidthFn | null = null;\n\n/**\n * Called by the shell during initialization to inject side pane controls.\n * Not part of the public module API -- only the shell calls this.\n */\nexport function initSidePane(\n openFn: SidePaneOpenFn,\n closeFn: SidePaneCloseFn,\n isOpenFn: SidePaneIsOpenFn,\n activeModuleIdFn: SidePaneActiveModuleIdFn,\n setFullWidthFn?: SidePaneSetFullWidthFn,\n) {\n _sidePaneOpen = openFn;\n _sidePaneClose = closeFn;\n _sidePaneIsOpen = isOpenFn;\n _sidePaneActiveModuleId = activeModuleIdFn;\n _sidePaneSetFullWidth = setFullWidthFn ?? null;\n}\n\nexport const sidePane = {\n /** Open the side pane with the given content and sizing options. */\n open(opts: SidePaneOptions) {\n if (_sidePaneOpen) {\n _sidePaneOpen(opts);\n } else {\n warnLog(\"sidePane.open: shell not initialized yet.\");\n }\n },\n /** Close the side pane. */\n close() {\n if (_sidePaneClose) {\n _sidePaneClose();\n } else {\n warnLog(\"sidePane.close: shell not initialized yet.\");\n }\n },\n /**\n * Toggle the side pane.\n *\n * If the pane is closed, opens it with opts.\n * If the pane is open with the same moduleId, closes it.\n * If the pane is open with a different moduleId, replaces it with opts.\n */\n toggle(opts: SidePaneOptions) {\n if (\n !_sidePaneIsOpen ||\n !_sidePaneActiveModuleId ||\n !_sidePaneOpen ||\n !_sidePaneClose\n ) {\n warnLog(\"sidePane.toggle: shell not initialized yet.\");\n return;\n }\n if (_sidePaneIsOpen() && _sidePaneActiveModuleId() === opts.moduleId) {\n _sidePaneClose();\n } else {\n _sidePaneOpen(opts);\n }\n },\n /** Returns true when the pane is currently open. */\n isOpen(): boolean {\n return _sidePaneIsOpen ? _sidePaneIsOpen() : false;\n },\n /** Returns the moduleId of the currently open pane, or null. */\n activeModuleId(): string | null {\n return _sidePaneActiveModuleId ? _sidePaneActiveModuleId() : null;\n },\n /**\n * Expand or collapse the pane to fill the full content area.\n *\n * When true the pane takes flex-1 and hides the main route content.\n * Use for full-screen tool views (schema viewer, form editors).\n * Call setFullWidth(false) to restore normal inline sizing.\n */\n setFullWidth(fullWidth: boolean) {\n if (_sidePaneSetFullWidth) {\n _sidePaneSetFullWidth(fullWidth);\n } else {\n warnLog(\"sidePane.setFullWidth: shell not initialized yet.\");\n }\n },\n};\n\n// fullscreen\n\n// The shell owns the fullscreen overlay. Modules request it via\n// fullscreen.enter(content) and exit via fullscreen.exit(). The shell renders\n// the content in a fixed inset-0 z-50 overlay, covering all shell chrome.\n// Same injection pattern as panel -- federation-safe.\n\nexport interface FullscreenOptions {\n /** React content to render inside the fullscreen overlay. */\n content: ReactNode;\n}\n\ntype FullscreenEnterFn = (opts: FullscreenOptions) => void;\ntype FullscreenExitFn = () => void;\n\nlet _fullscreenEnter: FullscreenEnterFn | null = null;\nlet _fullscreenExit: FullscreenExitFn | null = null;\n\n/**\n * Called by the shell during initialization to inject fullscreen controls.\n * Not part of the public module API -- only the shell calls this.\n */\nexport function initFullscreen(\n enterFn: FullscreenEnterFn,\n exitFn: FullscreenExitFn,\n) {\n _fullscreenEnter = enterFn;\n _fullscreenExit = exitFn;\n}\n\nexport const fullscreen = {\n /** Enter fullscreen mode, rendering content over all shell chrome. */\n enter(opts: FullscreenOptions) {\n if (_fullscreenEnter) {\n _fullscreenEnter(opts);\n } else {\n warnLog(\"fullscreen.enter: shell not initialized yet.\");\n }\n },\n /** Exit fullscreen mode, restoring the normal shell layout. */\n exit() {\n if (_fullscreenExit) {\n _fullscreenExit();\n } else {\n warnLog(\"fullscreen.exit: shell not initialized yet.\");\n }\n },\n};\n\n// events\n\ntype Unsubscribe = () => void;\n\nexport const events = {\n /** Subscribe to an event. Returns an unsubscribe function. */\n on<K extends keyof ShellEventMap>(\n key: K,\n handler: (payload: ShellEventMap[K]) => void,\n ): Unsubscribe {\n return eventBus.on(key as string, handler as (payload: unknown) => void);\n },\n\n /** Subscribe, auto-unsubscribing after the first emission. */\n once<K extends keyof ShellEventMap>(\n key: K,\n handler: (payload: ShellEventMap[K]) => void,\n ): Unsubscribe {\n return eventBus.once(key as string, handler as (payload: unknown) => void);\n },\n\n /** Emit an event. Handlers run asynchronously (microtask). */\n emit<K extends keyof ShellEventMap>(key: K, payload: ShellEventMap[K]): void {\n eventBus.emit(key as string, payload);\n },\n};\n","/**\n * Shell event bus -- in-memory pub/sub for cross-module communication.\n *\n * The bus is untyped internally (operates on strings and unknown payloads).\n * Type safety is provided by the public API layer in shell/api.ts, which\n * constrains keys and payloads via the ShellEventMap interface.\n *\n * Mirrors the server-side EventBus pattern (fire-and-forget, error isolation)\n * adapted for the browser's single-threaded model.\n */\nimport { devLog, warnLog } from \"@petrarca/sonnet-core\";\n\ntype Handler = (payload: unknown) => void;\ntype Unsubscribe = () => void;\n\nconst listeners = new Map<string, Set<Handler>>();\n\n/** Subscribe to an event key. Returns an unsubscribe function. */\nexport function on(key: string, handler: Handler): Unsubscribe {\n let set = listeners.get(key);\n if (!set) {\n set = new Set();\n listeners.set(key, set);\n }\n set.add(handler);\n devLog(`[shell:event] on \"${key}\" (${set.size} handler(s))`);\n return () => {\n set!.delete(handler);\n if (set!.size === 0) listeners.delete(key);\n devLog(`[shell:event] off \"${key}\" (${set!.size} handler(s))`);\n };\n}\n\n/** Subscribe to an event key, auto-unsubscribing after the first emission. */\nexport function once(key: string, handler: Handler): Unsubscribe {\n const unsubscribe = on(key, (payload) => {\n unsubscribe();\n handler(payload);\n });\n return unsubscribe;\n}\n\n/** Emit an event. Handlers run in microtasks (non-blocking, error-isolated). */\nexport function emit(key: string, payload: unknown): void {\n const set = listeners.get(key);\n const count = set?.size ?? 0;\n devLog(`[shell:event] emit \"${key}\"`, payload, `(${count} handler(s))`);\n if (!set || count === 0) return;\n for (const handler of set) {\n Promise.resolve().then(() => {\n try {\n handler(payload);\n } catch (err) {\n warnLog(`[shell:event] handler error \"${key}\":`, err);\n }\n });\n }\n}\n","/**\n * SidePane -- persistent resizable inline panel.\n *\n * Sits between SubNavPanel and the main content area in the AppShell flex row.\n * When open it takes a fixed pixel width; the content area (flex-1) shrinks to\n * fill the remainder. The main view remains fully visible and interactive.\n *\n * Opened/closed imperatively via sidePane.open() / sidePane.close() / sidePane.toggle()\n * from api.ts. State is provided by SidePaneContext (owned by AppShell).\n */\nimport type React from \"react\";\nimport { X } from \"lucide-react\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport { useResizablePanel } from \"@petrarca/sonnet-core/hooks\";\nimport { useSidePaneState } from \"./sidePaneState\";\n\nfunction DragHandle({\n separatorProps,\n onPointerDown,\n onDoubleClick,\n}: {\n separatorProps: React.HTMLAttributes<HTMLDivElement>;\n onPointerDown: React.PointerEventHandler<HTMLDivElement>;\n onDoubleClick: React.MouseEventHandler<HTMLDivElement>;\n}) {\n return (\n <div\n {...separatorProps}\n onPointerDown={onPointerDown}\n onDoubleClick={onDoubleClick}\n className={cn(\n \"absolute right-0 top-0 h-full w-1 cursor-col-resize\",\n \"hover:bg-primary/40 active:bg-primary/60 transition-colors\",\n )}\n />\n );\n}\n\nconst DEFAULT_WIDTH = 320;\nconst DEFAULT_MIN = 240;\nconst DEFAULT_MAX = 800;\n\n/**\n * SidePane renders nothing when no pane is open.\n * When open it renders a bordered panel with a drag handle on its right edge.\n * Double-clicking the handle resets to defaultWidth.\n */\nexport default function SidePane() {\n const { pane, close } = useSidePaneState();\n if (!pane) return null;\n return <SidePaneOpen pane={pane} onClose={close} />;\n}\n\nfunction SidePaneOpen({\n pane,\n onClose,\n}: {\n pane: NonNullable<ReturnType<typeof useSidePaneState>[\"pane\"]>;\n onClose: () => void;\n}) {\n const { panelWidth, handlePointerDown, handleDoubleClick, separatorProps } =\n useResizablePanel({\n defaultWidth: pane.defaultWidth ?? DEFAULT_WIDTH,\n minWidth: pane.minWidth ?? DEFAULT_MIN,\n maxWidth: pane.maxWidth ?? DEFAULT_MAX,\n direction: \"right-edge\",\n });\n\n const isFullWidth = pane.fullWidth === true;\n\n return (\n <div\n className={cn(\n \"relative flex flex-col border-r bg-background\",\n isFullWidth ? \"flex-1\" : \"shrink-0\",\n )}\n style={isFullWidth ? undefined : { width: panelWidth }}\n >\n {/* Header */}\n <div className=\"flex h-10 shrink-0 items-center justify-end border-b px-2\">\n <button\n onClick={onClose}\n className={cn(\n \"flex h-6 w-6 items-center justify-center rounded text-muted-foreground\",\n \"hover:bg-accent hover:text-foreground transition-colors\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n )}\n aria-label=\"Close side pane\"\n >\n <X className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n\n {/* Content */}\n <div className=\"flex-1 overflow-auto\">{pane.content}</div>\n\n {!isFullWidth && (\n <DragHandle\n separatorProps={separatorProps}\n onPointerDown={handlePointerDown}\n onDoubleClick={handleDoubleClick}\n />\n )}\n </div>\n );\n}\n","/**\n * Side pane state types and context.\n *\n * The side pane is a persistent, resizable inline panel that sits between\n * the SubNavPanel and the main content area. It shrinks the content area\n * rather than overlaying it -- the main view stays visible and interactive.\n *\n * Modules open/close/toggle it via the imperative sidePane API in api.ts.\n * AppShell owns the state and injects it here via SidePaneContext so that\n * SidePane.tsx can read it without coupling to AppShell directly.\n */\nimport { createContext, useContext, type ReactNode } from \"react\";\n\nexport interface SidePaneOptions {\n /** Content to render inside the side pane. */\n content: ReactNode;\n /**\n * Stable key identifying which module/tool owns this pane instance.\n * Used by IconRail to highlight the active pane module and by toggle()\n * to detect whether the same content is already open.\n */\n moduleId: string;\n /** Initial width in pixels. Defaults to 320. */\n defaultWidth?: number;\n /** Minimum draggable width in pixels. Defaults to 240. */\n minWidth?: number;\n /**\n * Maximum draggable width in pixels.\n * Omit or pass Infinity for unlimited (fills remaining space up to viewport).\n */\n maxWidth?: number;\n /**\n * When true, the pane expands to fill the entire content area (flex-1),\n * collapsing the main route content to zero width. Use for full-screen\n * tool views (schema viewer, form editors). The drag handle is hidden.\n * Toggle via sidePane.setFullWidth(boolean) from inside the pane content.\n */\n fullWidth?: boolean;\n}\n\nexport interface SidePaneState {\n /** Currently open pane options, or null when closed. */\n pane: SidePaneOptions | null;\n open: (opts: SidePaneOptions) => void;\n close: () => void;\n toggle: (opts: SidePaneOptions) => void;\n /** Expand or collapse the pane to fill the full content area. */\n setFullWidth: (fullWidth: boolean) => void;\n}\n\nexport const SidePaneContext = createContext<SidePaneState | null>(null);\n\n/**\n * Read the side pane state from context.\n * Must be called within an AppShell (which provides the context).\n */\nexport function useSidePaneState(): SidePaneState {\n const ctx = useContext(SidePaneContext);\n if (!ctx) {\n throw new Error(\"useSidePaneState must be used within an AppShell\");\n }\n return ctx;\n}\n","import { useEffect, useCallback } from \"react\";\nimport { useNavigate } from \"react-router-dom\";\nimport {\n CommandDialog,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n CommandSeparator,\n} from \"@petrarca/sonnet-ui\";\nimport { useShellModules } from \"./shellModules\";\nimport type { ServiceModule } from \"./types\";\n\ninterface CommandMenuProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}\n\n/**\n * CommandMenu -- Cmd+K command menu.\n *\n * Indexes all navigation items from the service domains so users can\n * quickly jump to any page by typing.\n */\nexport default function CommandMenu({ open, onOpenChange }: CommandMenuProps) {\n const navigate = useNavigate();\n const { mainModules, bottomModules } = useShellModules();\n\n // Global Cmd+K / Ctrl+K shortcut\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"k\" && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n onOpenChange(!open);\n }\n };\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [open, onOpenChange]);\n\n const handleSelect = useCallback(\n (path: string) => {\n navigate(path);\n onOpenChange(false);\n },\n [navigate, onOpenChange],\n );\n\n const renderNavGroup = (service: ServiceModule) => {\n if (service.navigation.length === 0) return null;\n const Icon = service.icon;\n return (\n <CommandGroup key={`nav-${service.id}`} heading={service.label}>\n {service.navigation.flatMap((group) =>\n group.links.map((link) => (\n <CommandItem\n key={link.path}\n value={`${service.label} ${group.heading ?? \"\"} ${link.label}`}\n onSelect={() => handleSelect(link.path)}\n >\n <Icon className=\"mr-2 h-4 w-4 text-muted-foreground\" />\n <span>{link.label}</span>\n {group.heading && (\n <span className=\"ml-auto text-xs text-muted-foreground\">\n {group.heading}\n </span>\n )}\n </CommandItem>\n )),\n )}\n </CommandGroup>\n );\n };\n\n const renderCommandGroup = (service: ServiceModule) => {\n if (!service.commands?.length) return null;\n const Icon = service.icon;\n return (\n <CommandGroup\n key={`cmd-${service.id}`}\n heading={service.commands[0].group ?? service.label}\n >\n {service.commands.map((cmd) => {\n const CmdIcon = cmd.icon ?? Icon;\n return (\n <CommandItem\n key={cmd.id}\n value={`${service.label} ${cmd.label}`}\n onSelect={() => {\n cmd.action();\n onOpenChange(false);\n }}\n >\n <CmdIcon className=\"mr-2 h-4 w-4 text-muted-foreground\" />\n <span>{cmd.label}</span>\n </CommandItem>\n );\n })}\n </CommandGroup>\n );\n };\n\n const allModules = [...mainModules, ...bottomModules];\n\n return (\n <CommandDialog open={open} onOpenChange={onOpenChange}>\n <CommandInput placeholder=\"Search pages, services, actions...\" />\n <CommandList>\n <CommandEmpty>No results found.</CommandEmpty>\n\n {mainModules.map(renderNavGroup)}\n\n <CommandSeparator />\n\n {bottomModules.map(renderNavGroup)}\n\n {allModules.some((m) => m.commands?.length) && (\n <>\n <CommandSeparator />\n {allModules.map(renderCommandGroup)}\n </>\n )}\n </CommandList>\n </CommandDialog>\n );\n}\n","/**\n * Shell configuration types and context.\n *\n * ShellConfig is intentionally minimal. The shell provides layout chrome\n * (TopBar header, IconRail, SubNavPanel, CommandMenu) but does not own\n * any app-specific content. The consumer composes the TopBar content --\n * logo, environment selector, search trigger, user menu -- via the\n * `topBar` ReactNode slot using building blocks exported from the shell.\n */\nimport { createContext, useContext, type ReactNode } from \"react\";\n\n// Top-level shell configuration.\n\nexport interface ShellConfig {\n /**\n * Content rendered inside the TopBar header. The shell provides the\n * `<header>` element with its sizing and border; the consumer owns\n * everything inside it.\n *\n * Compose this using building blocks like `SearchTrigger` and\n * `UserMenu` (exported from the shell) alongside any app-specific\n * components.\n */\n topBar?: ReactNode;\n}\n\n// Context\n\nexport const ShellConfigContext = createContext<ShellConfig | null>(null);\n\n/**\n * Read the shell configuration from context.\n * Must be called within a ShellConfigProvider.\n */\nexport function useShellConfig(): ShellConfig {\n const config = useContext(ShellConfigContext);\n if (!config) {\n throw new Error(\"useShellConfig must be used within a ShellConfigProvider\");\n }\n return config;\n}\n","import { Toaster } from \"sonner\";\nimport AppShell from \"./AppShell\";\nimport { ShellConfigProvider } from \"./ShellConfigProvider\";\nimport type { ShellConfig } from \"./shellConfig\";\nimport type { ModuleRegistry } from \"./createModuleRegistry\";\n\n/**\n * RootLayout -- top-level layout that wraps the entire authenticated app.\n * Renders the Toaster for notifications and the AppShell (icon rail + sub-nav + content).\n */\n\ninterface RootLayoutProps {\n config: ShellConfig;\n registry: ModuleRegistry;\n}\n\nexport default function RootLayout({ config, registry }: RootLayoutProps) {\n return (\n <ShellConfigProvider config={config}>\n <Toaster position=\"top-right\" richColors closeButton />\n <AppShell registry={registry} />\n </ShellConfigProvider>\n );\n}\n","/**\n * ShellConfigProvider -- wraps the shell with configuration context.\n */\nimport type { ReactNode } from \"react\";\nimport { ShellConfigContext, type ShellConfig } from \"./shellConfig\";\n\ninterface ShellConfigProviderProps {\n config: ShellConfig;\n children: ReactNode;\n}\n\nexport function ShellConfigProvider({\n config,\n children,\n}: ShellConfigProviderProps) {\n return (\n <ShellConfigContext.Provider value={config}>\n {children}\n </ShellConfigContext.Provider>\n );\n}\n","import { useLocation } from \"react-router-dom\";\n\n/**\n * PlaceholderPage — generic wireframe page for routes not yet implemented.\n * Shows the current path and a placeholder content area.\n */\nexport default function PlaceholderPage() {\n const { pathname } = useLocation();\n\n return (\n <div>\n <h1 className=\"mb-1\">{pathToTitle(pathname)}</h1>\n <p className=\"text-sm text-muted-foreground mb-6\">{pathname}</p>\n\n {/* Wireframe content placeholder */}\n <div className=\"rounded-lg border-2 border-dashed border-border p-12 flex items-center justify-center\">\n <span className=\"text-sm text-muted-foreground\">\n Content area — not yet implemented\n </span>\n </div>\n </div>\n );\n}\n\n/** Convert a path like \"/healthcare/patients\" to \"Patients\" */\nfunction pathToTitle(path: string): string {\n const last = path.split(\"/\").filter(Boolean).pop();\n if (!last) return \"Dashboard\";\n return last\n .split(\"-\")\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(\" \");\n}\n","import { Search } from \"lucide-react\";\nimport { Button } from \"@petrarca/sonnet-ui\";\nimport { navigation } from \"./api\";\n\n/**\n * SearchTrigger -- Cmd+K search button for the TopBar.\n *\n * Opens the shell CommandMenu via the imperative navigation API.\n * Generic building block, no app-specific dependencies.\n */\nexport function SearchTrigger() {\n return (\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"h-8 gap-2 text-sm text-muted-foreground w-56 justify-start\"\n onClick={() => navigation.openCommandMenu()}\n >\n <Search className=\"h-4 w-4\" />\n <span>Search...</span>\n <kbd className=\"ml-auto pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground\">\n <span className=\"text-xs\">&#x2318;</span>K\n </kbd>\n </Button>\n );\n}\n","import { LogOut, User } from \"lucide-react\";\nimport { Button } from \"@petrarca/sonnet-ui\";\nimport { Avatar, AvatarFallback } from \"@petrarca/sonnet-ui\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@petrarca/sonnet-ui\";\n\n/**\n * UserMenu -- avatar dropdown for the TopBar.\n *\n * Shows the user's initials in an avatar. The dropdown displays name,\n * email, a profile link, and a sign-out action. Generic building block,\n * no app-specific dependencies.\n */\n\nexport interface UserMenuUser {\n name: string;\n email: string;\n initials: string;\n}\n\ninterface UserMenuProps {\n user: UserMenuUser;\n onSignOut?: () => void;\n}\n\nexport function UserMenu({ user, onSignOut }: UserMenuProps) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"compact\" className=\"rounded-full\">\n <Avatar className=\"h-7 w-7\">\n <AvatarFallback className=\"text-xs\">{user.initials}</AvatarFallback>\n </Avatar>\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-48\">\n <DropdownMenuLabel className=\"font-normal\">\n <div className=\"flex flex-col gap-1\">\n <p className=\"text-sm font-medium\">{user.name}</p>\n <p className=\"text-xs text-muted-foreground\">{user.email}</p>\n </div>\n </DropdownMenuLabel>\n <DropdownMenuSeparator />\n <DropdownMenuItem>\n <User className=\"mr-2 h-4 w-4\" />\n Profile\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem onSelect={onSignOut}>\n <LogOut className=\"mr-2 h-4 w-4\" />\n Sign out\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n","/**\n * Module registry factory.\n *\n * Accepts a list of ServiceModules and returns derived data structures\n * consumed by the shell (icon rail groups, flattened routes, extension\n * point lookup). This is the reusable core; the app-specific module\n * list lives in the consumer (e.g. modules/registry.ts).\n */\nimport type { RouteObject } from \"react-router-dom\";\nimport type { ServiceModule, Contribution } from \"./types\";\n\nexport interface ModuleRegistry {\n /** All modules in registration order. */\n modules: ServiceModule[];\n\n /** Visible modules shown in the main area of the icon rail. */\n mainModules: ServiceModule[];\n\n /** Modules pinned to the bottom of the icon rail. */\n bottomModules: ServiceModule[];\n\n /** All routes from all modules, flattened. */\n allRoutes: RouteObject[];\n\n /** Get contributions for a named extension point, sorted by order. */\n getExtensionPoint: (name: string) => Contribution[];\n}\n\nexport function createModuleRegistry(modules: ServiceModule[]): ModuleRegistry {\n const visible = modules.filter((m) => !m.hidden);\n const mainModules = visible.filter((m) => !m.pinBottom);\n const bottomModules = visible.filter((m) => m.pinBottom);\n const allRoutes = modules.flatMap((m) => m.routes);\n\n // Pre-collect all contributions for O(n) lookup per call.\n const contributionsByPoint = new Map<string, Contribution[]>();\n for (const m of modules) {\n for (const c of m.contributions ?? []) {\n const list = contributionsByPoint.get(c.extensionPoint) ?? [];\n list.push(c);\n contributionsByPoint.set(c.extensionPoint, list);\n }\n }\n // Sort each group once.\n for (const list of contributionsByPoint.values()) {\n list.sort((a, b) => a.order - b.order);\n }\n\n function getExtensionPoint(name: string): Contribution[] {\n return contributionsByPoint.get(name) ?? [];\n }\n\n return { modules, mainModules, bottomModules, allRoutes, getExtensionPoint };\n}\n","/**\n * OverviewCard and FeatureLink -- building blocks for module overview pages.\n *\n * OverviewCard presents a feature with icon, title, description, and optional\n * navigation via a stable feature id.\n *\n * FeatureLink is an inline text link for use in descriptions or prose,\n * also navigating via stable feature id.\n *\n * Part of the shell -- extracts to @petrarca/sonnet-shell.\n */\n\nimport React from \"react\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport { navigation } from \"./api\";\n\ninterface OverviewCardProps {\n /** Lucide icon component. */\n icon: React.ComponentType<{ className?: string }>;\n /** Card title. */\n title: string;\n /** Description -- plain string or React nodes (e.g. with FeatureLink). */\n description: React.ReactNode;\n /**\n * Stable feature identifier (e.g. \"auditing.audit-events\").\n * Resolved to a path via the shell registry at click time.\n * Omit for non-navigable cards.\n */\n feature?: string;\n /** Additional CSS class names. */\n className?: string;\n}\n\n/**\n * FeatureLink -- inline text link navigating to a feature by stable id.\n *\n * Use inside OverviewCard descriptions or overview page prose to link\n * to a feature without hardcoding paths.\n *\n * @example\n * <FeatureLink feature=\"auditing.audit-log\">Audit Log</FeatureLink>\n */\nexport function FeatureLink({\n feature,\n children,\n}: {\n feature: string;\n children: React.ReactNode;\n}): React.ReactElement {\n return (\n <span\n role=\"link\"\n tabIndex={0}\n onClick={(e) => {\n e.stopPropagation();\n navigation.goToFeature(feature);\n }}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n e.stopPropagation();\n navigation.goToFeature(feature);\n }\n }}\n className=\"underline underline-offset-2 hover:text-foreground transition-colors cursor-pointer\"\n >\n {children}\n </span>\n );\n}\n\n/** Feature card for module overview pages. Navigates via the shell API. */\nexport function OverviewCard({\n icon: Icon,\n title,\n description,\n feature,\n className,\n}: OverviewCardProps): React.ReactElement {\n return (\n <button\n onClick={feature ? () => navigation.goToFeature(feature) : undefined}\n disabled={!feature}\n className={cn(\n \"rounded-lg border bg-card p-5 text-left flex flex-col gap-3\",\n \"disabled:cursor-default\",\n feature && \"hover:bg-accent/50 transition-colors\",\n className,\n )}\n >\n <div className=\"h-9 w-9 rounded-md bg-blue-50 flex items-center justify-center shrink-0\">\n <Icon className=\"h-5 w-5 text-blue-600\" />\n </div>\n <div>\n <p className=\"text-sm font-medium mb-1\">{title}</p>\n <p className=\"text-xs text-muted-foreground leading-relaxed\">\n {description}\n </p>\n </div>\n </button>\n );\n}\n"],"mappings":"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","names":["useEffect","useCallback","useRef","useMemo","useLocation","useNavigate","ScrollArea","jsx","Button","jsx","jsxs","Button","useMemo","cn","Tooltip","TooltipContent","TooltipTrigger","warnLog","warnLog","jsx","jsxs","useMemo","Tooltip","TooltipTrigger","TooltipContent","cn","cn","createContext","useContext","jsx","jsxs","cn","useEffect","jsx","jsxs","useEffect","createContext","useContext","Fragment","jsx","jsxs","useRef","useEffect","useLocation","useMemo","useCallback","useSidePaneState","useNavigate","sidePane","panel","dialog","ScrollArea","jsx","jsx","jsxs","useLocation","jsx","jsxs","Button","jsx","jsxs","Button","Button","jsx","jsxs","cn","jsx","jsxs","cn"]}
1
+ {"version":3,"sources":["../src/AppShell.tsx","../src/ConfirmDialog.tsx","../src/TopBar.tsx","../src/ShellFooter.tsx","../src/ShellRail.tsx","../src/IconRail.tsx","../src/SubNavPanel.tsx","../src/hooks.ts","../src/api.ts","../src/eventBus.ts","../src/shellModules.ts","../src/SidebarGroup.tsx","../src/SidebarItem.tsx","../src/shellNavigation.ts","../src/shellConfig.ts","../src/capabilities.ts","../src/SidePane.tsx","../src/sidePaneState.ts","../src/DragHandle.tsx","../src/CommandMenu.tsx","../src/ModuleEffects.tsx","../src/RootLayout.tsx","../src/ShellConfigProvider.tsx","../src/PlaceholderPage.tsx","../src/Sidebar.tsx","../src/ShellSidebar.tsx","../src/ShellVersion.tsx","../src/SearchTrigger.tsx","../src/UserMenu.tsx","../src/createModuleRegistry.ts","../src/OverviewCard.tsx"],"sourcesContent":["import React, {\n useState,\n useEffect,\n useCallback,\n useRef,\n useMemo,\n} from \"react\";\nimport { useResizablePanel } from \"@petrarca/sonnet-core/hooks\";\nimport { Outlet, useLocation, useNavigate } from \"react-router-dom\";\nimport { TooltipProvider } from \"@petrarca/sonnet-ui\";\nimport { ScrollArea } from \"@petrarca/sonnet-ui\";\nimport {\n Sheet,\n SheetContent,\n SheetHeader,\n SheetTitle,\n SheetDescription,\n SheetBody,\n} from \"@petrarca/sonnet-ui\";\nimport { ConfirmDialog } from \"./ConfirmDialog\";\nimport TopBar from \"./TopBar\";\nimport ShellFooter from \"./ShellFooter\";\nimport { ShellRail } from \"./ShellRail\";\nimport SidePane from \"./SidePane\";\nimport { DragHandle } from \"./DragHandle\";\nimport CommandMenu from \"./CommandMenu\";\nimport { ModuleEffects } from \"./ModuleEffects\";\nimport {\n initNavigation,\n initFeatureNav,\n initPanel,\n initDialog,\n initFullscreen,\n initSidePane,\n type PanelOptions,\n type ConfirmOptions,\n type FullscreenOptions,\n} from \"./api\";\nimport type { ModuleRegistry } from \"./createModuleRegistry\";\nimport { ShellModulesContext } from \"./shellModules\";\nimport { useShellConfig } from \"./shellConfig\";\nimport { SidePaneContext, type SidePaneOptions } from \"./sidePaneState\";\nimport { ShellNavigationContext } from \"./shellNavigation\";\nimport type { ShellModule } from \"./types\";\n\n// Single source of truth for panel width tokens.\n// px: pixel value used as defaultWidth for resizable mode (viewport-relative\n// tokens like \"half\" / \"full\" are not resizable -- resizable falls back to 640).\nconst PANEL_WIDTHS: Record<string, { css: string; px: number }> = {\n narrow: { css: \"w-[480px]\", px: 480 },\n default: { css: \"w-[640px]\", px: 640 },\n wide: { css: \"w-[800px]\", px: 800 },\n half: { css: \"w-[50vw]\", px: 640 },\n full: { css: \"w-screen\", px: 640 },\n // legacy aliases\n lg: { css: \"w-[640px]\", px: 640 },\n \"1/3\": { css: \"w-[33vw]\", px: 640 },\n \"1/2\": { css: \"w-[50vw]\", px: 640 },\n};\n\nconst DEFAULT_PANEL = PANEL_WIDTHS.default;\n\n// -- Helpers extracted to reduce AppShell complexity --\n\nfunction isSidePaneModule(service: {\n sidePane?: unknown;\n navigation: unknown[];\n}): boolean {\n return !!service.sidePane && service.navigation.length === 0;\n}\n\nfunction selectSidePaneModule(\n service: {\n id: string;\n basePath: string;\n routes: unknown[];\n sidePane?: {\n defaultWidth?: number;\n minWidth?: number;\n maxWidth?: number;\n contentFactory?: () => React.ReactNode;\n };\n },\n current: SidePaneOptions | null,\n setSidePaneState: (s: SidePaneOptions | null) => void,\n navigate: (path: string) => void,\n): void {\n if (current?.moduleId === service.id) {\n setSidePaneState(null);\n } else {\n setSidePaneState({\n moduleId: service.id,\n content: service.sidePane?.contentFactory?.() ?? null,\n defaultWidth: service.sidePane?.defaultWidth,\n minWidth: service.sidePane?.minWidth,\n maxWidth: service.sidePane?.maxWidth,\n });\n // Only navigate if the module has routes — pane-only modules\n // (routes: []) have no registered path, navigating would 404.\n if (service.routes.length > 0) {\n navigate(service.basePath);\n }\n }\n}\n\nfunction selectNavModule(\n service: {\n basePath: string;\n navigation: Array<{ links: Array<{ path: string }> }>;\n },\n navigate: (path: string) => void,\n setSubNavCollapsed: (v: boolean) => void,\n closeSidePane: () => void,\n): void {\n closeSidePane();\n setSubNavCollapsed(false);\n const target = service.navigation[0]?.links[0]?.path ?? service.basePath;\n navigate(target);\n}\n\n// Wire all imperative shell APIs once on mount.\nfunction useShellApiInit(deps: {\n navigate: ReturnType<typeof useNavigate>;\n openCommandMenu: () => void;\n handlePanelOpen: (opts: PanelOptions) => void;\n handlePanelClose: () => void;\n handleFullscreenEnter: (opts: FullscreenOptions) => void;\n handleFullscreenExit: () => void;\n handleSidePaneOpen: (opts: SidePaneOptions) => void;\n handleSidePaneClose: () => void;\n handleSidePaneIsOpen: () => boolean;\n handleSidePaneActiveModuleId: () => string | null;\n handleSidePaneSetFullWidth: (fullWidth: boolean) => void;\n setDialogState: React.Dispatch<React.SetStateAction<DialogState | null>>;\n featureLookup: (featureId: string) => string | null;\n}) {\n const stableRefs = useRef(deps);\n useEffect(() => {\n const r = stableRefs.current;\n initNavigation(r.navigate, r.openCommandMenu);\n initFeatureNav(r.featureLookup);\n initPanel(r.handlePanelOpen, r.handlePanelClose);\n initFullscreen(r.handleFullscreenEnter, r.handleFullscreenExit);\n initSidePane(\n r.handleSidePaneOpen,\n r.handleSidePaneClose,\n r.handleSidePaneIsOpen,\n r.handleSidePaneActiveModuleId,\n r.handleSidePaneSetFullWidth,\n );\n initDialog(\n (opts: ConfirmOptions) =>\n new Promise<boolean>((resolve) => r.setDialogState({ opts, resolve })),\n );\n }, []);\n}\n\ninterface AppShellProps {\n registry: ModuleRegistry;\n /**\n * Optional custom sidebar replacing the default IconRail + SubNavPanel.\n * When provided, the shell renders this element in place of the two-column\n * navigation chrome. Use the Sidebar / SidebarGroup / SidebarItem components\n * from this package to build a single-column navigation layout.\n */\n sidebar?: React.ReactNode;\n}\n\ninterface DialogState {\n opts: ConfirmOptions;\n resolve: (confirmed: boolean) => void;\n}\n\n/**\n * AppShell -- the main layout skeleton.\n *\n * Owns the panel (slide-over) -- modules request it via panel.open(),\n * the shell renders the provided content inside a Sheet.\n *\n * Receives its module registry as a prop so it has no dependency on\n * app-specific module lists.\n */\n// Hook: track which service is active based on URL.\nfunction useActiveService(modules: ModuleRegistry[\"modules\"]) {\n const location = useLocation();\n const serviceByBasePath = useMemo(\n () =>\n new Map(\n modules\n .filter((m) => !m.hidden && m.basePath !== \"/\")\n .map((m) => [m.basePath, m.id]),\n ),\n [modules],\n );\n const resolveServiceFromPath = useCallback(\n (pathname: string): string | null => {\n for (const [basePath, id] of serviceByBasePath) {\n if (pathname.startsWith(basePath)) return id;\n }\n return null;\n },\n [serviceByBasePath],\n );\n const [selectedServiceId, setSelectedServiceId] = useState<string | null>(\n () => resolveServiceFromPath(location.pathname),\n );\n useEffect(\n () => setSelectedServiceId(resolveServiceFromPath(location.pathname)),\n [location.pathname, resolveServiceFromPath],\n );\n const activeService = selectedServiceId\n ? (modules.find((s) => s.id === selectedServiceId) ?? null)\n : null;\n return { activeService, selectedServiceId, setSelectedServiceId };\n}\n\n// Hook: side pane state and handlers.\nfunction useSidePaneState() {\n const [sidePaneState, setSidePaneState] = useState<SidePaneOptions | null>(\n null,\n );\n const handleOpen = useCallback(\n (opts: SidePaneOptions) => setSidePaneState(opts),\n [],\n );\n const handleClose = useCallback(() => setSidePaneState(null), []);\n const handleIsOpen = useCallback(\n () => sidePaneState !== null,\n [sidePaneState],\n );\n const handleActiveModuleId = useCallback(\n () => sidePaneState?.moduleId ?? null,\n [sidePaneState],\n );\n const handleSetFullWidth = useCallback((fullWidth: boolean) => {\n setSidePaneState((prev) => (prev ? { ...prev, fullWidth } : prev));\n }, []);\n return {\n sidePaneState,\n setSidePaneState,\n handleOpen,\n handleClose,\n handleIsOpen,\n handleActiveModuleId,\n handleSetFullWidth,\n };\n}\n\n/** Resolved resize options passed as a single object to SlideOverPanel. */\ninterface PanelResizeOptions {\n enabled: boolean;\n defaultWidth: number;\n minWidth: number;\n maxWidth: number;\n}\n\nconst DEFAULT_RESIZE_MIN = 240;\nconst DEFAULT_RESIZE_MAX = 1200;\n\n// Derive resize options from panel state. Extracted to keep usePanelState lean.\nfunction resizeOptionsFromPanel(\n state: PanelOptions | null,\n widthEntry: { px: number },\n): PanelResizeOptions {\n if (!state?.resizable) {\n return {\n enabled: false,\n defaultWidth: widthEntry.px,\n minWidth: DEFAULT_RESIZE_MIN,\n maxWidth: DEFAULT_RESIZE_MAX,\n };\n }\n const viewportMax =\n typeof window !== \"undefined\"\n ? Math.round(window.innerWidth * 0.9)\n : DEFAULT_RESIZE_MAX;\n return {\n enabled: true,\n defaultWidth: widthEntry.px,\n minWidth: state.minWidth ?? DEFAULT_RESIZE_MIN,\n maxWidth: state.maxWidth ?? viewportMax,\n };\n}\n\n// Hook: slide-over panel state and handlers.\nfunction usePanelState() {\n const [panelState, setPanelState] = useState<PanelOptions | null>(null);\n const panelOnCloseRef = useRef<(() => void) | undefined>(undefined);\n const handleOpen = useCallback(\n (opts: PanelOptions) => setPanelState(opts),\n [],\n );\n const handleClose = useCallback(() => {\n panelOnCloseRef.current = panelState?.onClose;\n setPanelState(null);\n }, [panelState]);\n\n const widthEntry =\n PANEL_WIDTHS[panelState?.width ?? \"default\"] ?? DEFAULT_PANEL;\n const panelWidth = widthEntry.css;\n const panelOffsetTop = panelState?.coverage === \"full\" ? \"0px\" : \"3rem\";\n\n return {\n panelState,\n panelOnCloseRef,\n handleOpen,\n handleClose,\n panelWidth,\n panelOffsetTop,\n resize: resizeOptionsFromPanel(panelState, widthEntry),\n };\n}\n\n// Hook: confirm dialog state and handlers.\nfunction useDialogState() {\n const [dialogState, setDialogState] = useState<DialogState | null>(null);\n const handleConfirm = useCallback(() => {\n dialogState?.resolve(true);\n setDialogState(null);\n }, [dialogState]);\n const handleCancel = useCallback(() => {\n dialogState?.resolve(false);\n setDialogState(null);\n }, [dialogState]);\n return { dialogState, setDialogState, handleConfirm, handleCancel };\n}\n\n// Build a stable feature id -> path lookup from the module registry.\nfunction useFeatureLookup(modules: ModuleRegistry[\"modules\"]) {\n return useMemo(() => {\n const map = new Map<string, string>();\n for (const m of modules) {\n for (const group of m.navigation) {\n for (const link of group.links) {\n if (link.id) map.set(link.id, link.path);\n }\n }\n }\n return (featureId: string) => map.get(featureId) ?? null;\n }, [modules]);\n}\n\nexport default function AppShell({ registry, sidebar }: AppShellProps) {\n const navigate = useNavigate();\n const config = useShellConfig();\n const { modules } = registry;\n\n const { activeService, setSelectedServiceId } = useActiveService(modules);\n const [subNavCollapsed, setSubNavCollapsed] = useState(false);\n const [commandMenuOpen, setCommandMenuOpen] = useState(false);\n const openCommandMenu = useCallback(() => setCommandMenuOpen(true), []);\n const [fullscreenState, setFullscreenState] =\n useState<FullscreenOptions | null>(null);\n const handleFullscreenEnter = useCallback(\n (opts: FullscreenOptions) => setFullscreenState(opts),\n [],\n );\n const handleFullscreenExit = useCallback(() => setFullscreenState(null), []);\n\n const sidePane = useSidePaneState();\n const panel = usePanelState();\n const dialog = useDialogState();\n const featureLookup = useFeatureLookup(modules);\n\n useShellApiInit({\n navigate,\n openCommandMenu,\n handlePanelOpen: panel.handleOpen,\n handlePanelClose: panel.handleClose,\n handleFullscreenEnter,\n handleFullscreenExit,\n handleSidePaneOpen: sidePane.handleOpen,\n handleSidePaneClose: sidePane.handleClose,\n handleSidePaneIsOpen: sidePane.handleIsOpen,\n handleSidePaneActiveModuleId: sidePane.handleActiveModuleId,\n handleSidePaneSetFullWidth: sidePane.handleSetFullWidth,\n setDialogState: dialog.setDialogState,\n featureLookup,\n });\n\n const handleServiceSelect = useCallback(\n (serviceId: string) => {\n const service = modules.find((s) => s.id === serviceId);\n if (!service) return;\n if (isSidePaneModule(service)) {\n selectSidePaneModule(\n service,\n sidePane.sidePaneState,\n sidePane.setSidePaneState,\n navigate,\n );\n // Don't change activeService for pane-only modules — the content\n // area still shows the previous route and needs its layout mode.\n // Collapse SubNavPanel by default so it doesn't linger from a nav module.\n // Consumers can opt out via sidePane.collapseSubNav: false.\n if (service.sidePane?.collapseSubNav !== false) {\n setSubNavCollapsed(true);\n }\n } else {\n selectNavModule(\n service,\n navigate,\n setSubNavCollapsed,\n sidePane.handleClose,\n );\n setSelectedServiceId(serviceId);\n }\n },\n [\n modules,\n sidePane.sidePaneState,\n sidePane.setSidePaneState,\n sidePane.handleClose,\n navigate,\n setSelectedServiceId,\n setSubNavCollapsed,\n ],\n );\n\n const sidePaneContextValue = useMemo(\n () => ({\n pane: sidePane.sidePaneState,\n open: sidePane.handleOpen,\n close: sidePane.handleClose,\n toggle: (opts: SidePaneOptions) => {\n if (sidePane.sidePaneState?.moduleId === opts.moduleId) {\n sidePane.setSidePaneState(null);\n } else {\n sidePane.setSidePaneState(opts);\n }\n },\n setFullWidth: sidePane.handleSetFullWidth,\n }),\n [sidePane],\n );\n\n const navigationValue = {\n activeService,\n sidePaneModuleId: sidePane.sidePaneState?.moduleId ?? null,\n subNavCollapsed,\n onToggleSubNav: () => setSubNavCollapsed((c) => !c),\n onServiceSelect: handleServiceSelect,\n };\n\n return (\n <ShellModulesContext.Provider value={registry}>\n <SidePaneContext.Provider value={sidePaneContextValue}>\n <ShellNavigationContext.Provider value={navigationValue}>\n <TooltipProvider>\n {/* Module-owned effects (event subscriptions, cache invalidation) */}\n <ModuleEffects modules={modules} />\n <div className=\"flex h-screen w-screen flex-col overflow-hidden\">\n {/* TopBar */}\n <TopBar>{config.topBar}</TopBar>\n\n {/* CommandMenu (Cmd+K) */}\n <CommandMenu\n open={commandMenuOpen}\n onOpenChange={setCommandMenuOpen}\n />\n\n {/* Body: sidebar (or ShellRail) + SidePane + Content Area */}\n <ShellBody\n activeService={activeService}\n sidePaneFullWidth={sidePane.sidePaneState?.fullWidth}\n sidebar={sidebar}\n />\n\n {/* Footer */}\n {config.footer && <ShellFooter>{config.footer}</ShellFooter>}\n\n {/* Confirm Dialog */}\n {dialog.dialogState && (\n <ConfirmDialog\n open={true}\n title={dialog.dialogState.opts.title}\n description={dialog.dialogState.opts.description}\n confirmLabel={dialog.dialogState.opts.confirmLabel}\n cancelLabel={dialog.dialogState.opts.cancelLabel}\n variant={dialog.dialogState.opts.variant}\n onConfirm={dialog.handleConfirm}\n onCancel={dialog.handleCancel}\n />\n )}\n\n {/* Fullscreen overlay -- covers all shell chrome */}\n {fullscreenState && (\n <div className=\"fixed inset-0 z-50 bg-background overflow-auto\">\n {fullscreenState.content}\n </div>\n )}\n\n {/* Slide-over Panel */}\n <SlideOverPanel\n panelState={panel.panelState}\n panelWidth={panel.panelWidth}\n panelOffsetTop={panel.panelOffsetTop}\n panelOnCloseRef={panel.panelOnCloseRef}\n onClose={panel.handleClose}\n resize={panel.resize}\n />\n </div>\n </TooltipProvider>\n </ShellNavigationContext.Provider>\n </SidePaneContext.Provider>\n </ShellModulesContext.Provider>\n );\n}\n\n// -- Sub-components extracted to reduce AppShell complexity --\n\ninterface SlideOverPanelProps {\n panelState: PanelOptions | null;\n panelWidth: string;\n panelOffsetTop: string;\n panelOnCloseRef: React.MutableRefObject<(() => void) | undefined>;\n onClose: () => void;\n resize: PanelResizeOptions;\n}\n\nfunction SlideOverPanel({\n panelState,\n panelWidth,\n panelOffsetTop,\n panelOnCloseRef,\n onClose,\n resize,\n}: SlideOverPanelProps) {\n const sheetProps = {\n side: \"right\" as const,\n offsetTop: panelOffsetTop,\n onCloseAutoFocus: (e: Event) => {\n if (panelOnCloseRef.current) {\n e.preventDefault();\n panelOnCloseRef.current();\n }\n },\n ...(!panelState?.description && { \"aria-describedby\": undefined }),\n };\n\n return (\n <Sheet\n open={panelState !== null}\n onOpenChange={(open) => {\n if (!open) onClose();\n }}\n >\n {resize.enabled ? (\n <ResizableSheetContent {...sheetProps} resize={resize}>\n {panelState && <PanelContent state={panelState} />}\n </ResizableSheetContent>\n ) : (\n <SheetContent {...sheetProps} className={`${panelWidth} max-w-[90vw]`}>\n {panelState && <PanelContent state={panelState} />}\n </SheetContent>\n )}\n </Sheet>\n );\n}\n\n/**\n * Wrapper that mounts useResizablePanel only when resize is enabled.\n * Hooks must be called unconditionally — splitting into a separate component\n * is the idiomatic way to avoid calling hooks behind a conditional.\n */\nfunction ResizableSheetContent({\n resize,\n children,\n ...sheetProps\n}: {\n resize: PanelResizeOptions;\n children: React.ReactNode;\n} & React.ComponentPropsWithoutRef<typeof SheetContent>) {\n const {\n panelWidth: dynWidth,\n handlePointerDown,\n handleDoubleClick,\n separatorProps,\n } = useResizablePanel({\n defaultWidth: resize.defaultWidth,\n minWidth: resize.minWidth,\n maxWidth: resize.maxWidth,\n direction: \"left-edge\",\n });\n\n return (\n <SheetContent\n {...sheetProps}\n className=\"max-w-[90vw]\"\n style={{ width: dynWidth }}\n >\n <DragHandle\n edge=\"left\"\n separatorProps={separatorProps}\n onPointerDown={handlePointerDown}\n onDoubleClick={handleDoubleClick}\n />\n {children}\n </SheetContent>\n );\n}\n\ninterface ShellBodyProps {\n activeService: ShellModule | null;\n sidePaneFullWidth?: boolean;\n sidebar?: React.ReactNode;\n}\n\nfunction ShellBody({\n activeService,\n sidePaneFullWidth,\n sidebar,\n}: ShellBodyProps) {\n return (\n <div className=\"flex flex-1 overflow-hidden\">\n {sidebar ?? <ShellRail />}\n\n <SidePane />\n\n {sidePaneFullWidth !== true && (\n <div className=\"flex-1 min-w-0 h-full overflow-hidden\">\n <ContentArea layout={activeService?.layout} />\n </div>\n )}\n </div>\n );\n}\n\nfunction ContentArea({ layout }: { layout?: \"default\" | \"full\" }) {\n if (layout === \"full\") {\n return (\n <div className=\"h-full w-full overflow-hidden\">\n <Outlet />\n </div>\n );\n }\n return (\n <ScrollArea className=\"h-full\">\n <main className=\"p-6\">\n <Outlet />\n </main>\n </ScrollArea>\n );\n}\n\nfunction PanelContent({ state }: { state: PanelOptions }) {\n return (\n <>\n {state.title ? (\n <SheetHeader>\n <SheetTitle>{state.title}</SheetTitle>\n {state.description && (\n <SheetDescription>{state.description}</SheetDescription>\n )}\n </SheetHeader>\n ) : (\n <SheetTitle className=\"sr-only\">Panel</SheetTitle>\n )}\n <SheetBody>{state.content}</SheetBody>\n </>\n );\n}\n","/**\n * Confirm Dialog\n *\n * Reusable confirmation dialog for actions that require user confirmation.\n * Used for discard changes, delete actions, etc.\n *\n * Wired into the shell via `initDialog` in `shell/api.ts` so modules can\n * trigger it imperatively with `dialog.confirm(opts)`.\n *\n * @module components/Common/ConfirmDialog\n */\n\nimport React from \"react\";\nimport { AlertTriangle } from \"lucide-react\";\nimport { Button } from \"@petrarca/sonnet-ui\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from \"@petrarca/sonnet-ui\";\n\nexport interface ConfirmDialogProps {\n /** Whether the dialog is open */\n open: boolean;\n\n /** Dialog title */\n title: string;\n\n /** Description shown below the title */\n description?: string;\n\n /** Confirm button label (default: \"Confirm\") */\n confirmLabel?: string;\n\n /** Cancel button label (default: \"Cancel\") */\n cancelLabel?: string;\n\n /**\n * Controls confirm button appearance.\n * \"destructive\" for irreversible actions (delete, revoke, etc.)\n */\n variant?: \"default\" | \"destructive\";\n\n /** Callback when user confirms */\n onConfirm: () => void;\n\n /** Callback when user cancels or closes dialog */\n onCancel: () => void;\n}\n\n/**\n * ConfirmDialog Component\n *\n * A reusable confirmation dialog backed by shadcn Dialog primitives.\n */\nexport function ConfirmDialog({\n open,\n title,\n description,\n confirmLabel = \"Confirm\",\n cancelLabel = \"Cancel\",\n variant = \"default\",\n onConfirm,\n onCancel,\n}: ConfirmDialogProps): React.ReactElement {\n return (\n <Dialog open={open} onOpenChange={(isOpen) => !isOpen && onCancel()}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>{title}</DialogTitle>\n {description && <DialogDescription>{description}</DialogDescription>}\n </DialogHeader>\n\n {variant === \"destructive\" && (\n <div className=\"flex gap-2 items-start\">\n <AlertTriangle\n size={20}\n className=\"text-destructive flex-shrink-0 mt-0.5\"\n />\n <p className=\"flex-1 text-sm text-muted-foreground\">\n This action cannot be undone.\n </p>\n </div>\n )}\n\n <DialogFooter>\n <Button variant=\"outline\" onClick={onCancel}>\n {cancelLabel}\n </Button>\n <Button variant={variant} onClick={onConfirm}>\n {confirmLabel}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n","import type { ReactNode } from \"react\";\n\n/**\n * TopBar -- persistent header across the entire application.\n *\n * A pure layout container. The shell provides the `<header>` element with\n * its sizing, background, and border. The consumer owns all content via\n * the `children` prop (composed through `ShellConfig.topBar`).\n */\ninterface TopBarProps {\n children?: ReactNode;\n}\n\nexport default function TopBar({ children }: TopBarProps) {\n return (\n <header className=\"h-12 shrink-0 border-b border-border flex items-center justify-between px-3 bg-background z-20\">\n {children}\n </header>\n );\n}\n","/**\n * ShellFooter — persistent footer bar across the entire application.\n *\n * A pure layout container, mirroring TopBar. The shell provides the\n * `<footer>` element with its sizing, background, and border. The\n * consumer owns all content via the `children` prop (composed through\n * `ShellConfig.footer`).\n */\nimport type { ReactNode } from \"react\";\n\nexport interface ShellFooterProps {\n children?: ReactNode;\n}\n\nexport default function ShellFooter({ children }: ShellFooterProps) {\n return (\n <footer className=\"h-8 shrink-0 border-t border-border flex items-center justify-between px-3 bg-background text-[11px] text-muted-foreground z-20\">\n {children}\n </footer>\n );\n}\n","/**\n * ShellRail — icon-rail + sub-nav-panel layout, auto-wired from the\n * module registry and shell navigation context.\n *\n * Reads active service state from ShellNavigationContext (provided by\n * AppShell) and module list from ShellModulesContext. No props required.\n *\n * For custom layouts, compose IconRail, RailIcon, RailSeparator, and\n * SubNavPanel directly.\n */\nimport React, { useMemo } from \"react\";\nimport { IconRail, RailIcon, RailSeparator } from \"./IconRail\";\nimport { SubNavPanel } from \"./SubNavPanel\";\nimport { useShellModules } from \"./shellModules\";\nimport { useShellNavigation } from \"./shellNavigation\";\nimport { useShellConfig } from \"./shellConfig\";\nimport { evaluateModule, resolveCapabilityPolicy } from \"./capabilities\";\nimport type { ShellModule } from \"./types\";\n\nexport function ShellRail(): React.ReactElement {\n const { mainModules, bottomModules } = useShellModules();\n const { resolveCapability, capabilityPolicy } = useShellConfig();\n const {\n activeService,\n sidePaneModuleId,\n subNavCollapsed,\n onToggleSubNav,\n onServiceSelect,\n } = useShellNavigation();\n\n const isActive = (id: string) =>\n activeService?.id === id || sidePaneModuleId === id;\n\n const policy = useMemo(\n () => resolveCapabilityPolicy(capabilityPolicy),\n [capabilityPolicy],\n );\n\n const renderModule = (service: ShellModule): React.ReactElement | null => {\n const { effect, reason } = evaluateModule(\n service,\n \"rail\",\n resolveCapability,\n policy,\n );\n // \"redirect\" has no rail rendering — treat as hidden.\n if (effect === \"hidden\" || effect === \"redirect\") return null;\n const disabled = effect === \"disabled\";\n return (\n <RailIcon\n key={service.id}\n icon={service.icon}\n label={service.label}\n active={isActive(service.id)}\n onClick={() => onServiceSelect(service.id)}\n disabled={disabled}\n tooltip={\n disabled && reason ? `${service.label} — ${reason}` : undefined\n }\n />\n );\n };\n\n return (\n <>\n <IconRail>\n <div className=\"flex-1 flex flex-col items-center gap-1 overflow-y-auto\">\n {mainModules.map(renderModule)}\n </div>\n\n <RailSeparator />\n <div className=\"flex flex-col items-center gap-1\">\n {bottomModules.map(renderModule)}\n </div>\n </IconRail>\n\n {activeService && activeService.navigation.length > 0 && (\n <SubNavPanel\n service={activeService}\n collapsed={subNavCollapsed}\n onToggleCollapse={onToggleSubNav}\n />\n )}\n </>\n );\n}\n","/**\n * IconRail primitives — composable building blocks for the narrow\n * vertical icon strip.\n *\n * - IconRail: the container (<nav> with flex column, border, bg)\n * - RailIcon: a single icon button with tooltip\n * - RailSeparator: divider between groups\n *\n * For the auto-wired layout, use ShellRail instead.\n */\nimport React from \"react\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport { Button, Separator } from \"@petrarca/sonnet-ui\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"@petrarca/sonnet-ui\";\nimport type { LucideIcon } from \"lucide-react\";\n\n// IconRail container\n\nexport interface IconRailProps {\n children: React.ReactNode;\n className?: string;\n}\n\n/** Narrow vertical nav container for RailIcon items. */\nexport function IconRail({\n children,\n className,\n}: IconRailProps): React.ReactElement {\n return (\n <nav\n className={cn(\n \"w-14 shrink-0 border-r bg-muted flex flex-col items-center py-2 gap-1\",\n className,\n )}\n >\n {children}\n </nav>\n );\n}\n\n// RailIcon\n\nexport interface RailIconProps {\n icon: LucideIcon;\n label: string;\n active?: boolean;\n onClick?: () => void;\n /** Render greyed and non-interactive (e.g. a capability requirement is unmet). */\n disabled?: boolean;\n /** Optional tooltip override (e.g. why the item is disabled). Defaults to `label`. */\n tooltip?: string;\n}\n\n/** Single icon button with tooltip inside an IconRail. */\nexport function RailIcon({\n icon: Icon,\n label,\n active = false,\n onClick,\n disabled = false,\n tooltip,\n}: RailIconProps): React.ReactElement {\n return (\n <Tooltip delayDuration={0}>\n <TooltipTrigger asChild>\n {/* aria-disabled (not native `disabled`) keeps the trigger focusable so\n the tooltip explaining *why* remains discoverable. */}\n <Button\n variant=\"ghost\"\n size=\"compact\"\n aria-disabled={disabled || undefined}\n onClick={disabled ? undefined : onClick}\n className={cn(\n \"h-10 w-10 rounded-lg transition-colors\",\n disabled\n ? \"text-muted-foreground/40 cursor-default hover:bg-transparent\"\n : active\n ? \"bg-background text-foreground shadow-sm\"\n : \"text-muted-foreground hover:text-foreground hover:bg-muted-foreground/10\",\n )}\n >\n <Icon className=\"h-5 w-5\" />\n <span className=\"sr-only\">{label}</span>\n </Button>\n </TooltipTrigger>\n <TooltipContent side=\"right\" sideOffset={8}>\n {tooltip ?? label}\n </TooltipContent>\n </Tooltip>\n );\n}\n\n// RailSeparator\n\n/** Visual divider between icon groups inside an IconRail. */\nexport function RailSeparator(): React.ReactElement {\n return <Separator className=\"w-6 my-1\" />;\n}\n","/**\n * SubNavPanel — contextual secondary navigation for the selected service.\n *\n * Shows the service label at top, then grouped nav links using the shared\n * SidebarGroup / SidebarItem primitives. If other modules contribute links\n * via the \"<moduleId>.nav\" extension point, they are appended.\n *\n * Supports a collapsed state (thin strip with expand chevron).\n */\nimport { useMemo } from \"react\";\nimport { ChevronsLeft, ChevronsRight } from \"lucide-react\";\nimport { ScrollArea } from \"@petrarca/sonnet-ui\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"@petrarca/sonnet-ui\";\nimport type { ShellModule, NavGroup } from \"./types\";\nimport { useExtensionPoint } from \"./hooks\";\nimport { SidebarGroup } from \"./SidebarGroup\";\nimport { SidebarItem } from \"./SidebarItem\";\n\nexport interface SubNavPanelProps {\n service: ShellModule;\n collapsed: boolean;\n onToggleCollapse: () => void;\n}\n\n// Merge contributed nav links from other modules.\nfunction useMergedNavigation(service: ShellModule): NavGroup[] {\n const contributions = useExtensionPoint(`${service.id}.nav`);\n return useMemo(() => {\n if (contributions.length === 0) return service.navigation;\n\n const contributed: NavGroup = {\n id: `${service.id}-contributed`,\n links: contributions.map((c) => ({\n id: c.extensionPoint + \".\" + c.label.toLowerCase().replace(/\\s+/g, \"-\"),\n label: c.label,\n path: c.path,\n })),\n };\n\n return [...service.navigation, contributed];\n }, [service, contributions]);\n}\n\nexport function SubNavPanel({\n service,\n collapsed,\n onToggleCollapse,\n}: SubNavPanelProps) {\n const mergedNavigation = useMergedNavigation(service);\n\n if (collapsed) {\n return (\n <aside className=\"shrink-0 border-r bg-background flex flex-col items-center pt-2.5\">\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n className=\"text-muted-foreground/50 hover:text-muted-foreground transition-colors p-1\"\n onClick={onToggleCollapse}\n >\n <ChevronsRight className=\"h-4 w-4\" />\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"right\">Expand navigation</TooltipContent>\n </Tooltip>\n </aside>\n );\n }\n\n return (\n <aside className=\"w-52 shrink-0 border-r bg-background flex flex-col\">\n {/* Service header with collapse toggle */}\n <div className=\"h-10 shrink-0 flex items-center justify-between px-4\">\n <span className=\"text-sm font-semibold text-foreground\">\n {service.label}\n </span>\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n className=\"text-muted-foreground/40 hover:text-muted-foreground transition-colors p-0.5\"\n onClick={onToggleCollapse}\n >\n <ChevronsLeft className=\"h-3.5 w-3.5\" />\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"right\">Collapse navigation</TooltipContent>\n </Tooltip>\n </div>\n\n {/* Nav groups — reuses SidebarGroup / SidebarItem primitives */}\n <ScrollArea className=\"flex-1\">\n <nav className=\"px-1.5 pb-4 space-y-2\">\n {mergedNavigation.map((group) => (\n <SidebarGroup\n key={group.id}\n heading={group.heading}\n collapsible={group.collapsible}\n >\n {group.links.map((link) => (\n <SidebarItem\n key={link.path}\n label={link.label}\n path={link.path}\n badge={link.badge}\n />\n ))}\n </SidebarGroup>\n ))}\n </nav>\n </ScrollArea>\n </aside>\n );\n}\n","/**\n * Shell hooks -- reactive APIs for modules.\n *\n * Import path: @/shell/hooks\n */\nimport { useEffect, useMemo, useRef } from \"react\";\nimport { events } from \"./api\";\nimport { useShellModules } from \"./shellModules\";\nimport type { Contribution, ShellModule, ShellEventMap } from \"./types\";\n\n/**\n * Get sorted contributions for a named extension point.\n *\n * Returns all contributions registered by any module for the given\n * extension point, sorted by `order` (ascending).\n *\n * @example\n * ```tsx\n * const tabs = useExtensionPoint(\"organization-detail\");\n * ```\n */\nexport function useExtensionPoint(name: string): Contribution[] {\n const { getExtensionPoint } = useShellModules();\n return useMemo(() => getExtensionPoint(name), [getExtensionPoint, name]);\n}\n\n/**\n * Get the list of visible service modules (excludes hidden and bottom-pinned).\n *\n * Useful for building overviews like the home page.\n */\nexport function useMainModules(): ShellModule[] {\n const { mainModules } = useShellModules();\n return mainModules;\n}\n\n/**\n * Subscribe to a shell event, auto-unsubscribing on unmount.\n *\n * The handler reference is stabilized via useRef so that the\n * subscription is not torn down and recreated on every render.\n *\n * @example\n * ```tsx\n * useShellEvent(\"schema-definition:changed\", (payload) => {\n * queryClient.invalidateQueries({ queryKey: [\"my-key\"] });\n * });\n * ```\n */\nexport function useShellEvent<K extends keyof ShellEventMap>(\n key: K,\n handler: (payload: ShellEventMap[K]) => void,\n): void {\n const handlerRef = useRef(handler);\n handlerRef.current = handler;\n\n useEffect(() => {\n return events.on(key, (payload) => handlerRef.current(payload));\n }, [key]);\n}\n","/**\n * Shell API -- imperative domain capabilities for modules.\n *\n * Import path: @/shell/api\n *\n * Grouped by domain: notification, dialog, navigation, panel, events.\n */\nimport type { ReactNode } from \"react\";\nimport { toast } from \"sonner\";\nimport { warnLog } from \"@petrarca/sonnet-core\";\nimport type { ShellEventMap } from \"./types\";\nimport * as eventBus from \"./eventBus\";\n\n// notification\n\ninterface PromiseOptions<T> {\n loading: string;\n success: string | ((data: T) => string);\n error: string | ((err: unknown) => string);\n}\n\nexport const notification = {\n success(message: string) {\n toast.success(message);\n },\n error(message: string) {\n toast.error(message);\n },\n warning(message: string) {\n toast.warning(message);\n },\n info(message: string) {\n toast.info(message);\n },\n promise<T>(promise: Promise<T>, opts: PromiseOptions<T>) {\n return toast.promise(promise, opts);\n },\n dismiss(id?: string | number) {\n toast.dismiss(id);\n },\n};\n\n// dialog\n\n// The shell mounts a single ConfirmDialog instance in AppShell and injects\n// its open function here via initDialog(). Modules call dialog.confirm()\n// without knowing where the implementation lives -- federation-safe, same\n// pattern as navigation and panel.\n\nexport interface ConfirmOptions {\n title: string;\n description?: string;\n confirmLabel?: string;\n cancelLabel?: string;\n variant?: \"default\" | \"destructive\";\n}\n\ntype DialogConfirmFn = (opts: ConfirmOptions) => Promise<boolean>;\n\nlet _dialogConfirm: DialogConfirmFn | null = null;\n\n/**\n * Called by the shell during initialization to inject the confirm dialog.\n * Not part of the public module API -- only the shell calls this.\n */\nexport function initDialog(confirmFn: DialogConfirmFn) {\n _dialogConfirm = confirmFn;\n}\n\nexport const dialog = {\n /**\n * Show a confirmation dialog. Returns true if confirmed, false if cancelled.\n */\n confirm(opts: ConfirmOptions): Promise<boolean> {\n if (_dialogConfirm) {\n return _dialogConfirm(opts);\n }\n warnLog(\"dialog.confirm: shell not initialized yet.\");\n return Promise.resolve(false);\n },\n};\n\n// navigation\n\n// The shell injects the navigate function and command menu opener at startup\n// via initNavigation(). Modules call navigation.goTo() etc. without knowing\n// where the implementation comes from -- works with both monorepo and\n// Module Federation (host provides the injector, remotes consume the API).\n\ntype NavigateFn = (path: string) => void;\ntype CommandMenuFn = () => void;\ntype FeatureLookupFn = (featureId: string) => string | null;\n\nlet _navigate: NavigateFn | null = null;\nlet _openCommandMenu: CommandMenuFn | null = null;\nlet _lookupFeature: FeatureLookupFn | null = null;\n\n/**\n * Called by the shell during initialization to inject router + command menu.\n * Not part of the public module API -- only the shell calls this.\n */\nexport function initNavigation(\n navigateFn: NavigateFn,\n openCommandMenuFn: CommandMenuFn,\n) {\n _navigate = navigateFn;\n _openCommandMenu = openCommandMenuFn;\n}\n\n/**\n * Called by the shell during initialization to inject the feature lookup.\n * Resolves a stable feature id (e.g. \"auditing.audit-events\") to a path.\n * Not part of the public module API -- only the shell calls this.\n */\nexport function initFeatureNav(lookupFn: FeatureLookupFn) {\n _lookupFeature = lookupFn;\n}\n\nexport const navigation = {\n /** Navigate to a path within the shell. */\n goTo(path: string) {\n if (_navigate) {\n _navigate(path);\n } else {\n warnLog(\"navigation.goTo: shell not initialized yet.\");\n }\n },\n /**\n * Navigate to a feature by its stable identifier (e.g. \"auditing.audit-events\").\n * The path is resolved from the module registry at call time, so it stays\n * correct even if routes are reorganised.\n */\n goToFeature(featureId: string) {\n if (!_navigate || !_lookupFeature) {\n warnLog(\"navigation.goToFeature: shell not initialized yet.\");\n return;\n }\n const path = _lookupFeature(featureId);\n if (path) {\n _navigate(path);\n } else {\n warnLog(\"navigation.goToFeature: unknown feature id '{}'.\", featureId);\n }\n },\n /** Open the Cmd+K command menu. */\n openCommandMenu() {\n if (_openCommandMenu) {\n _openCommandMenu();\n } else {\n warnLog(\"navigation.openCommandMenu: shell not initialized yet.\");\n }\n },\n /** Go back in browser history. */\n back() {\n window.history.back();\n },\n};\n\n// panel\n\n// The shell owns the slide-over panel (Sheet). Modules request it via\n// panel.open() with content to render. The shell renders that content inside\n// the panel. Same injection pattern as navigation -- federation-safe.\n\nexport interface PanelOptions {\n /**\n * Title shown in the panel header. When omitted the header is visually\n * hidden (the content owns its own header) but a screen-reader-only\n * title is still rendered for accessibility.\n */\n title?: string;\n /** React content to render inside the panel */\n content: ReactNode;\n /** Optional description below the title */\n description?: string;\n /**\n * Panel width token.\n *\n * - \"narrow\" -- 480px -- quick actions, simple single-field forms\n * - \"default\" -- 640px -- standard entity forms (default when omitted)\n * - \"wide\" -- 800px -- forms with embedded tables or complex layouts\n * - \"half\" -- 50vw -- split-screen inspection, side-by-side context\n * - \"full\" -- 100vw -- immersive editing, full-width canvases\n *\n * Legacy values \"lg\", \"1/3\", \"1/2\" are kept for backward compatibility\n * and map to \"default\" (640px), 33vw, and \"half\" (50vw) respectively.\n */\n width?:\n | \"narrow\"\n | \"default\"\n | \"wide\"\n | \"half\"\n | \"full\"\n | \"lg\"\n | \"1/3\"\n | \"1/2\";\n /**\n * Vertical coverage of the panel.\n * - \"below-header\" (default): panel starts below the TopBar, keeping it visible.\n * - \"full\": panel covers the full viewport height including the TopBar.\n */\n coverage?: \"below-header\" | \"full\";\n /**\n * Allow the user to drag the left edge of the panel to resize it.\n * Defaults to false. When true, the fixed `width` token is used as the\n * initial width and the panel width is controlled dynamically.\n */\n resizable?: boolean;\n /**\n * Minimum width in pixels when resizable. Defaults to 240.\n * Ignored when resizable is false.\n */\n minWidth?: number;\n /**\n * Maximum width in pixels when resizable. Defaults to 90% of viewport width.\n * Ignored when resizable is false.\n */\n maxWidth?: number;\n /** Called after the panel finishes closing. Use to restore focus to the triggering element. */\n onClose?: () => void;\n}\n\ntype PanelOpenFn = (opts: PanelOptions) => void;\ntype PanelCloseFn = () => void;\n\nlet _panelOpen: PanelOpenFn | null = null;\nlet _panelClose: PanelCloseFn | null = null;\n\n/**\n * Called by the shell during initialization to inject panel controls.\n * Not part of the public module API -- only the shell calls this.\n */\nexport function initPanel(openFn: PanelOpenFn, closeFn: PanelCloseFn) {\n _panelOpen = openFn;\n _panelClose = closeFn;\n}\n\nexport const panel = {\n /** Open the shell panel with content rendered inside. */\n open(opts: PanelOptions) {\n if (_panelOpen) {\n _panelOpen(opts);\n } else {\n warnLog(\"panel.open: shell not initialized yet.\");\n }\n },\n /** Close the panel. */\n close() {\n if (_panelClose) {\n _panelClose();\n } else {\n warnLog(\"panel.close: shell not initialized yet.\");\n }\n },\n};\n\n// sidePane\n\n// The shell owns the side pane (SidePane component in AppShell). Modules\n// request it via sidePane.open() with content and sizing options. The pane\n// sits inline beside the content area -- the main view shrinks rather than\n// being overlaid. Same injection pattern as panel -- federation-safe.\n\nimport type { SidePaneOptions } from \"./sidePaneState\";\nexport type { SidePaneOptions };\n\ntype SidePaneOpenFn = (opts: SidePaneOptions) => void;\ntype SidePaneCloseFn = () => void;\ntype SidePaneIsOpenFn = () => boolean;\ntype SidePaneActiveModuleIdFn = () => string | null;\ntype SidePaneSetFullWidthFn = (fullWidth: boolean) => void;\n\nlet _sidePaneOpen: SidePaneOpenFn | null = null;\nlet _sidePaneClose: SidePaneCloseFn | null = null;\nlet _sidePaneIsOpen: SidePaneIsOpenFn | null = null;\nlet _sidePaneActiveModuleId: SidePaneActiveModuleIdFn | null = null;\nlet _sidePaneSetFullWidth: SidePaneSetFullWidthFn | null = null;\n\n/**\n * Called by the shell during initialization to inject side pane controls.\n * Not part of the public module API -- only the shell calls this.\n */\nexport function initSidePane(\n openFn: SidePaneOpenFn,\n closeFn: SidePaneCloseFn,\n isOpenFn: SidePaneIsOpenFn,\n activeModuleIdFn: SidePaneActiveModuleIdFn,\n setFullWidthFn?: SidePaneSetFullWidthFn,\n) {\n _sidePaneOpen = openFn;\n _sidePaneClose = closeFn;\n _sidePaneIsOpen = isOpenFn;\n _sidePaneActiveModuleId = activeModuleIdFn;\n _sidePaneSetFullWidth = setFullWidthFn ?? null;\n}\n\nexport const sidePane = {\n /** Open the side pane with the given content and sizing options. */\n open(opts: SidePaneOptions) {\n if (_sidePaneOpen) {\n _sidePaneOpen(opts);\n } else {\n warnLog(\"sidePane.open: shell not initialized yet.\");\n }\n },\n /** Close the side pane. */\n close() {\n if (_sidePaneClose) {\n _sidePaneClose();\n } else {\n warnLog(\"sidePane.close: shell not initialized yet.\");\n }\n },\n /**\n * Toggle the side pane.\n *\n * If the pane is closed, opens it with opts.\n * If the pane is open with the same moduleId, closes it.\n * If the pane is open with a different moduleId, replaces it with opts.\n */\n toggle(opts: SidePaneOptions) {\n if (\n !_sidePaneIsOpen ||\n !_sidePaneActiveModuleId ||\n !_sidePaneOpen ||\n !_sidePaneClose\n ) {\n warnLog(\"sidePane.toggle: shell not initialized yet.\");\n return;\n }\n if (_sidePaneIsOpen() && _sidePaneActiveModuleId() === opts.moduleId) {\n _sidePaneClose();\n } else {\n _sidePaneOpen(opts);\n }\n },\n /** Returns true when the pane is currently open. */\n isOpen(): boolean {\n return _sidePaneIsOpen ? _sidePaneIsOpen() : false;\n },\n /** Returns the moduleId of the currently open pane, or null. */\n activeModuleId(): string | null {\n return _sidePaneActiveModuleId ? _sidePaneActiveModuleId() : null;\n },\n /**\n * Expand or collapse the pane to fill the full content area.\n *\n * When true the pane takes flex-1 and hides the main route content.\n * Use for full-screen tool views (schema viewer, form editors).\n * Call setFullWidth(false) to restore normal inline sizing.\n */\n setFullWidth(fullWidth: boolean) {\n if (_sidePaneSetFullWidth) {\n _sidePaneSetFullWidth(fullWidth);\n } else {\n warnLog(\"sidePane.setFullWidth: shell not initialized yet.\");\n }\n },\n};\n\n// fullscreen\n\n// The shell owns the fullscreen overlay. Modules request it via\n// fullscreen.enter(content) and exit via fullscreen.exit(). The shell renders\n// the content in a fixed inset-0 z-50 overlay, covering all shell chrome.\n// Same injection pattern as panel -- federation-safe.\n\nexport interface FullscreenOptions {\n /** React content to render inside the fullscreen overlay. */\n content: ReactNode;\n}\n\ntype FullscreenEnterFn = (opts: FullscreenOptions) => void;\ntype FullscreenExitFn = () => void;\n\nlet _fullscreenEnter: FullscreenEnterFn | null = null;\nlet _fullscreenExit: FullscreenExitFn | null = null;\n\n/**\n * Called by the shell during initialization to inject fullscreen controls.\n * Not part of the public module API -- only the shell calls this.\n */\nexport function initFullscreen(\n enterFn: FullscreenEnterFn,\n exitFn: FullscreenExitFn,\n) {\n _fullscreenEnter = enterFn;\n _fullscreenExit = exitFn;\n}\n\nexport const fullscreen = {\n /** Enter fullscreen mode, rendering content over all shell chrome. */\n enter(opts: FullscreenOptions) {\n if (_fullscreenEnter) {\n _fullscreenEnter(opts);\n } else {\n warnLog(\"fullscreen.enter: shell not initialized yet.\");\n }\n },\n /** Exit fullscreen mode, restoring the normal shell layout. */\n exit() {\n if (_fullscreenExit) {\n _fullscreenExit();\n } else {\n warnLog(\"fullscreen.exit: shell not initialized yet.\");\n }\n },\n};\n\n// events\n\ntype Unsubscribe = () => void;\n\nexport const events = {\n /** Subscribe to an event. Returns an unsubscribe function. */\n on<K extends keyof ShellEventMap>(\n key: K,\n handler: (payload: ShellEventMap[K]) => void,\n ): Unsubscribe {\n return eventBus.on(key as string, handler as (payload: unknown) => void);\n },\n\n /** Subscribe, auto-unsubscribing after the first emission. */\n once<K extends keyof ShellEventMap>(\n key: K,\n handler: (payload: ShellEventMap[K]) => void,\n ): Unsubscribe {\n return eventBus.once(key as string, handler as (payload: unknown) => void);\n },\n\n /** Emit an event. Handlers run asynchronously (microtask). */\n emit<K extends keyof ShellEventMap>(key: K, payload: ShellEventMap[K]): void {\n eventBus.emit(key as string, payload);\n },\n};\n","/**\n * Shell event bus -- in-memory pub/sub for cross-module communication.\n *\n * The bus is untyped internally (operates on strings and unknown payloads).\n * Type safety is provided by the public API layer in shell/api.ts, which\n * constrains keys and payloads via the ShellEventMap interface.\n *\n * Mirrors the server-side EventBus pattern (fire-and-forget, error isolation)\n * adapted for the browser's single-threaded model.\n */\nimport { devLog, warnLog } from \"@petrarca/sonnet-core\";\n\ntype Handler = (payload: unknown) => void;\ntype Unsubscribe = () => void;\n\nconst listeners = new Map<string, Set<Handler>>();\n\n/** Subscribe to an event key. Returns an unsubscribe function. */\nexport function on(key: string, handler: Handler): Unsubscribe {\n let set = listeners.get(key);\n if (!set) {\n set = new Set();\n listeners.set(key, set);\n }\n set.add(handler);\n devLog(`[shell:event] on \"${key}\" (${set.size} handler(s))`);\n return () => {\n set!.delete(handler);\n if (set!.size === 0) listeners.delete(key);\n devLog(`[shell:event] off \"${key}\" (${set!.size} handler(s))`);\n };\n}\n\n/** Subscribe to an event key, auto-unsubscribing after the first emission. */\nexport function once(key: string, handler: Handler): Unsubscribe {\n const unsubscribe = on(key, (payload) => {\n unsubscribe();\n handler(payload);\n });\n return unsubscribe;\n}\n\n/** Emit an event. Handlers run in microtasks (non-blocking, error-isolated). */\nexport function emit(key: string, payload: unknown): void {\n const set = listeners.get(key);\n const count = set?.size ?? 0;\n devLog(`[shell:event] emit \"${key}\"`, payload, `(${count} handler(s))`);\n if (!set || count === 0) return;\n for (const handler of set) {\n Promise.resolve().then(() => {\n try {\n handler(payload);\n } catch (err) {\n warnLog(`[shell:event] handler error \"${key}\":`, err);\n }\n });\n }\n}\n","/**\n * Shell modules context.\n *\n * Provides the module registry to shell components (IconRail,\n * CommandMenu, hooks) without requiring them to import from the\n * app-specific modules/registry.ts. AppShell injects the registry;\n * children consume it via useShellModules().\n */\nimport { createContext, useContext } from \"react\";\nimport type { ModuleRegistry } from \"./createModuleRegistry\";\n\nexport const ShellModulesContext = createContext<ModuleRegistry | null>(null);\n\n/**\n * Read the module registry from context.\n * Must be called within an AppShell (which provides the context).\n */\nexport function useShellModules(): ModuleRegistry {\n const registry = useContext(ShellModulesContext);\n if (!registry) {\n throw new Error(\"useShellModules must be used within an AppShell\");\n }\n return registry;\n}\n","/** Labeled, optionally collapsible section within a Sidebar. */\nimport React, { useState } from \"react\";\nimport { ChevronDown } from \"lucide-react\";\nimport { cn } from \"@petrarca/sonnet-core\";\n\nexport interface SidebarGroupProps {\n heading?: string;\n collapsible?: boolean;\n defaultOpen?: boolean;\n /** Render a border separator below this group. */\n separator?: boolean;\n children: React.ReactNode;\n}\n\n// Section heading with optional collapse toggle.\nfunction GroupHeading({\n heading,\n canCollapse,\n open,\n onToggle,\n}: {\n heading: string;\n canCollapse: boolean;\n open: boolean;\n onToggle: () => void;\n}) {\n return (\n <button\n type=\"button\"\n onClick={canCollapse ? onToggle : undefined}\n className={cn(\n \"flex w-full items-center gap-1 px-2 py-1.5\",\n \"text-[11px] font-semibold uppercase tracking-widest text-muted-foreground/70\",\n canCollapse ? \"hover:text-foreground cursor-pointer\" : \"cursor-default\",\n )}\n >\n {canCollapse && (\n <ChevronDown\n className={cn(\"h-3 w-3 transition-transform\", !open && \"-rotate-90\")}\n />\n )}\n <span>{heading}</span>\n </button>\n );\n}\n\nexport function SidebarGroup({\n heading,\n collapsible = false,\n defaultOpen = true,\n separator = false,\n children,\n}: SidebarGroupProps): React.ReactElement {\n const [open, setOpen] = useState(defaultOpen);\n const canCollapse = collapsible && !!heading;\n\n return (\n <div className={cn(separator && \"border-b border-border pb-2\")}>\n {heading && (\n <GroupHeading\n heading={heading}\n canCollapse={canCollapse}\n open={open}\n onToggle={() => setOpen((v) => !v)}\n />\n )}\n {(!canCollapse || open) && <ul className=\"space-y-0.5\">{children}</ul>}\n </div>\n );\n}\n","/** Single navigation row inside a Sidebar — icon + label + optional trailing slot. */\nimport React from \"react\";\nimport { Link, useLocation } from \"react-router-dom\";\nimport { ChevronRight } from \"lucide-react\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport type { LucideIcon } from \"lucide-react\";\n\nexport interface SidebarItemProps {\n icon?: LucideIcon;\n label: string;\n path: string;\n badge?: string | number;\n indent?: number;\n expandable?: boolean;\n expanded?: boolean;\n onToggle?: () => void;\n onClick?: () => void;\n}\n\n// Trailing badge or expand chevron rendered after the label.\nfunction ItemTrailing({\n badge,\n expandable,\n expanded,\n onToggle,\n}: Pick<SidebarItemProps, \"badge\" | \"expandable\" | \"expanded\" | \"onToggle\">) {\n if (badge != null) {\n return (\n <span className=\"inline-flex items-center rounded-full bg-muted px-1.5 h-[18px] text-[10px] tabular-nums text-muted-foreground\">\n {badge}\n </span>\n );\n }\n if (expandable) {\n const handleClick = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onToggle?.();\n };\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n className=\"p-0.5 text-muted-foreground hover:text-foreground\"\n >\n <ChevronRight\n className={cn(\n \"h-3 w-3 transition-transform\",\n expanded && \"rotate-90\",\n )}\n />\n </button>\n );\n }\n return null;\n}\n\nexport function SidebarItem({\n icon: Icon,\n label,\n path,\n badge,\n indent = 0,\n expandable = false,\n expanded = false,\n onToggle,\n onClick,\n}: SidebarItemProps): React.ReactElement {\n const { pathname } = useLocation();\n const isActive = pathname === path;\n const style =\n indent > 0 ? { paddingLeft: `${indent * 16 + 8}px` } : undefined;\n\n return (\n <li>\n <Link\n to={path}\n onClick={onClick}\n style={style}\n className={cn(\n \"flex items-center gap-2 rounded px-2 py-1.5 text-[13px] font-medium transition-colors select-none\",\n isActive\n ? \"bg-accent text-accent-foreground\"\n : \"text-muted-foreground hover:text-foreground hover:bg-accent/50\",\n )}\n >\n {Icon && <Icon className=\"h-4 w-4 shrink-0\" />}\n <span className=\"min-w-0 flex-1 truncate\">{label}</span>\n <ItemTrailing\n badge={badge}\n expandable={expandable}\n expanded={expanded}\n onToggle={onToggle}\n />\n </Link>\n </li>\n );\n}\n","/**\n * Shell navigation context — provides active service state and interaction\n * handlers to ShellRail, SubNavPanel, and any custom navigation components.\n *\n * Provided by AppShell. Consumed by ShellRail (and available to consumers\n * who build custom navigation layouts).\n */\nimport { createContext, useContext } from \"react\";\nimport type { ShellModule } from \"./types\";\n\nexport interface ShellNavigationState {\n activeService: ShellModule | null;\n sidePaneModuleId: string | null;\n subNavCollapsed: boolean;\n onToggleSubNav: () => void;\n onServiceSelect: (id: string) => void;\n}\n\nexport const ShellNavigationContext =\n createContext<ShellNavigationState | null>(null);\n\n/** Read shell navigation state. Must be used within AppShell. */\nexport function useShellNavigation(): ShellNavigationState {\n const ctx = useContext(ShellNavigationContext);\n if (!ctx) {\n throw new Error(\"useShellNavigation must be used within AppShell\");\n }\n return ctx;\n}\n","/**\n * Shell configuration types and context.\n *\n * ShellConfig is intentionally minimal. The shell provides layout chrome\n * (TopBar header, IconRail, SubNavPanel, CommandMenu) but does not own\n * any app-specific content. The consumer composes the TopBar content --\n * logo, environment selector, search trigger, user menu -- via the\n * `topBar` ReactNode slot using building blocks exported from the shell.\n */\nimport { createContext, useContext, type ReactNode } from \"react\";\nimport type { CapabilityPolicy, CapabilityResolver } from \"./types\";\n\n// Top-level shell configuration.\n\nexport interface ShellConfig {\n /**\n * Content rendered inside the TopBar header. The shell provides the\n * `<header>` element with its sizing and border; the consumer owns\n * everything inside it.\n *\n * Compose this using building blocks like `SearchTrigger` and\n * `UserMenu` (exported from the shell) alongside any app-specific\n * components.\n */\n topBar?: ReactNode;\n\n /**\n * Content rendered inside the ShellFooter. The shell provides the\n * `<footer>` element with its sizing and border; the consumer owns\n * everything inside it.\n *\n * Common uses: status bar, sync indicators, version info, quick actions.\n * Omit to render no footer.\n */\n footer?: ReactNode;\n\n /**\n * Evaluates a module capability (from `ShellModule.requires`) for gating the\n * icon rail / command menu / routes. Absent ⇒ no gating (all modules\n * available). See docs/design/module-capabilities.md.\n */\n resolveCapability?: CapabilityResolver;\n\n /**\n * Sparse overrides for the (unmet reason kind, surface) → effect matrix,\n * merged over the shell defaults. Lets the app tune hide-vs-disable per\n * reason kind and surface without touching modules.\n */\n capabilityPolicy?: CapabilityPolicy;\n}\n\n// Context\n\nexport const ShellConfigContext = createContext<ShellConfig | null>(null);\n\n/**\n * Read the shell configuration from context.\n * Must be called within a ShellConfigProvider.\n */\nexport function useShellConfig(): ShellConfig {\n const config = useContext(ShellConfigContext);\n if (!config) {\n throw new Error(\"useShellConfig must be used within a ShellConfigProvider\");\n }\n return config;\n}\n","/**\n * Capability gating — evaluate a module's requirements into a per-surface\n * presentation effect.\n *\n * See docs/design/module-capabilities.md. The shell is domain-agnostic: a\n * module declares `requires` capabilities, the app provides a\n * `CapabilityResolver`, and the shell maps the resolver's semantic reason kind\n * to an `Effect` via a surface-aware policy matrix.\n */\nimport { warnLog } from \"@petrarca/sonnet-core\";\nimport type {\n CapabilityPolicy,\n CapabilityResolver,\n Effect,\n ShellModule,\n Surface,\n UnmetKind,\n} from \"./types\";\n\n/** Default (kind, surface) → effect matrix. App overrides are merged over this. */\nexport const DEFAULT_CAPABILITY_POLICY: Record<\n UnmetKind,\n Record<Surface, Effect>\n> = {\n \"missing-state\": { rail: \"disabled\", command: \"disabled\", route: \"redirect\" },\n \"not-authorized\": { rail: \"hidden\", command: \"hidden\", route: \"redirect\" },\n \"not-authorized-soft\": {\n rail: \"disabled\",\n command: \"disabled\",\n route: \"redirect\",\n },\n \"feature-off\": { rail: \"hidden\", command: \"disabled\", route: \"redirect\" },\n error: { rail: \"hidden\", command: \"hidden\", route: \"redirect\" },\n};\n\n/** Strictness order — the most restrictive effect wins when folding requirements. */\nconst EFFECT_RANK: Record<Effect, number> = {\n hidden: 3,\n redirect: 2,\n disabled: 1,\n visible: 0,\n};\n\n/** Merge a sparse app override over the default matrix. */\nexport function resolveCapabilityPolicy(\n override?: CapabilityPolicy,\n): Record<UnmetKind, Record<Surface, Effect>> {\n if (!override) return DEFAULT_CAPABILITY_POLICY;\n const merged = {} as Record<UnmetKind, Record<Surface, Effect>>;\n for (const kind of Object.keys(DEFAULT_CAPABILITY_POLICY) as UnmetKind[]) {\n merged[kind] = {\n ...DEFAULT_CAPABILITY_POLICY[kind],\n ...(override[kind] ?? {}),\n };\n }\n return merged;\n}\n\nexport interface ModuleEffect {\n effect: Effect;\n /** Hint from the first most-restrictive unmet capability (for tooltips). */\n reason?: string;\n}\n\n/**\n * Fold a single unmet-capability result into the running accumulator.\n * Extracted to keep evaluateModule below the cyclomatic-complexity limit.\n */\nfunction foldUnmet(\n effect: Effect,\n resultReason: string | undefined,\n acc: ModuleEffect,\n): ModuleEffect {\n const rank = EFFECT_RANK[effect];\n const worstRank = EFFECT_RANK[acc.effect];\n if (rank > worstRank) {\n // Strictly more restrictive — take this effect and its reason.\n return { effect, reason: resultReason };\n }\n if (rank === worstRank && !acc.reason && resultReason) {\n // Same restrictiveness; take the first available reason at this rank.\n return { effect: acc.effect, reason: resultReason };\n }\n return acc;\n}\n\n/**\n * Evaluate a module's requirements for a given surface.\n *\n * Returns `visible` when there are no requirements or all are met. Otherwise\n * each unmet capability maps (kind, surface) → effect and the most restrictive\n * wins (hidden > redirect > disabled > visible). When capabilities share the\n * same effect rank, the first one with a non-empty reason provides the tooltip.\n */\nexport function evaluateModule(\n module: ShellModule,\n surface: Surface,\n resolve: CapabilityResolver | undefined,\n policy: Record<UnmetKind, Record<Surface, Effect>>,\n): ModuleEffect {\n const capabilities = module.requires;\n if (!capabilities || capabilities.length === 0) return { effect: \"visible\" };\n // No resolver ⇒ nothing to evaluate against ⇒ available (gating disabled).\n if (!resolve) return { effect: \"visible\" };\n\n let acc: ModuleEffect = { effect: \"visible\" };\n for (const capability of capabilities) {\n const result = resolve(capability);\n if (result.met) continue;\n const kind = result.kind ?? \"error\";\n if (kind === \"error\") {\n warnLog(\n `[capabilities] unmet capability \"${capability}\" resolved to kind \"error\" (fail-closed)`,\n );\n }\n acc = foldUnmet(policy[kind][surface], result.reason, acc);\n }\n return acc;\n}\n","/**\n * SidePane -- persistent resizable inline panel.\n *\n * Sits between SubNavPanel and the main content area in the AppShell flex row.\n * When open it takes a fixed pixel width; the content area (flex-1) shrinks to\n * fill the remainder. The main view remains fully visible and interactive.\n *\n * Opened/closed imperatively via sidePane.open() / sidePane.close() / sidePane.toggle()\n * from api.ts. State is provided by SidePaneContext (owned by AppShell).\n */\nimport { X } from \"lucide-react\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport { useResizablePanel } from \"@petrarca/sonnet-core/hooks\";\nimport { useSidePaneState } from \"./sidePaneState\";\nimport { DragHandle } from \"./DragHandle\";\n\nconst DEFAULT_WIDTH = 320;\nconst DEFAULT_MIN = 240;\nconst DEFAULT_MAX = 800;\n\n/**\n * SidePane renders nothing when no pane is open.\n * When open it renders a bordered panel with a drag handle on its right edge.\n * Double-clicking the handle resets to defaultWidth.\n */\nexport default function SidePane() {\n const { pane, close } = useSidePaneState();\n if (!pane) return null;\n return <SidePaneOpen pane={pane} onClose={close} />;\n}\n\nfunction SidePaneOpen({\n pane,\n onClose,\n}: {\n pane: NonNullable<ReturnType<typeof useSidePaneState>[\"pane\"]>;\n onClose: () => void;\n}) {\n const { panelWidth, handlePointerDown, handleDoubleClick, separatorProps } =\n useResizablePanel({\n defaultWidth: pane.defaultWidth ?? DEFAULT_WIDTH,\n minWidth: pane.minWidth ?? DEFAULT_MIN,\n maxWidth: pane.maxWidth ?? DEFAULT_MAX,\n direction: \"right-edge\",\n });\n\n const isFullWidth = pane.fullWidth === true;\n\n return (\n <div\n className={cn(\n \"relative flex flex-col border-r bg-background\",\n isFullWidth ? \"flex-1\" : \"shrink-0\",\n )}\n style={isFullWidth ? undefined : { width: panelWidth }}\n >\n {/* Header */}\n <div className=\"flex h-10 shrink-0 items-center justify-end border-b px-2\">\n <button\n onClick={onClose}\n className={cn(\n \"flex h-6 w-6 items-center justify-center rounded text-muted-foreground\",\n \"hover:bg-accent hover:text-foreground transition-colors\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n )}\n aria-label=\"Close side pane\"\n >\n <X className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n\n {/* Content */}\n <div className=\"flex-1 overflow-auto\">{pane.content}</div>\n\n {!isFullWidth && (\n <DragHandle\n edge=\"right\"\n separatorProps={separatorProps}\n onPointerDown={handlePointerDown}\n onDoubleClick={handleDoubleClick}\n />\n )}\n </div>\n );\n}\n","/**\n * Side pane state types and context.\n *\n * The side pane is a persistent, resizable inline panel that sits between\n * the SubNavPanel and the main content area. It shrinks the content area\n * rather than overlaying it -- the main view stays visible and interactive.\n *\n * Modules open/close/toggle it via the imperative sidePane API in api.ts.\n * AppShell owns the state and injects it here via SidePaneContext so that\n * SidePane.tsx can read it without coupling to AppShell directly.\n */\nimport { createContext, useContext, type ReactNode } from \"react\";\n\nexport interface SidePaneOptions {\n /** Content to render inside the side pane. */\n content: ReactNode;\n /**\n * Stable key identifying which module/tool owns this pane instance.\n * Used by IconRail to highlight the active pane module and by toggle()\n * to detect whether the same content is already open.\n */\n moduleId: string;\n /** Initial width in pixels. Defaults to 320. */\n defaultWidth?: number;\n /** Minimum draggable width in pixels. Defaults to 240. */\n minWidth?: number;\n /**\n * Maximum draggable width in pixels.\n * Omit or pass Infinity for unlimited (fills remaining space up to viewport).\n */\n maxWidth?: number;\n /**\n * When true, the pane expands to fill the entire content area (flex-1),\n * collapsing the main route content to zero width. Use for full-screen\n * tool views (schema viewer, form editors). The drag handle is hidden.\n * Toggle via sidePane.setFullWidth(boolean) from inside the pane content.\n */\n fullWidth?: boolean;\n}\n\nexport interface SidePaneState {\n /** Currently open pane options, or null when closed. */\n pane: SidePaneOptions | null;\n open: (opts: SidePaneOptions) => void;\n close: () => void;\n toggle: (opts: SidePaneOptions) => void;\n /** Expand or collapse the pane to fill the full content area. */\n setFullWidth: (fullWidth: boolean) => void;\n}\n\nexport const SidePaneContext = createContext<SidePaneState | null>(null);\n\n/**\n * Read the side pane state from context.\n * Must be called within an AppShell (which provides the context).\n */\nexport function useSidePaneState(): SidePaneState {\n const ctx = useContext(SidePaneContext);\n if (!ctx) {\n throw new Error(\"useSidePaneState must be used within an AppShell\");\n }\n return ctx;\n}\n","/**\n * DragHandle — shared resize handle used by SidePane (right-edge) and\n * SlideOverPanel (left-edge).\n *\n * Invisible at rest. On hover shows a 2px primary line; while actively\n * dragging the line thickens to 4px. The hit area is always 8px wide\n * regardless of visual state.\n */\nimport type React from \"react\";\nimport { cn } from \"@petrarca/sonnet-core\";\n\ninterface DragHandleProps {\n /** Which edge of the parent the handle sits on. */\n edge: \"left\" | \"right\";\n separatorProps: React.HTMLAttributes<HTMLDivElement>;\n onPointerDown: React.PointerEventHandler<HTMLDivElement>;\n onDoubleClick: React.MouseEventHandler<HTMLDivElement>;\n}\n\nexport function DragHandle({\n edge,\n separatorProps,\n onPointerDown,\n onDoubleClick,\n}: DragHandleProps) {\n return (\n <div\n {...separatorProps}\n onPointerDown={onPointerDown}\n onDoubleClick={onDoubleClick}\n className={cn(\n // 8px invisible hit area; visual feedback only via the before pseudo-element.\n \"absolute top-0 h-full w-2 cursor-col-resize\",\n edge === \"right\" ? \"right-0\" : \"left-0\",\n // Centered line: invisible at rest, 2px on hover, 4px while dragging.\n \"before:absolute before:inset-y-0 before:left-1/2 before:-translate-x-1/2\",\n \"before:w-0 before:transition-all before:duration-150\",\n \"hover:before:w-0.5 hover:before:bg-primary/60\",\n \"active:before:w-1 active:before:bg-primary/80\",\n )}\n />\n );\n}\n","import { useEffect, useCallback, useMemo } from \"react\";\nimport { useNavigate } from \"react-router-dom\";\nimport {\n CommandDialog,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n CommandSeparator,\n} from \"@petrarca/sonnet-ui\";\nimport { useShellModules } from \"./shellModules\";\nimport { useShellConfig } from \"./shellConfig\";\nimport { evaluateModule, resolveCapabilityPolicy } from \"./capabilities\";\nimport type { ShellModule } from \"./types\";\n\ninterface CommandMenuProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}\n\n/**\n * CommandMenu -- Cmd+K command menu.\n *\n * Indexes all navigation items from the service domains so users can\n * quickly jump to any page by typing.\n */\nexport default function CommandMenu({ open, onOpenChange }: CommandMenuProps) {\n const navigate = useNavigate();\n const { mainModules, bottomModules } = useShellModules();\n const { resolveCapability, capabilityPolicy } = useShellConfig();\n\n // Global Cmd+K / Ctrl+K shortcut\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"k\" && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n onOpenChange(!open);\n }\n };\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [open, onOpenChange]);\n\n const policy = useMemo(\n () => resolveCapabilityPolicy(capabilityPolicy),\n [capabilityPolicy],\n );\n\n // Evaluate a module's requirements for the \"command\" surface.\n const moduleEffect = (service: ShellModule) =>\n evaluateModule(service, \"command\", resolveCapability, policy);\n\n const handleSelect = useCallback(\n (path: string) => {\n navigate(path);\n onOpenChange(false);\n },\n [navigate, onOpenChange],\n );\n\n const renderNavGroup = (service: ShellModule) => {\n if (service.navigation.length === 0) return null;\n const { effect, reason } = moduleEffect(service);\n // hidden / redirect ⇒ omit from the palette; disabled ⇒ show greyed.\n if (effect === \"hidden\" || effect === \"redirect\") return null;\n const disabled = effect === \"disabled\";\n const Icon = service.icon;\n return (\n <CommandGroup key={`nav-${service.id}`} heading={service.label}>\n {service.navigation.flatMap((group) =>\n group.links.map((link) => (\n <CommandItem\n key={link.path}\n value={`${service.label} ${group.heading ?? \"\"} ${link.label}`}\n disabled={disabled}\n onSelect={disabled ? undefined : () => handleSelect(link.path)}\n >\n <Icon className=\"mr-2 h-4 w-4 text-muted-foreground\" />\n <span>{link.label}</span>\n {disabled && reason ? (\n <span className=\"ml-auto text-xs text-muted-foreground\">\n {reason}\n </span>\n ) : (\n group.heading && (\n <span className=\"ml-auto text-xs text-muted-foreground\">\n {group.heading}\n </span>\n )\n )}\n </CommandItem>\n )),\n )}\n </CommandGroup>\n );\n };\n\n const renderCommandGroup = (service: ShellModule) => {\n if (!service.commands?.length) return null;\n const { effect, reason } = moduleEffect(service);\n if (effect === \"hidden\" || effect === \"redirect\") return null;\n const disabled = effect === \"disabled\";\n const Icon = service.icon;\n return (\n <CommandGroup\n key={`cmd-${service.id}`}\n heading={service.commands[0].group ?? service.label}\n >\n {service.commands.map((cmd) => {\n const CmdIcon = cmd.icon ?? Icon;\n return (\n <CommandItem\n key={cmd.id}\n value={`${service.label} ${cmd.label}`}\n disabled={disabled}\n onSelect={\n disabled\n ? undefined\n : () => {\n cmd.action();\n onOpenChange(false);\n }\n }\n >\n <CmdIcon className=\"mr-2 h-4 w-4 text-muted-foreground\" />\n <span>{cmd.label}</span>\n {disabled && reason && (\n <span className=\"ml-auto text-xs text-muted-foreground\">\n {reason}\n </span>\n )}\n </CommandItem>\n );\n })}\n </CommandGroup>\n );\n };\n\n const allModules = [...mainModules, ...bottomModules];\n\n // A module group has visible nav items when: it has navigation links AND its\n // capability effect is not hidden/redirect. Pre-compute to guard separators.\n const hasVisibleNav = (modules: ShellModule[]) =>\n modules.some(\n (m) =>\n m.navigation.length > 0 &&\n ![\"hidden\", \"redirect\"].includes(moduleEffect(m).effect),\n );\n const hasVisibleCmds = allModules.some(\n (m) =>\n (m.commands?.length ?? 0) > 0 &&\n ![\"hidden\", \"redirect\"].includes(moduleEffect(m).effect),\n );\n\n return (\n <CommandDialog open={open} onOpenChange={onOpenChange}>\n <CommandInput placeholder=\"Search pages, services, actions...\" />\n <CommandList>\n <CommandEmpty>No results found.</CommandEmpty>\n\n {mainModules.map(renderNavGroup)}\n\n {/* Only show the separator when both groups contribute visible items,\n to avoid a dangling separator when all modules in one group are\n capability-gated to hidden. */}\n {hasVisibleNav(mainModules) && hasVisibleNav(bottomModules) && (\n <CommandSeparator />\n )}\n\n {bottomModules.map(renderNavGroup)}\n\n {hasVisibleCmds && (\n <>\n <CommandSeparator />\n {allModules.map(renderCommandGroup)}\n </>\n )}\n </CommandList>\n </CommandDialog>\n );\n}\n","/**\n * ModuleEffects -- runs each module's optional `useEffects` hook.\n *\n * Mounted once by AppShell inside the shell tree so module effects have access\n * to Router / QueryClient / provider context. Lets a module own its reactions\n * to app state (e.g. subscribe to a shell event and invalidate its own caches)\n * instead of centralizing that knowledge in app-level code.\n *\n * Each module gets its own host component so its `useEffects` hook is called\n * unconditionally from a stable component (Rules of Hooks). The module set must\n * be stable for the app's lifetime (it is — modules are declared at load time).\n *\n * A per-host `ModuleEffectBoundary` isolates errors: if one module's hook\n * throws, only that module's effects are lost — the rest of the shell is\n * unaffected.\n */\nimport React from \"react\";\nimport { warnLog } from \"@petrarca/sonnet-core\";\nimport type { ShellModule } from \"./types\";\n\ninterface BoundaryState {\n caught: boolean;\n}\n\n/** Minimal error boundary isolating a single module's useEffects hook. */\nclass ModuleEffectBoundary extends React.Component<\n { moduleId: string; children: React.ReactNode },\n BoundaryState\n> {\n state: BoundaryState = { caught: false };\n\n static getDerivedStateFromError(): BoundaryState {\n return { caught: true };\n }\n\n componentDidCatch(error: unknown) {\n warnLog(\n \"[ModuleEffects] module '{}' useEffects threw — effects disabled for this module: {}\",\n this.props.moduleId,\n error,\n );\n }\n\n render() {\n return this.state.caught ? null : this.props.children;\n }\n}\n\nfunction ModuleEffectHost({ module }: { module: ShellModule }) {\n // Safe: render only mounts a host for modules that declare useEffects (see\n // ModuleEffects), and the module identity is stable, so this hook is called\n // unconditionally for the component's lifetime.\n module.useEffects!();\n return null;\n}\n\nexport function ModuleEffects({ modules }: { modules: ShellModule[] }) {\n return (\n <>\n {modules\n .filter((m) => typeof m.useEffects === \"function\")\n .map((m) => (\n <ModuleEffectBoundary key={m.id} moduleId={m.id}>\n <ModuleEffectHost module={m} />\n </ModuleEffectBoundary>\n ))}\n </>\n );\n}\n","import React from \"react\";\nimport { Toaster } from \"sonner\";\nimport AppShell from \"./AppShell\";\nimport { ShellConfigProvider } from \"./ShellConfigProvider\";\nimport type { ShellConfig } from \"./shellConfig\";\nimport type { ModuleRegistry } from \"./createModuleRegistry\";\n\n/**\n * RootLayout -- top-level layout that wraps the entire authenticated app.\n * Renders the Toaster for notifications and the AppShell (icon rail + sub-nav + content).\n */\n\ninterface RootLayoutProps {\n config: ShellConfig;\n registry: ModuleRegistry;\n /** Optional custom sidebar replacing the default IconRail + SubNavPanel. */\n sidebar?: React.ReactNode;\n}\n\nexport default function RootLayout({\n config,\n registry,\n sidebar,\n}: RootLayoutProps) {\n return (\n <ShellConfigProvider config={config}>\n <Toaster position=\"top-right\" richColors closeButton />\n <AppShell registry={registry} sidebar={sidebar} />\n </ShellConfigProvider>\n );\n}\n","/**\n * ShellConfigProvider -- wraps the shell with configuration context.\n */\nimport type { ReactNode } from \"react\";\nimport { ShellConfigContext, type ShellConfig } from \"./shellConfig\";\n\ninterface ShellConfigProviderProps {\n config: ShellConfig;\n children: ReactNode;\n}\n\nexport function ShellConfigProvider({\n config,\n children,\n}: ShellConfigProviderProps) {\n return (\n <ShellConfigContext.Provider value={config}>\n {children}\n </ShellConfigContext.Provider>\n );\n}\n","import { useLocation } from \"react-router-dom\";\n\n/**\n * PlaceholderPage — generic wireframe page for routes not yet implemented.\n * Shows the current path and a placeholder content area.\n */\nexport default function PlaceholderPage() {\n const { pathname } = useLocation();\n\n return (\n <div>\n <h1 className=\"mb-1\">{pathToTitle(pathname)}</h1>\n <p className=\"text-sm text-muted-foreground mb-6\">{pathname}</p>\n\n {/* Wireframe content placeholder */}\n <div className=\"rounded-lg border-2 border-dashed border-border p-12 flex items-center justify-center\">\n <span className=\"text-sm text-muted-foreground\">\n Content area — not yet implemented\n </span>\n </div>\n </div>\n );\n}\n\n/** Convert a path like \"/healthcare/patients\" to \"Patients\" */\nfunction pathToTitle(path: string): string {\n const last = path.split(\"/\").filter(Boolean).pop();\n if (!last) return \"Dashboard\";\n return last\n .split(\"-\")\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(\" \");\n}\n","/**\n * Sidebar — single-column navigation layout.\n *\n * Alternative to the IconRail + SubNavPanel two-column pattern.\n * Renders an optional header, a scrollable body with SidebarGroup /\n * SidebarItem children, and takes its full height from the shell.\n */\nimport React from \"react\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport { ScrollArea } from \"@petrarca/sonnet-ui\";\n\nexport interface SidebarProps {\n children: React.ReactNode;\n /** Optional header rendered above the scrollable nav (e.g. app name, collapse button). */\n header?: React.ReactNode;\n width?: number;\n className?: string;\n}\n\nexport function Sidebar({\n children,\n header,\n width = 260,\n className,\n}: SidebarProps): React.ReactElement {\n return (\n <aside\n style={{ width }}\n className={cn(\n \"shrink-0 border-r bg-muted/30 flex flex-col h-full\",\n className,\n )}\n >\n {header}\n <ScrollArea className=\"flex-1\">\n <nav className=\"px-1.5 py-2 space-y-3\">{children}</nav>\n </ScrollArea>\n </aside>\n );\n}\n","/**\n * ShellSidebar — single-column sidebar layout, auto-wired from the\n * module registry.\n *\n * Reads module list from ShellModulesContext (provided by AppShell).\n * For custom layouts, compose Sidebar / SidebarGroup / SidebarItem directly.\n */\nimport React from \"react\";\nimport { useShellModules } from \"./shellModules\";\nimport { Sidebar } from \"./Sidebar\";\nimport type { SidebarProps } from \"./Sidebar\";\nimport { SidebarGroup } from \"./SidebarGroup\";\nimport { SidebarItem } from \"./SidebarItem\";\n\nexport type ShellSidebarProps = Omit<SidebarProps, \"children\"> & {\n /** Label for the bottom-pinned modules group. Default: \"Tools\". */\n bottomGroupLabel?: string;\n};\n\nexport function ShellSidebar({\n bottomGroupLabel = \"Tools\",\n ...sidebarProps\n}: ShellSidebarProps): React.ReactElement {\n const { mainModules, bottomModules } = useShellModules();\n\n // Collect all topNav links across all main modules (in module order).\n const topNavItems = mainModules.flatMap((mod) =>\n (mod.topNav ?? []).map((link) => ({ link, icon: mod.icon })),\n );\n\n return (\n <Sidebar {...sidebarProps}>\n {/* Top fixed zone — no heading, separator below */}\n {topNavItems.length > 0 && (\n <SidebarGroup separator>\n {topNavItems.map(({ link, icon }) => (\n <SidebarItem\n key={link.path}\n icon={icon}\n label={link.label}\n path={link.path}\n badge={link.badge}\n />\n ))}\n </SidebarGroup>\n )}\n\n {/* Grouped sections */}\n {mainModules.map((mod) => {\n if (mod.navigation.length === 0) {\n return (\n <SidebarItem\n key={mod.id}\n icon={mod.icon}\n label={mod.label}\n path={mod.basePath}\n />\n );\n }\n return (\n <SidebarGroup key={mod.id} heading={mod.label} collapsible>\n {mod.navigation.flatMap((group) => [\n // Render NavGroup heading if it has one\n ...(group.heading\n ? [\n <SidebarGroup\n key={group.id}\n heading={group.heading}\n collapsible={group.collapsible}\n >\n {group.links.map((link) => (\n <SidebarItem\n key={link.path}\n icon={mod.icon}\n label={link.label}\n path={link.path}\n badge={link.badge}\n />\n ))}\n </SidebarGroup>,\n ]\n : group.links.map((link) => (\n <SidebarItem\n key={link.path}\n icon={mod.icon}\n label={link.label}\n path={link.path}\n badge={link.badge}\n />\n ))),\n ])}\n </SidebarGroup>\n );\n })}\n\n {bottomModules.length > 0 && (\n <SidebarGroup heading={bottomGroupLabel} collapsible>\n {bottomModules.map((mod) => (\n <SidebarItem\n key={mod.id}\n icon={mod.icon}\n label={mod.label}\n path={mod.basePath}\n />\n ))}\n </SidebarGroup>\n )}\n </Sidebar>\n );\n}\n","/**\n * ShellVersion — displays the app name and optional version in the footer.\n *\n * Typically used as ShellConfig.footer content alongside ShellFooter.\n * The consumer provides name and version from their own package.json.\n */\nimport React from \"react\";\n\nexport interface ShellVersionProps {\n /** Application name. */\n name: string;\n /** Version string (e.g. from package.json). Omit to show name only. */\n version?: string;\n}\n\nexport function ShellVersion({\n name,\n version,\n}: ShellVersionProps): React.ReactElement {\n return (\n <div className=\"flex items-center gap-2\">\n <span>{name}</span>\n {version && <span className=\"text-muted-foreground/50\">v{version}</span>}\n </div>\n );\n}\n","import { Search } from \"lucide-react\";\nimport { Button } from \"@petrarca/sonnet-ui\";\nimport { navigation } from \"./api\";\n\n/**\n * SearchTrigger -- Cmd+K search button for the TopBar.\n *\n * Opens the shell CommandMenu via the imperative navigation API.\n * Generic building block, no app-specific dependencies.\n */\nexport function SearchTrigger() {\n return (\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"h-8 gap-2 text-sm text-muted-foreground w-56 justify-start\"\n onClick={() => navigation.openCommandMenu()}\n >\n <Search className=\"h-4 w-4\" />\n <span>Search...</span>\n <kbd className=\"ml-auto pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground\">\n <span className=\"text-xs\">&#x2318;</span>K\n </kbd>\n </Button>\n );\n}\n","import { LogOut, User } from \"lucide-react\";\nimport { Button } from \"@petrarca/sonnet-ui\";\nimport { Avatar, AvatarFallback } from \"@petrarca/sonnet-ui\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@petrarca/sonnet-ui\";\n\n/**\n * UserMenu -- avatar dropdown for the TopBar.\n *\n * Shows the user's initials in an avatar. The dropdown displays name,\n * email, a profile link, and a sign-out action. Generic building block,\n * no app-specific dependencies.\n */\n\nexport interface UserMenuUser {\n name: string;\n email: string;\n initials: string;\n}\n\ninterface UserMenuProps {\n user: UserMenuUser;\n onSignOut?: () => void;\n}\n\nexport function UserMenu({ user, onSignOut }: UserMenuProps) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"compact\" className=\"rounded-full\">\n <Avatar className=\"h-7 w-7\">\n <AvatarFallback className=\"text-xs\">{user.initials}</AvatarFallback>\n </Avatar>\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-48\">\n <DropdownMenuLabel className=\"font-normal\">\n <div className=\"flex flex-col gap-1\">\n <p className=\"text-sm font-medium\">{user.name}</p>\n <p className=\"text-xs text-muted-foreground\">{user.email}</p>\n </div>\n </DropdownMenuLabel>\n <DropdownMenuSeparator />\n <DropdownMenuItem>\n <User className=\"mr-2 h-4 w-4\" />\n Profile\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem onSelect={onSignOut}>\n <LogOut className=\"mr-2 h-4 w-4\" />\n Sign out\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n","/**\n * Module registry factory.\n *\n * Accepts a list of ShellModules and returns derived data structures\n * consumed by the shell (icon rail groups, flattened routes, extension\n * point lookup). This is the reusable core; the app-specific module\n * list lives in the consumer (e.g. modules/registry.ts).\n */\nimport type { RouteObject } from \"react-router-dom\";\nimport type { ShellModule, Contribution } from \"./types\";\n\nexport interface ModuleRegistry {\n /** All modules in registration order. */\n modules: ShellModule[];\n\n /** Visible modules shown in the main area of the icon rail. */\n mainModules: ShellModule[];\n\n /** Modules pinned to the bottom of the icon rail. */\n bottomModules: ShellModule[];\n\n /** All routes from all modules, flattened. */\n allRoutes: RouteObject[];\n\n /** Get contributions for a named extension point, sorted by order. */\n getExtensionPoint: (name: string) => Contribution[];\n}\n\nexport function createModuleRegistry(modules: ShellModule[]): ModuleRegistry {\n const visible = modules.filter((m) => !m.hidden);\n const mainModules = visible.filter((m) => !m.pinBottom);\n const bottomModules = visible.filter((m) => m.pinBottom);\n const allRoutes = modules.flatMap((m) => m.routes);\n\n // Pre-collect all contributions for O(n) lookup per call.\n const contributionsByPoint = new Map<string, Contribution[]>();\n for (const m of modules) {\n for (const c of m.contributions ?? []) {\n const list = contributionsByPoint.get(c.extensionPoint) ?? [];\n list.push(c);\n contributionsByPoint.set(c.extensionPoint, list);\n }\n }\n // Sort each group once.\n for (const list of contributionsByPoint.values()) {\n list.sort((a, b) => a.order - b.order);\n }\n\n function getExtensionPoint(name: string): Contribution[] {\n return contributionsByPoint.get(name) ?? [];\n }\n\n return { modules, mainModules, bottomModules, allRoutes, getExtensionPoint };\n}\n","/**\n * OverviewCard and FeatureLink -- building blocks for module overview pages.\n *\n * OverviewCard presents a feature with icon, title, description, and optional\n * navigation via a stable feature id.\n *\n * FeatureLink is an inline text link for use in descriptions or prose,\n * also navigating via stable feature id.\n *\n * Part of the shell -- extracts to @petrarca/sonnet-shell.\n */\n\nimport React from \"react\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport { navigation } from \"./api\";\n\ninterface OverviewCardProps {\n /** Lucide icon component. */\n icon: React.ComponentType<{ className?: string }>;\n /** Card title. */\n title: string;\n /** Description -- plain string or React nodes (e.g. with FeatureLink). */\n description: React.ReactNode;\n /**\n * Stable feature identifier (e.g. \"auditing.audit-events\").\n * Resolved to a path via the shell registry at click time.\n * Omit for non-navigable cards.\n */\n feature?: string;\n /** Additional CSS class names. */\n className?: string;\n}\n\n/**\n * FeatureLink -- inline text link navigating to a feature by stable id.\n *\n * Use inside OverviewCard descriptions or overview page prose to link\n * to a feature without hardcoding paths.\n *\n * @example\n * <FeatureLink feature=\"auditing.audit-log\">Audit Log</FeatureLink>\n */\nexport function FeatureLink({\n feature,\n children,\n}: {\n feature: string;\n children: React.ReactNode;\n}): React.ReactElement {\n return (\n <span\n role=\"link\"\n tabIndex={0}\n onClick={(e) => {\n e.stopPropagation();\n navigation.goToFeature(feature);\n }}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n e.stopPropagation();\n navigation.goToFeature(feature);\n }\n }}\n className=\"underline underline-offset-2 hover:text-foreground transition-colors cursor-pointer\"\n >\n {children}\n </span>\n );\n}\n\n/** Feature card for module overview pages. Navigates via the shell API. */\nexport function OverviewCard({\n icon: Icon,\n title,\n description,\n feature,\n className,\n}: OverviewCardProps): React.ReactElement {\n return (\n <button\n onClick={feature ? () => navigation.goToFeature(feature) : undefined}\n disabled={!feature}\n className={cn(\n \"rounded-lg border bg-card p-5 text-left flex flex-col gap-3\",\n \"disabled:cursor-default\",\n feature && \"hover:bg-accent/50 transition-colors\",\n className,\n )}\n >\n <div className=\"h-9 w-9 rounded-md bg-blue-50 flex items-center justify-center shrink-0\">\n <Icon className=\"h-5 w-5 text-blue-600\" />\n </div>\n <div>\n <p className=\"text-sm font-medium mb-1\">{title}</p>\n <p className=\"text-xs text-muted-foreground leading-relaxed\">\n {description}\n </p>\n </div>\n </button>\n );\n}\n"],"mappings":"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","names":["useState","useEffect","useCallback","useRef","useMemo","useResizablePanel","useLocation","useNavigate","ScrollArea","jsx","jsx","useMemo","Button","jsx","jsxs","useMemo","Tooltip","TooltipContent","TooltipTrigger","warnLog","warnLog","cn","jsx","jsxs","cn","jsx","jsxs","jsx","jsxs","useMemo","Tooltip","TooltipTrigger","TooltipContent","createContext","useContext","createContext","useContext","warnLog","jsx","jsxs","useMemo","cn","createContext","useContext","cn","jsx","jsx","jsxs","cn","useEffect","useMemo","Fragment","jsx","jsxs","useEffect","useMemo","React","warnLog","Fragment","jsx","Fragment","jsx","jsxs","useRef","useEffect","useLocation","useMemo","useCallback","useState","useSidePaneState","useNavigate","sidePane","panel","dialog","useResizablePanel","ScrollArea","jsx","jsx","jsxs","useLocation","jsx","jsxs","cn","ScrollArea","jsx","jsxs","jsx","jsxs","jsx","jsxs","Button","jsx","jsxs","Button","Button","jsx","jsxs","cn","jsx","jsxs","cn"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@petrarca/sonnet-shell",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Application shell, layout, navigation, auth flow, and imperative API for the Petrarca Sonnet component library",
5
5
  "license": "Apache-2.0",
6
6
  "publishConfig": {
@@ -25,8 +25,8 @@
25
25
  "dependencies": {
26
26
  "lucide-react": "^0.553.0",
27
27
  "sonner": "^2.0.7",
28
- "@petrarca/sonnet-core": "0.2.0",
29
- "@petrarca/sonnet-ui": "0.2.0"
28
+ "@petrarca/sonnet-ui": "0.4.0",
29
+ "@petrarca/sonnet-core": "0.4.0"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "react": ">=19",