@principal-ade/panel-layouts 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../src/hooks/usePanelPersistence.ts","../src/services/LocalStorageWorkspaceAdapter.ts","../src/services/WorkspaceLayoutService.ts","../src/hooks/useWorkspace.ts","../src/keyboard/hooks/usePanelFocus.ts","../src/keyboard/hooks/usePanelKeyboardShortcuts.ts","../src/keyboard/hooks/usePanelFocusListener.ts","../src/keyboard/components/FocusIndicator.tsx","../src/command-palette/components/CommandInput.tsx","../src/command-palette/components/CommandItem.tsx","../src/command-palette/components/CommandList.tsx","../src/command-palette/components/CommandPalette.tsx","../src/command-palette/services/CommandRegistryService.ts","../src/command-palette/hooks/useCommandPalette.ts","../src/command-palette/commands/panelCommands.ts"],"sourcesContent":["/**\n * usePanelPersistence Hook\n *\n * Extracted and adapted from electron-app/src/renderer/hooks/usePanelPersistence.ts\n * Manages saving and loading panel sizes and collapsed states with debounced persistence.\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react';\nimport type {\n UsePanelPersistenceOptions,\n PanelSizes,\n TwoPanelSizes,\n PanelCollapsed,\n PanelPersistence,\n PersistenceAdapter,\n} from '../types/persistence.types';\n\n/**\n * Default localStorage-based persistence adapter for web applications\n */\nexport class LocalStoragePersistenceAdapter implements PersistenceAdapter {\n private storageKey = 'panel-layouts';\n\n async load(viewKey: string) {\n try {\n const stored = localStorage.getItem(`${this.storageKey}:${viewKey}`);\n return stored ? JSON.parse(stored) : null;\n } catch (error) {\n console.error(`Failed to load panel layout for ${viewKey}:`, error);\n return null;\n }\n }\n\n async save(viewKey: string, state: { sizes: PanelSizes | TwoPanelSizes }) {\n try {\n localStorage.setItem(\n `${this.storageKey}:${viewKey}`,\n JSON.stringify(state),\n );\n } catch (error) {\n console.error(`Failed to save panel layout for ${viewKey}:`, error);\n }\n }\n}\n\n/**\n * Hook for persisting panel layouts across sessions\n *\n * Manages panel sizes and collapsed states with automatic debounced saving.\n * Supports both 2-panel and 3-panel layouts.\n *\n * @param options - Configuration options for persistence\n * @returns Panel state and handlers for resizing and collapsing\n *\n * @example\n * ```tsx\n * const persistence = usePanelPersistence({\n * viewKey: 'my-app',\n * defaultSizes: { left: 30, middle: 70, right: 0 },\n * collapsed: { left: false, right: true },\n * panelType: 'three-panel',\n * });\n *\n * <ConfigurablePanelLayout\n * {...otherProps}\n * defaultSizes={persistence.sizes}\n * collapsed={persistence.collapsed}\n * onPanelResize={persistence.handlePanelResize}\n * />\n * ```\n */\nexport function usePanelPersistence(\n options: UsePanelPersistenceOptions,\n): PanelPersistence {\n const {\n viewKey,\n defaultSizes,\n panelType,\n adapter = new LocalStoragePersistenceAdapter(),\n } = options;\n\n const [sizes, setSizes] = useState(defaultSizes);\n const [collapsed, setCollapsed] = useState(options.collapsed);\n const prevCollapsedRef = useRef(options.collapsed);\n const lastNonZeroSizesRef = useRef<Partial<PanelSizes & TwoPanelSizes>>({});\n const saveTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pendingPersistSizesRef = useRef<typeof sizes | null>(null);\n\n // Load saved state on mount\n useEffect(() => {\n const loadSavedState = async () => {\n const saved = await adapter.load(viewKey);\n if (saved?.sizes) {\n setSizes(saved.sizes as typeof sizes);\n updateLastNonZeroSizes(saved.sizes);\n }\n };\n loadSavedState();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [viewKey]);\n\n const updateLastNonZeroSizes = useCallback(\n (incomingSizes: PanelSizes | TwoPanelSizes) => {\n if ('left' in incomingSizes && incomingSizes.left > 0) {\n lastNonZeroSizesRef.current.left = incomingSizes.left;\n }\n\n if ('middle' in incomingSizes && incomingSizes.middle > 0) {\n lastNonZeroSizesRef.current.middle = incomingSizes.middle;\n }\n\n if ('right' in incomingSizes && incomingSizes.right > 0) {\n lastNonZeroSizesRef.current.right = incomingSizes.right;\n }\n },\n [],\n );\n\n const getFallbackSize = useCallback(\n (panel: 'left' | 'right') => {\n const storedSize = lastNonZeroSizesRef.current[panel];\n if (storedSize && storedSize > 0) {\n return storedSize;\n }\n\n if (panel === 'left' && 'left' in defaultSizes && defaultSizes.left > 0) {\n return defaultSizes.left;\n }\n\n if (\n panel === 'right' &&\n 'right' in defaultSizes &&\n defaultSizes.right > 0\n ) {\n return defaultSizes.right;\n }\n\n return undefined;\n },\n [defaultSizes],\n );\n\n // Update sizes when defaultSizes changes (parent has loaded preferences)\n const prevDefaultSizesRef = useRef(defaultSizes);\n useEffect(() => {\n // Only update if the actual values changed, not just the reference\n const hasChanged =\n ('left' in defaultSizes &&\n defaultSizes.left !== prevDefaultSizesRef.current.left) ||\n ('middle' in defaultSizes &&\n 'middle' in prevDefaultSizesRef.current &&\n defaultSizes.middle !==\n (prevDefaultSizesRef.current as PanelSizes).middle) ||\n ('right' in defaultSizes &&\n defaultSizes.right !== prevDefaultSizesRef.current.right);\n\n if (hasChanged) {\n setSizes(defaultSizes);\n updateLastNonZeroSizes(defaultSizes);\n prevDefaultSizesRef.current = defaultSizes;\n }\n }, [defaultSizes, updateLastNonZeroSizes]);\n\n // Sync with parent's collapsed state (e.g., from titlebar buttons)\n useEffect(() => {\n const leftChanged =\n options.collapsed.left !== prevCollapsedRef.current.left;\n const rightChanged =\n 'right' in options.collapsed &&\n 'right' in prevCollapsedRef.current &&\n (options.collapsed as PanelCollapsed).right !==\n (prevCollapsedRef.current as PanelCollapsed).right;\n\n if (leftChanged || rightChanged) {\n setCollapsed(options.collapsed);\n prevCollapsedRef.current = { ...options.collapsed };\n }\n }, [options.collapsed.left, (options.collapsed as PanelCollapsed).right]);\n\n // Save preferences helper (only saves sizes, not collapsed state)\n const savePreferences = useCallback(\n async (newSizes: typeof sizes) => {\n try {\n await adapter.save(viewKey, { sizes: newSizes });\n } catch (error) {\n console.error(\n `Failed to save panel preferences for ${viewKey}:`,\n error,\n );\n }\n },\n [viewKey, adapter],\n );\n\n // Handle panel resize (debounced)\n const handlePanelResize = useCallback(\n (newSizes: typeof sizes) => {\n const sanitizedSizes = { ...newSizes } as typeof newSizes;\n let shouldPersist = true;\n\n if ('left' in newSizes) {\n const leftCollapsed = Boolean((collapsed as PanelCollapsed)?.left);\n const leftSize = newSizes.left;\n\n if (leftCollapsed) {\n const fallback = getFallbackSize('left');\n if (fallback !== undefined && fallback > 0) {\n sanitizedSizes.left = fallback;\n } else {\n shouldPersist = false;\n }\n } else if (leftSize === 0) {\n shouldPersist = false;\n }\n }\n\n if (panelType === 'three-panel' && 'right' in newSizes) {\n const rightCollapsed = Boolean((collapsed as PanelCollapsed)?.right);\n const rightSize = newSizes.right;\n\n if (rightCollapsed) {\n const fallback = getFallbackSize('right');\n if (fallback !== undefined && fallback > 0) {\n sanitizedSizes.right = fallback;\n } else {\n shouldPersist = false;\n }\n } else if (rightSize === 0) {\n shouldPersist = false;\n }\n }\n\n setSizes(sanitizedSizes);\n updateLastNonZeroSizes(sanitizedSizes);\n\n if (saveTimeoutRef.current) {\n clearTimeout(saveTimeoutRef.current);\n saveTimeoutRef.current = null;\n }\n\n if (!shouldPersist) {\n pendingPersistSizesRef.current = null;\n return;\n }\n\n pendingPersistSizesRef.current = sanitizedSizes;\n saveTimeoutRef.current = setTimeout(() => {\n const pendingSizes = pendingPersistSizesRef.current;\n if (pendingSizes) {\n savePreferences(pendingSizes);\n pendingPersistSizesRef.current = null;\n }\n saveTimeoutRef.current = null;\n }, 500);\n },\n [\n collapsed,\n getFallbackSize,\n panelType,\n savePreferences,\n updateLastNonZeroSizes,\n ],\n );\n\n // Cleanup: save any pending changes on unmount\n useEffect(() => {\n return () => {\n if (saveTimeoutRef.current) {\n const pendingSizes = pendingPersistSizesRef.current;\n if (pendingSizes) {\n savePreferences(pendingSizes);\n pendingPersistSizesRef.current = null;\n }\n clearTimeout(saveTimeoutRef.current);\n saveTimeoutRef.current = null;\n }\n };\n }, [savePreferences]);\n\n // Collapse/expand handlers - no-ops because state is controlled by parent\n // The parent manages collapsed state via titlebar buttons and passes it down as props\n const handleLeftCollapseComplete = useCallback(async () => {\n // No-op: parent controls state\n }, []);\n\n const handleLeftExpandComplete = useCallback(async () => {\n // No-op: parent controls state\n }, []);\n\n const handleRightCollapseComplete = useCallback(async () => {\n // No-op: parent controls state\n }, []);\n\n const handleRightExpandComplete = useCallback(async () => {\n // No-op: parent controls state\n }, []);\n\n if (panelType === 'three-panel') {\n return {\n type: 'three-panel',\n sizes: sizes as PanelSizes,\n collapsed: collapsed as PanelCollapsed,\n handlePanelResize: handlePanelResize as (sizes: PanelSizes) => void,\n handleLeftCollapseComplete,\n handleLeftExpandComplete,\n handleRightCollapseComplete,\n handleRightExpandComplete,\n };\n } else {\n return {\n type: 'two-panel',\n sizes: sizes as TwoPanelSizes,\n collapsed: collapsed as { left?: boolean },\n handlePanelResize: handlePanelResize as (sizes: TwoPanelSizes) => void,\n handleLeftCollapseComplete,\n handleLeftExpandComplete,\n };\n }\n}\n","/**\n * LocalStorageWorkspaceAdapter - Browser localStorage implementation\n * Stores workspace presets and repository states in browser localStorage\n */\n\nimport type {\n WorkspaceLayout,\n WorkspaceStorageAdapter,\n RepositoryWorkspaceState,\n} from '../types/workspace.types';\n\nexport class LocalStorageWorkspaceAdapter implements WorkspaceStorageAdapter {\n private readonly PRESETS_KEY = 'panel-layouts:workspace-presets';\n private readonly REPO_STATE_PREFIX = 'panel-layouts:repo-state:';\n\n /**\n * Load all user-created workspace presets\n */\n async loadWorkspacePresets(): Promise<Record<string, WorkspaceLayout>> {\n try {\n const stored = localStorage.getItem(this.PRESETS_KEY);\n if (!stored) {\n return {};\n }\n return JSON.parse(stored);\n } catch (error) {\n console.error('Failed to load workspace presets:', error);\n return {};\n }\n }\n\n /**\n * Save workspace presets\n */\n async saveWorkspacePresets(\n presets: Record<string, WorkspaceLayout>,\n ): Promise<void> {\n try {\n localStorage.setItem(this.PRESETS_KEY, JSON.stringify(presets));\n } catch (error) {\n console.error('Failed to save workspace presets:', error);\n throw error;\n }\n }\n\n /**\n * Load repository-specific workspace state\n */\n async loadRepositoryState(\n repositoryKey: string,\n ): Promise<RepositoryWorkspaceState | null> {\n try {\n const key = `${this.REPO_STATE_PREFIX}${repositoryKey}`;\n const stored = localStorage.getItem(key);\n if (!stored) {\n return null;\n }\n return JSON.parse(stored);\n } catch (error) {\n console.error(\n `Failed to load repository state for ${repositoryKey}:`,\n error,\n );\n return null;\n }\n }\n\n /**\n * Save repository-specific workspace state\n */\n async saveRepositoryState(\n repositoryKey: string,\n state: RepositoryWorkspaceState,\n ): Promise<void> {\n try {\n const key = `${this.REPO_STATE_PREFIX}${repositoryKey}`;\n localStorage.setItem(key, JSON.stringify(state));\n } catch (error) {\n console.error(\n `Failed to save repository state for ${repositoryKey}:`,\n error,\n );\n throw error;\n }\n }\n\n /**\n * Load all repository states\n */\n async loadAllRepositoryStates(): Promise<\n Record<string, RepositoryWorkspaceState>\n > {\n try {\n const allStates: Record<string, RepositoryWorkspaceState> = {};\n\n // Iterate through all localStorage keys\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key && key.startsWith(this.REPO_STATE_PREFIX)) {\n const repositoryKey = key.substring(this.REPO_STATE_PREFIX.length);\n const stored = localStorage.getItem(key);\n if (stored) {\n try {\n allStates[repositoryKey] = JSON.parse(stored);\n } catch (parseError) {\n console.error(\n `Failed to parse repository state for ${repositoryKey}:`,\n parseError,\n );\n }\n }\n }\n }\n\n return allStates;\n } catch (error) {\n console.error('Failed to load all repository states:', error);\n return {};\n }\n }\n}\n","/**\n * WorkspaceLayoutService - Manages workspace layout presets\n * Extracted from electron-app/src/renderer/services/WorkspaceLayoutService.ts\n *\n * This service handles CRUD operations for workspace layouts (panel configuration presets)\n * and provides utilities for comparing layouts and managing built-in workspaces.\n */\n\nimport type { PanelLayout } from '@principal-ade/panels';\nimport type {\n WorkspaceLayout,\n WorkspaceStorageAdapter,\n RepositoryWorkspaceState,\n CreateWorkspaceOptions,\n UpdateWorkspaceOptions,\n} from '../types/workspace.types';\nimport { LocalStorageWorkspaceAdapter } from './LocalStorageWorkspaceAdapter';\n\nexport class WorkspaceLayoutService {\n private static adapter: WorkspaceStorageAdapter =\n new LocalStorageWorkspaceAdapter();\n\n /**\n * Configure a custom storage adapter (for Electron IPC or remote storage)\n */\n static setAdapter(adapter: WorkspaceStorageAdapter): void {\n this.adapter = adapter;\n }\n\n /**\n * Get all workspace layouts (including built-in)\n */\n static async getWorkspaceLayouts(): Promise<Record<string, WorkspaceLayout>> {\n const builtInWorkspaces = this.getBuiltInWorkspaceLayouts();\n const userWorkspaces = await this.adapter.loadWorkspacePresets();\n\n // Merge built-in and user workspaces, built-in takes precedence\n return {\n ...userWorkspaces,\n ...builtInWorkspaces,\n };\n }\n\n /**\n * Get a specific workspace layout by ID\n */\n static async getWorkspaceLayout(id: string): Promise<WorkspaceLayout | null> {\n const workspaces = await this.getWorkspaceLayouts();\n return workspaces[id] || null;\n }\n\n /**\n * Create a new workspace layout\n */\n static async createWorkspaceLayout(\n options: CreateWorkspaceOptions,\n ): Promise<WorkspaceLayout> {\n const userWorkspaces = await this.adapter.loadWorkspacePresets();\n const id = this.generateWorkspaceId(options.name);\n\n const workspace: WorkspaceLayout = {\n id,\n name: options.name,\n description: options.description,\n layout: options.layout,\n defaultSizes: options.defaultSizes,\n defaultCollapsed: options.defaultCollapsed,\n createdAt: Date.now(),\n updatedAt: Date.now(),\n isBuiltIn: false,\n };\n\n const updatedPresets = {\n ...userWorkspaces,\n [id]: workspace,\n };\n\n await this.adapter.saveWorkspacePresets(updatedPresets);\n\n return workspace;\n }\n\n /**\n * Update an existing workspace layout\n */\n static async updateWorkspaceLayout(\n id: string,\n updates: UpdateWorkspaceOptions,\n ): Promise<WorkspaceLayout | null> {\n const userWorkspaces = await this.adapter.loadWorkspacePresets();\n const existingWorkspace = userWorkspaces[id];\n\n if (!existingWorkspace) {\n console.error(`Workspace layout ${id} not found`);\n return null;\n }\n\n // Don't allow updating built-in workspaces\n if (existingWorkspace.isBuiltIn) {\n console.error(`Cannot update built-in workspace layout ${id}`);\n return null;\n }\n\n const updatedWorkspace: WorkspaceLayout = {\n ...existingWorkspace,\n ...updates,\n id, // Preserve ID\n createdAt: existingWorkspace.createdAt, // Preserve creation time\n updatedAt: Date.now(),\n };\n\n const updatedPresets = {\n ...userWorkspaces,\n [id]: updatedWorkspace,\n };\n\n await this.adapter.saveWorkspacePresets(updatedPresets);\n\n return updatedWorkspace;\n }\n\n /**\n * Delete a workspace layout\n */\n static async deleteWorkspaceLayout(id: string): Promise<boolean> {\n const userWorkspaces = await this.adapter.loadWorkspacePresets();\n const workspace = userWorkspaces[id];\n\n if (!workspace) {\n console.error(`Workspace layout ${id} not found`);\n return false;\n }\n\n // Don't allow deleting built-in workspaces\n if (workspace.isBuiltIn) {\n console.error(`Cannot delete built-in workspace layout ${id}`);\n return false;\n }\n\n const updatedPresets = { ...userWorkspaces };\n delete updatedPresets[id];\n\n await this.adapter.saveWorkspacePresets(updatedPresets);\n\n return true;\n }\n\n /**\n * Get repository state (which workspace + current sizes/collapsed)\n */\n static async getRepositoryState(\n repositoryKey: string,\n ): Promise<RepositoryWorkspaceState | null> {\n return await this.adapter.loadRepositoryState(repositoryKey);\n }\n\n /**\n * Set repository state (which workspace + current sizes/collapsed/layout)\n */\n static async setRepositoryState(\n repositoryKey: string,\n state: RepositoryWorkspaceState,\n ): Promise<void> {\n await this.adapter.saveRepositoryState(repositoryKey, state);\n }\n\n /**\n * Update only sizes in repository state\n */\n static async updateRepositorySizes(\n repositoryKey: string,\n sizes: { left: number; middle: number; right: number },\n ): Promise<void> {\n const currentState = await this.getRepositoryState(repositoryKey);\n if (!currentState) return;\n\n await this.setRepositoryState(repositoryKey, {\n ...currentState,\n sizes,\n });\n }\n\n /**\n * Update only collapsed state in repository state\n */\n static async updateRepositoryCollapsed(\n repositoryKey: string,\n collapsed: { left?: boolean; right?: boolean },\n ): Promise<void> {\n const currentState = await this.getRepositoryState(repositoryKey);\n if (!currentState) return;\n\n await this.setRepositoryState(repositoryKey, {\n ...currentState,\n collapsed,\n });\n }\n\n /**\n * Check if repository state differs from workspace defaults\n */\n static hasStateDeviation(\n repoState: {\n workspaceId: string | null;\n sizes: { left: number; middle: number; right: number };\n collapsed: { left?: boolean; right?: boolean };\n },\n workspace: WorkspaceLayout,\n ): {\n hasSizeDeviation: boolean;\n hasCollapsedDeviation: boolean;\n } {\n const hasSizeDeviation = workspace.defaultSizes\n ? JSON.stringify(repoState.sizes) !==\n JSON.stringify(workspace.defaultSizes)\n : false;\n\n const hasCollapsedDeviation = workspace.defaultCollapsed\n ? JSON.stringify(repoState.collapsed) !==\n JSON.stringify(workspace.defaultCollapsed)\n : false;\n\n return { hasSizeDeviation, hasCollapsedDeviation };\n }\n\n /**\n * Update workspace defaults from repository state\n */\n static async updateWorkspaceFromRepositoryState(\n workspaceId: string,\n repositoryKey: string,\n ): Promise<void> {\n const workspace = await this.getWorkspaceLayout(workspaceId);\n const repoState = await this.getRepositoryState(repositoryKey);\n\n if (!workspace || !repoState || workspace.isBuiltIn) {\n console.error(\n 'Cannot update built-in workspace or workspace/state not found',\n );\n return;\n }\n\n await this.updateWorkspaceLayout(workspaceId, {\n defaultSizes: repoState.sizes,\n defaultCollapsed: repoState.collapsed,\n });\n }\n\n /**\n * Reset repository state to workspace defaults\n */\n static async resetRepositoryToWorkspaceDefaults(\n repositoryKey: string,\n workspaceId: string,\n ): Promise<void> {\n const workspace = await this.getWorkspaceLayout(workspaceId);\n if (!workspace) {\n console.error(`Workspace ${workspaceId} not found`);\n return;\n }\n\n const currentState = await this.getRepositoryState(repositoryKey);\n if (!currentState) return;\n\n await this.setRepositoryState(repositoryKey, {\n ...currentState,\n sizes: workspace.defaultSizes || { left: 20, middle: 45, right: 35 },\n collapsed: workspace.defaultCollapsed || { left: false, right: false },\n });\n }\n\n /**\n * Check if a layout matches a workspace layout\n */\n static isLayoutMatchingWorkspace(\n layout: PanelLayout,\n workspace: WorkspaceLayout,\n ): boolean {\n return this.areLayoutsEqual(layout, workspace.layout);\n }\n\n /**\n * Find workspace ID that matches the given layout\n */\n static async findMatchingWorkspace(\n layout: PanelLayout,\n ): Promise<string | null> {\n const workspaces = await this.getWorkspaceLayouts();\n\n for (const [id, workspace] of Object.entries(workspaces)) {\n if (this.isLayoutMatchingWorkspace(layout, workspace)) {\n return id;\n }\n }\n\n return null;\n }\n\n /**\n * Deep comparison of two panel layouts\n */\n private static areLayoutsEqual(\n layout1: PanelLayout,\n layout2: PanelLayout,\n ): boolean {\n return JSON.stringify(layout1) === JSON.stringify(layout2);\n }\n\n /**\n * Generate a unique ID from a workspace name\n */\n private static generateWorkspaceId(name: string): string {\n const base = name.toLowerCase().replace(/[^a-z0-9]+/g, '-');\n return `${base}-${Date.now()}`;\n }\n\n /**\n * Get built-in workspace layouts\n */\n static getBuiltInWorkspaceLayouts(): Record<string, WorkspaceLayout> {\n const now = Date.now();\n\n return {\n 'project-management': {\n id: 'project-management',\n name: 'Project Management',\n description:\n 'Tasks, dependencies, issues, file tree, docs, drawings, multi terminal, city visualization, code viewer, markdown slides, and excalidraw',\n layout: {\n left: {\n type: 'tabs',\n panels: [\n 'tasks',\n 'dependencies',\n 'gitIssues',\n 'fileTree',\n 'docs',\n 'drawings',\n ],\n config: { defaultActiveTab: 0, tabPosition: 'top' },\n },\n middle: 'multiTerminal',\n right: {\n type: 'tabs',\n panels: [\n 'cityVisualization',\n 'codeViewer',\n 'markdownViewer',\n 'excalidrawDiagram',\n ],\n config: { defaultActiveTab: 0, tabPosition: 'top' },\n },\n },\n defaultSizes: { left: 20, middle: 45, right: 35 },\n defaultCollapsed: { left: false, right: false },\n createdAt: now,\n updatedAt: now,\n isBuiltIn: true,\n },\n 'code-review': {\n id: 'code-review',\n name: 'Code Review',\n description:\n 'Git changes, pull requests, and file tree on left, git diff and code viewer in middle, city map on right',\n layout: {\n left: {\n type: 'tabs',\n panels: ['gitChanges', 'gitPullRequests', 'fileTree'],\n config: { defaultActiveTab: 0, tabPosition: 'top' },\n },\n middle: {\n type: 'tabs',\n panels: ['gitDiff', 'codeViewer'],\n config: { defaultActiveTab: 0, tabPosition: 'top' },\n },\n right: 'cityVisualization',\n },\n defaultSizes: { left: 20, middle: 50, right: 30 },\n defaultCollapsed: { left: false, right: false },\n createdAt: now,\n updatedAt: now,\n isBuiltIn: true,\n },\n documentation: {\n id: 'documentation',\n name: 'Documentation',\n description: 'Docs, markdown viewer, and code viewer',\n layout: {\n left: 'docs',\n middle: 'markdownViewer',\n right: 'codeViewer',\n },\n defaultSizes: { left: 20, middle: 50, right: 30 },\n defaultCollapsed: { left: false, right: true },\n createdAt: now,\n updatedAt: now,\n isBuiltIn: true,\n },\n 'agent-work': {\n id: 'agent-work',\n name: 'Agent Work',\n description:\n 'Tasks, agent sessions, file tree, agent context, git changes, docs, multi terminal, city map, agent events, code viewer, and markdown slides',\n layout: {\n left: {\n type: 'tabs',\n panels: [\n 'tasks',\n 'agentSessions',\n 'fileTree',\n 'agentContext',\n 'gitChanges',\n 'docs',\n ],\n config: { defaultActiveTab: 0, tabPosition: 'top' },\n },\n middle: 'multiTerminal',\n right: {\n type: 'tabs',\n panels: [\n 'cityVisualization',\n 'agentEvents',\n 'codeViewer',\n 'markdownViewer',\n ],\n config: { defaultActiveTab: 0, tabPosition: 'top' },\n },\n },\n defaultSizes: { left: 20, middle: 45, right: 35 },\n defaultCollapsed: { left: false, right: false },\n createdAt: now,\n updatedAt: now,\n isBuiltIn: true,\n },\n 'quality-check': {\n id: 'quality-check',\n name: 'Quality Check',\n description:\n 'Package information, tools, and dependencies on left; city visualization map in middle; multi terminal and code viewer on right (collapsed)',\n layout: {\n left: {\n type: 'tabs',\n panels: ['packageInfo', 'tools', 'dependencies'],\n config: { defaultActiveTab: 0, tabPosition: 'top' },\n },\n middle: 'cityVisualization',\n right: {\n type: 'tabs',\n panels: ['multiTerminal', 'codeViewer'],\n config: { defaultActiveTab: 0, tabPosition: 'top' },\n },\n },\n defaultSizes: { left: 20, middle: 45, right: 35 },\n defaultCollapsed: { left: false, right: true },\n createdAt: now,\n updatedAt: now,\n isBuiltIn: true,\n },\n drawing: {\n id: 'drawing',\n name: 'Drawing',\n description:\n 'Drawings and docs, excalidraw diagram, multi terminal and markdown viewer',\n layout: {\n left: {\n type: 'tabs',\n panels: ['drawings', 'docs'],\n config: { defaultActiveTab: 0, tabPosition: 'top' },\n },\n middle: 'excalidrawDiagram',\n right: {\n type: 'tabs',\n panels: ['multiTerminal', 'markdownViewer'],\n config: { defaultActiveTab: 0, tabPosition: 'top' },\n },\n },\n defaultSizes: { left: 20, middle: 50, right: 30 },\n defaultCollapsed: { left: false, right: true },\n createdAt: now,\n updatedAt: now,\n isBuiltIn: true,\n },\n 'old-school': {\n id: 'old-school',\n name: 'Old School',\n description:\n 'File tree, search, git changes, and docs on left; code viewer and markdown viewer in middle; multi terminal and city map on right (collapsed)',\n layout: {\n left: {\n type: 'tabs',\n panels: ['fileTree', 'search', 'gitChanges', 'docs'],\n config: { defaultActiveTab: 0, tabPosition: 'top' },\n },\n middle: {\n type: 'tabs',\n panels: ['codeViewer', 'markdownViewer'],\n config: { defaultActiveTab: 0, tabPosition: 'top' },\n },\n right: {\n type: 'tabs',\n panels: ['multiTerminal', 'cityVisualization'],\n config: { defaultActiveTab: 0, tabPosition: 'top' },\n },\n },\n defaultSizes: { left: 20, middle: 50, right: 30 },\n defaultCollapsed: { left: false, right: true },\n createdAt: now,\n updatedAt: now,\n isBuiltIn: true,\n },\n 'principal-office': {\n id: 'principal-office',\n name: 'Principal Office',\n description:\n 'Alexandria docs on left, MDX editor in middle, multi terminal on right',\n layout: {\n left: 'docs',\n middle: 'mdxEditor',\n right: 'multiTerminal',\n },\n defaultSizes: { left: 20, middle: 50, right: 30 },\n defaultCollapsed: { left: false, right: false },\n createdAt: now,\n updatedAt: now,\n isBuiltIn: true,\n },\n };\n }\n\n /**\n * Initialize workspace layouts with built-in defaults if none exist\n */\n static async initializeWorkspaceLayouts(): Promise<void> {\n const userWorkspaces = await this.adapter.loadWorkspacePresets();\n\n // Only initialize if there are no user workspaces yet\n // Built-in workspaces are always available via getBuiltInWorkspaceLayouts()\n if (Object.keys(userWorkspaces).length === 0) {\n // Nothing to do - built-in workspaces are always available\n // This method exists for compatibility with electron-app\n }\n }\n}\n","/**\n * useWorkspace - React hook for workspace management\n * Provides easy access to workspace operations and state\n */\n\nimport { useState, useEffect, useCallback } from 'react';\nimport { WorkspaceLayoutService } from '../services/WorkspaceLayoutService';\nimport type {\n WorkspaceLayout,\n RepositoryWorkspaceState,\n CreateWorkspaceOptions,\n UpdateWorkspaceOptions,\n} from '../types/workspace.types';\n\nexport interface UseWorkspaceOptions {\n /**\n * Optional repository key for repository-specific state\n * If provided, the hook will manage repository state\n */\n repositoryKey?: string;\n\n /**\n * Auto-initialize repository state if it doesn't exist\n */\n autoInitialize?: boolean;\n\n /**\n * Default workspace to use for auto-initialization\n */\n defaultWorkspaceId?: string;\n}\n\nexport interface UseWorkspaceReturn {\n /**\n * All available workspaces (built-in + user-created)\n */\n workspaces: Record<string, WorkspaceLayout>;\n\n /**\n * Current repository state (if repositoryKey provided)\n */\n repositoryState: RepositoryWorkspaceState | null;\n\n /**\n * Current active workspace (if repositoryKey provided)\n */\n activeWorkspace: WorkspaceLayout | null;\n\n /**\n * Loading state\n */\n loading: boolean;\n\n /**\n * Error state\n */\n error: Error | null;\n\n /**\n * Get a specific workspace by ID\n */\n getWorkspace: (id: string) => Promise<WorkspaceLayout | null>;\n\n /**\n * Create a new workspace\n */\n createWorkspace: (options: CreateWorkspaceOptions) => Promise<WorkspaceLayout>;\n\n /**\n * Update an existing workspace\n */\n updateWorkspace: (\n id: string,\n updates: UpdateWorkspaceOptions,\n ) => Promise<WorkspaceLayout | null>;\n\n /**\n * Delete a workspace\n */\n deleteWorkspace: (id: string) => Promise<boolean>;\n\n /**\n * Apply a workspace to the current repository\n */\n applyWorkspace: (workspaceId: string) => Promise<void>;\n\n /**\n * Update repository sizes\n */\n updateSizes: (sizes: {\n left: number;\n middle: number;\n right: number;\n }) => Promise<void>;\n\n /**\n * Update repository collapsed state\n */\n updateCollapsed: (collapsed: {\n left?: boolean;\n right?: boolean;\n }) => Promise<void>;\n\n /**\n * Reset repository to workspace defaults\n */\n resetToDefaults: () => Promise<void>;\n\n /**\n * Refresh workspace data\n */\n refresh: () => Promise<void>;\n}\n\nexport function useWorkspace(\n options: UseWorkspaceOptions = {},\n): UseWorkspaceReturn {\n const { repositoryKey, autoInitialize = false, defaultWorkspaceId } = options;\n\n const [workspaces, setWorkspaces] = useState<Record<string, WorkspaceLayout>>(\n {},\n );\n const [repositoryState, setRepositoryState] =\n useState<RepositoryWorkspaceState | null>(null);\n const [activeWorkspace, setActiveWorkspace] =\n useState<WorkspaceLayout | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n /**\n * Load all workspaces and repository state\n */\n const loadData = useCallback(async () => {\n try {\n setLoading(true);\n setError(null);\n\n // Load all workspaces\n const allWorkspaces =\n await WorkspaceLayoutService.getWorkspaceLayouts();\n setWorkspaces(allWorkspaces);\n\n // Load repository state if repositoryKey provided\n if (repositoryKey) {\n let repoState =\n await WorkspaceLayoutService.getRepositoryState(repositoryKey);\n\n // Auto-initialize if requested and state doesn't exist\n if (!repoState && autoInitialize) {\n const workspaceId =\n defaultWorkspaceId || 'project-management'; // Default to project-management\n const workspace =\n await WorkspaceLayoutService.getWorkspaceLayout(workspaceId);\n\n if (workspace) {\n repoState = {\n workspaceId,\n sizes: workspace.defaultSizes || {\n left: 20,\n middle: 45,\n right: 35,\n },\n collapsed: workspace.defaultCollapsed || {\n left: false,\n right: false,\n },\n };\n\n await WorkspaceLayoutService.setRepositoryState(\n repositoryKey,\n repoState,\n );\n }\n }\n\n setRepositoryState(repoState);\n\n // Load active workspace if repository has one\n if (repoState?.workspaceId) {\n const workspace = await WorkspaceLayoutService.getWorkspaceLayout(\n repoState.workspaceId,\n );\n setActiveWorkspace(workspace);\n } else {\n setActiveWorkspace(null);\n }\n }\n } catch (err) {\n setError(err as Error);\n console.error('Failed to load workspace data:', err);\n } finally {\n setLoading(false);\n }\n }, [repositoryKey, autoInitialize, defaultWorkspaceId]);\n\n /**\n * Initial load\n */\n useEffect(() => {\n loadData();\n }, [loadData]);\n\n /**\n * Get a specific workspace\n */\n const getWorkspace = useCallback(\n async (id: string) => {\n return await WorkspaceLayoutService.getWorkspaceLayout(id);\n },\n [],\n );\n\n /**\n * Create a new workspace\n */\n const createWorkspace = useCallback(\n async (createOptions: CreateWorkspaceOptions) => {\n const workspace =\n await WorkspaceLayoutService.createWorkspaceLayout(createOptions);\n await loadData(); // Refresh\n return workspace;\n },\n [loadData],\n );\n\n /**\n * Update an existing workspace\n */\n const updateWorkspace = useCallback(\n async (id: string, updates: UpdateWorkspaceOptions) => {\n const workspace =\n await WorkspaceLayoutService.updateWorkspaceLayout(id, updates);\n await loadData(); // Refresh\n return workspace;\n },\n [loadData],\n );\n\n /**\n * Delete a workspace\n */\n const deleteWorkspace = useCallback(\n async (id: string) => {\n const success = await WorkspaceLayoutService.deleteWorkspaceLayout(id);\n if (success) {\n await loadData(); // Refresh\n }\n return success;\n },\n [loadData],\n );\n\n /**\n * Apply a workspace to the current repository\n */\n const applyWorkspace = useCallback(\n async (workspaceId: string) => {\n if (!repositoryKey) {\n console.error('Cannot apply workspace without repositoryKey');\n return;\n }\n\n const workspace =\n await WorkspaceLayoutService.getWorkspaceLayout(workspaceId);\n if (!workspace) {\n console.error(`Workspace ${workspaceId} not found`);\n return;\n }\n\n const newState: RepositoryWorkspaceState = {\n workspaceId,\n sizes: workspace.defaultSizes || { left: 20, middle: 45, right: 35 },\n collapsed: workspace.defaultCollapsed || {\n left: false,\n right: false,\n },\n };\n\n await WorkspaceLayoutService.setRepositoryState(repositoryKey, newState);\n await loadData(); // Refresh\n },\n [repositoryKey, loadData],\n );\n\n /**\n * Update repository sizes\n */\n const updateSizes = useCallback(\n async (sizes: { left: number; middle: number; right: number }) => {\n if (!repositoryKey) {\n console.error('Cannot update sizes without repositoryKey');\n return;\n }\n\n await WorkspaceLayoutService.updateRepositorySizes(repositoryKey, sizes);\n await loadData(); // Refresh\n },\n [repositoryKey, loadData],\n );\n\n /**\n * Update repository collapsed state\n */\n const updateCollapsed = useCallback(\n async (collapsed: { left?: boolean; right?: boolean }) => {\n if (!repositoryKey) {\n console.error('Cannot update collapsed without repositoryKey');\n return;\n }\n\n await WorkspaceLayoutService.updateRepositoryCollapsed(\n repositoryKey,\n collapsed,\n );\n await loadData(); // Refresh\n },\n [repositoryKey, loadData],\n );\n\n /**\n * Reset repository to workspace defaults\n */\n const resetToDefaults = useCallback(async () => {\n if (!repositoryKey || !repositoryState?.workspaceId) {\n console.error('Cannot reset without repositoryKey and active workspace');\n return;\n }\n\n await WorkspaceLayoutService.resetRepositoryToWorkspaceDefaults(\n repositoryKey,\n repositoryState.workspaceId,\n );\n await loadData(); // Refresh\n }, [repositoryKey, repositoryState?.workspaceId, loadData]);\n\n /**\n * Refresh workspace data\n */\n const refresh = useCallback(async () => {\n await loadData();\n }, [loadData]);\n\n return {\n workspaces,\n repositoryState,\n activeWorkspace,\n loading,\n error,\n getWorkspace,\n createWorkspace,\n updateWorkspace,\n deleteWorkspace,\n applyWorkspace,\n updateSizes,\n updateCollapsed,\n resetToDefaults,\n refresh,\n };\n}\n","/**\n * usePanelFocus - Hook for managing panel focus state\n */\n\nimport { useState, useCallback } from 'react';\nimport type {\n PanelEventEmitter,\n PanelFocusEventPayload,\n PanelBlurEventPayload,\n} from '@principal-ade/panel-framework-core';\nimport type { PanelSlotId, PanelFocusState, PanelFocusActions } from '../types';\nimport type { PanelCollapsed } from '../../types/persistence.types';\n\nexport interface UsePanelFocusOptions {\n /** Initial focused panel (optional) */\n initialFocus?: PanelSlotId | null;\n\n /** Collapsed state to determine which panels are visible */\n collapsed?: PanelCollapsed;\n\n /** Whether this is a two-panel or three-panel layout */\n panelType?: 'two-panel' | 'three-panel';\n\n /** Callback when focus changes */\n onFocusChange?: (panel: PanelSlotId | null) => void;\n\n /** Event emitter from panel framework (optional, for focus events) */\n events?: PanelEventEmitter;\n\n /** Function to map panel slot to panel ID (optional, required for event emission) */\n getPanelId?: (slot: PanelSlotId) => string | undefined;\n}\n\nexport interface UsePanelFocusReturn extends PanelFocusState, PanelFocusActions {\n /** Check if a specific panel is focused */\n isFocused: (panel: PanelSlotId) => boolean;\n}\n\n/**\n * Hook for managing panel focus state with keyboard shortcuts\n */\nexport function usePanelFocus(\n options: UsePanelFocusOptions = {}\n): UsePanelFocusReturn {\n const {\n initialFocus = null,\n collapsed = {},\n panelType = 'three-panel',\n onFocusChange,\n events,\n getPanelId,\n } = options;\n\n const [focusedPanel, setFocusedPanelState] = useState<PanelSlotId | null>(\n initialFocus\n );\n\n const setFocus = useCallback(\n (panel: PanelSlotId) => {\n const previousPanel = focusedPanel;\n setFocusedPanelState(panel);\n onFocusChange?.(panel);\n\n // Emit framework events if event emitter is provided\n if (events && getPanelId) {\n // Emit blur event for previous panel\n if (previousPanel) {\n const prevPanelId = getPanelId(previousPanel);\n if (prevPanelId) {\n events.emit<PanelBlurEventPayload>({\n type: 'panel:blur',\n source: 'panel-layouts',\n timestamp: Date.now(),\n payload: {\n panelId: prevPanelId,\n panelSlot: previousPanel,\n nextPanelId: getPanelId(panel),\n },\n });\n }\n }\n\n // Emit focus event for new panel\n const panelId = getPanelId(panel);\n if (panelId) {\n events.emit<PanelFocusEventPayload>({\n type: 'panel:focus',\n source: 'panel-layouts',\n timestamp: Date.now(),\n payload: {\n panelId,\n panelSlot: panel,\n source: 'keyboard-shortcut',\n },\n });\n }\n }\n },\n [focusedPanel, onFocusChange, events, getPanelId]\n );\n\n const clearFocus = useCallback(() => {\n const previousPanel = focusedPanel;\n setFocusedPanelState(null);\n onFocusChange?.(null);\n\n // Emit blur event when clearing focus\n if (events && getPanelId && previousPanel) {\n const prevPanelId = getPanelId(previousPanel);\n if (prevPanelId) {\n events.emit<PanelBlurEventPayload>({\n type: 'panel:blur',\n source: 'panel-layouts',\n timestamp: Date.now(),\n payload: {\n panelId: prevPanelId,\n panelSlot: previousPanel,\n },\n });\n }\n }\n }, [focusedPanel, onFocusChange, events, getPanelId]);\n\n const getVisiblePanels = useCallback((): PanelSlotId[] => {\n const panels: PanelSlotId[] = [];\n\n if (!collapsed.left) {\n panels.push('left');\n }\n panels.push('middle'); // Middle is always visible\n if (panelType === 'three-panel' && !collapsed.right) {\n panels.push('right');\n }\n\n return panels;\n }, [collapsed, panelType]);\n\n const focusNext = useCallback(() => {\n const visiblePanels = getVisiblePanels();\n if (visiblePanels.length === 0) return;\n\n if (focusedPanel === null) {\n // No panel focused, focus first visible panel\n setFocus(visiblePanels[0]);\n return;\n }\n\n const currentIndex = visiblePanels.indexOf(focusedPanel);\n if (currentIndex === -1) {\n // Current panel is not visible, focus first visible panel\n setFocus(visiblePanels[0]);\n return;\n }\n\n // Move to next panel (wrap around)\n const nextIndex = (currentIndex + 1) % visiblePanels.length;\n setFocus(visiblePanels[nextIndex]);\n }, [focusedPanel, getVisiblePanels, setFocus]);\n\n const focusPrevious = useCallback(() => {\n const visiblePanels = getVisiblePanels();\n if (visiblePanels.length === 0) return;\n\n if (focusedPanel === null) {\n // No panel focused, focus last visible panel\n setFocus(visiblePanels[visiblePanels.length - 1]);\n return;\n }\n\n const currentIndex = visiblePanels.indexOf(focusedPanel);\n if (currentIndex === -1) {\n // Current panel is not visible, focus last visible panel\n setFocus(visiblePanels[visiblePanels.length - 1]);\n return;\n }\n\n // Move to previous panel (wrap around)\n const prevIndex =\n currentIndex === 0 ? visiblePanels.length - 1 : currentIndex - 1;\n setFocus(visiblePanels[prevIndex]);\n }, [focusedPanel, getVisiblePanels, setFocus]);\n\n const isFocused = useCallback(\n (panel: PanelSlotId) => focusedPanel === panel,\n [focusedPanel]\n );\n\n return {\n focusedPanel,\n setFocus,\n clearFocus,\n focusNext,\n focusPrevious,\n isFocused,\n };\n}\n","/**\n * usePanelKeyboardShortcuts - Hook for keyboard shortcuts to control panel focus and collapse\n */\n\nimport { useEffect, useCallback, useRef } from 'react';\nimport type { PanelSlotId } from '../types';\nimport type { PanelCollapsed } from '../../types/persistence.types';\n\nexport interface UsePanelKeyboardShortcutsOptions {\n /** Whether keyboard shortcuts are enabled */\n enabled?: boolean;\n\n /** Current focused panel */\n focusedPanel: PanelSlotId | null;\n\n /** Current collapsed state */\n collapsed: PanelCollapsed;\n\n /** Panel type (two-panel or three-panel) */\n panelType: 'two-panel' | 'three-panel';\n\n /** Set focus to a specific panel */\n setFocus: (panel: PanelSlotId) => void;\n\n /** Callback to expand a panel */\n onExpand: (panel: 'left' | 'right') => void | Promise<void>;\n\n /** Callback to collapse a panel */\n onCollapse: (panel: 'left' | 'right') => void | Promise<void>;\n}\n\n/**\n * Hook for handling Alt+1/2/3 keyboard shortcuts for panel toggle and focus\n *\n * Behavior:\n * - Alt+1 (Left Panel):\n * 1. If collapsed: expand (no focus change)\n * 2. If expanded but not focused: focus it\n * 3. If focused: collapse and focus middle\n *\n * - Alt+2 (Middle Panel):\n * - Always focus middle (never collapses)\n *\n * - Alt+3 (Right Panel):\n * 1. If collapsed: expand (no focus change)\n * 2. If expanded but not focused: focus it\n * 3. If focused: collapse and focus middle\n */\nexport function usePanelKeyboardShortcuts(\n options: UsePanelKeyboardShortcutsOptions\n): void {\n const {\n enabled = true,\n focusedPanel,\n collapsed,\n panelType,\n setFocus,\n onExpand,\n onCollapse,\n } = options;\n\n // Use refs to avoid recreating event listener on every render\n const focusedPanelRef = useRef(focusedPanel);\n const collapsedRef = useRef(collapsed);\n const panelTypeRef = useRef(panelType);\n\n useEffect(() => {\n focusedPanelRef.current = focusedPanel;\n }, [focusedPanel]);\n\n useEffect(() => {\n collapsedRef.current = collapsed;\n }, [collapsed]);\n\n useEffect(() => {\n panelTypeRef.current = panelType;\n }, [panelType]);\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent) => {\n // Only handle Alt+Number shortcuts\n if (!event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {\n return;\n }\n\n // Use event.code instead of event.key to handle international keyboards\n // event.code gives us 'Digit1', 'Digit2', etc. regardless of keyboard layout\n const code = event.code;\n const currentFocused = focusedPanelRef.current;\n const currentCollapsed = collapsedRef.current;\n const currentPanelType = panelTypeRef.current;\n\n // Alt+1: Toggle left panel\n if (code === 'Digit1' || code === 'Numpad1') {\n event.preventDefault();\n\n if (currentCollapsed.left) {\n // State 1: Collapsed -> Expand (no focus change)\n onExpand('left');\n } else if (currentFocused !== 'left') {\n // State 2: Expanded but not focused -> Focus\n setFocus('left');\n } else {\n // State 3: Focused -> Collapse and focus middle\n onCollapse('left');\n setFocus('middle');\n }\n }\n // Alt+2: Focus middle panel\n else if (code === 'Digit2' || code === 'Numpad2') {\n event.preventDefault();\n setFocus('middle');\n }\n // Alt+3: Toggle right panel (only for three-panel layouts)\n else if ((code === 'Digit3' || code === 'Numpad3') && currentPanelType === 'three-panel') {\n event.preventDefault();\n\n if (currentCollapsed.right) {\n // State 1: Collapsed -> Expand (no focus change)\n onExpand('right');\n } else if (currentFocused !== 'right') {\n // State 2: Expanded but not focused -> Focus\n setFocus('right');\n } else {\n // State 3: Focused -> Collapse and focus middle\n onCollapse('right');\n setFocus('middle');\n }\n }\n },\n [setFocus, onExpand, onCollapse]\n );\n\n useEffect(() => {\n if (!enabled) {\n return;\n }\n\n window.addEventListener('keydown', handleKeyDown);\n\n return () => {\n window.removeEventListener('keydown', handleKeyDown);\n };\n }, [enabled, handleKeyDown]);\n}\n","/**\n * usePanelFocusListener - Helper hook for panels to listen to focus events\n */\n\nimport { useEffect } from 'react';\nimport type {\n PanelEventEmitter,\n PanelFocusEventPayload,\n PanelBlurEventPayload,\n} from '@principal-ade/panel-framework-core';\n\n/**\n * Hook for panels to listen to focus events from the framework\n *\n * This is a convenience hook that panels can use to respond to focus changes\n * from keyboard shortcuts, mouse clicks, or programmatic navigation.\n *\n * @param panelId - The ID of this panel (from panel metadata)\n * @param events - Event emitter from PanelComponentProps\n * @param onFocus - Callback when this panel receives focus\n * @param onBlur - Optional callback when this panel loses focus\n *\n * @example\n * ```typescript\n * function TerminalPanel({ context, actions, events }: PanelComponentProps) {\n * const xtermRef = useRef<Terminal>();\n *\n * usePanelFocusListener(\n * 'terminal',\n * events,\n * () => xtermRef.current?.focus(),\n * () => xtermRef.current?.blur()\n * );\n *\n * return <div id=\"xterm-container\" />;\n * }\n * ```\n */\nexport function usePanelFocusListener(\n panelId: string,\n events: PanelEventEmitter,\n onFocus: () => void,\n onBlur?: () => void\n): void {\n useEffect(() => {\n // Listen for focus events\n const unsubscribeFocus = events.on<PanelFocusEventPayload>(\n 'panel:focus',\n (event) => {\n if (event.payload.panelId === panelId) {\n onFocus();\n }\n }\n );\n\n // Listen for blur events (optional)\n let unsubscribeBlur: (() => void) | undefined;\n if (onBlur) {\n unsubscribeBlur = events.on<PanelBlurEventPayload>(\n 'panel:blur',\n (event) => {\n if (event.payload.panelId === panelId) {\n onBlur();\n }\n }\n );\n }\n\n return () => {\n unsubscribeFocus();\n unsubscribeBlur?.();\n };\n }, [panelId, events, onFocus, onBlur]);\n}\n","/**\n * FocusIndicator - Visual indicator for focused panel\n */\n\nimport React from 'react';\n\nexport interface FocusIndicatorProps {\n /** Whether this panel is currently focused */\n isFocused: boolean;\n\n /** Custom class name */\n className?: string;\n\n /** Custom styles */\n style?: React.CSSProperties;\n}\n\n/**\n * Visual indicator that highlights the focused panel\n *\n * Renders a subtle border/glow around the focused panel for keyboard navigation feedback\n */\nexport const FocusIndicator: React.FC<FocusIndicatorProps> = ({\n isFocused,\n className = '',\n style = {},\n}) => {\n if (!isFocused) {\n return null;\n }\n\n const defaultStyles: React.CSSProperties = {\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n pointerEvents: 'none',\n border: '2px solid var(--panel-focus-border-color, #0066cc)',\n borderRadius: '4px',\n boxShadow: '0 0 0 1px var(--panel-focus-shadow-color, rgba(0, 102, 204, 0.2))',\n zIndex: 1000,\n transition: 'opacity 0.15s ease-in-out',\n ...style,\n };\n\n return (\n <div\n className={`panel-focus-indicator ${className}`}\n style={defaultStyles}\n role=\"presentation\"\n aria-hidden=\"true\"\n />\n );\n};\n","import React, { useEffect, useRef } from 'react';\nimport { useTheme } from '@principal-ade/industry-theme';\n\ninterface CommandInputProps {\n value: string;\n onChange: (value: string) => void;\n placeholder?: string;\n onClose: () => void;\n onEnter?: () => void;\n}\n\n/**\n * CommandInput - Input field for the command palette\n * Auto-focuses on mount and handles input changes\n */\nexport const CommandInput: React.FC<CommandInputProps> = ({\n value,\n onChange,\n placeholder = '> Type a command...',\n onClose,\n onEnter,\n}) => {\n const { theme } = useTheme();\n const inputRef = useRef<HTMLInputElement>(null);\n\n // Auto-focus on mount\n useEffect(() => {\n if (inputRef.current) {\n inputRef.current.focus();\n }\n }, []);\n\n // Handle keyboard events\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n switch (e.key) {\n case 'Enter':\n e.preventDefault();\n onEnter?.();\n break;\n case 'Escape':\n e.preventDefault();\n onClose();\n break;\n }\n };\n\n return (\n <div\n style={{\n padding: '0',\n borderBottom: `1px solid ${theme.colors.border}`,\n backgroundColor: theme.colors.background,\n }}\n >\n <input\n ref={inputRef}\n type=\"text\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n style={{\n width: '100%',\n padding: '16px 20px',\n fontSize: '16px',\n fontFamily: theme.fonts.monospace,\n backgroundColor: 'transparent',\n border: 'none',\n outline: 'none',\n color: theme.colors.text,\n caretColor: theme.colors.primary,\n }}\n autoComplete=\"off\"\n autoCorrect=\"off\"\n autoCapitalize=\"off\"\n spellCheck={false}\n />\n </div>\n );\n};\n","import React, { forwardRef } from 'react';\nimport { useTheme } from '@principal-ade/industry-theme';\nimport type { Command } from '../types/command.types';\n\ninterface CommandItemProps {\n command: Command;\n isSelected: boolean;\n onClick: () => void;\n onMouseEnter: () => void;\n}\n\n/**\n * CommandItem - Individual command item in the list\n * Displays command label, description, icon, and keyboard shortcut\n */\nexport const CommandItem = forwardRef<HTMLDivElement, CommandItemProps>(\n ({ command, isSelected, onClick, onMouseEnter }, ref) => {\n const { theme } = useTheme();\n const { label, description, icon, shortcut } = command;\n const [isHovered, setIsHovered] = React.useState(false);\n\n return (\n <div\n ref={ref}\n onClick={onClick}\n onMouseEnter={() => {\n setIsHovered(true);\n onMouseEnter();\n }}\n onMouseLeave={() => setIsHovered(false)}\n style={{\n padding: '10px 16px',\n cursor: 'pointer',\n backgroundColor: isSelected || isHovered\n ? theme.colors.backgroundSecondary\n : 'transparent',\n borderLeft: isSelected || isHovered\n ? `3px solid ${theme.colors.primary}`\n : '3px solid transparent',\n transition: 'all 0.1s ease',\n display: 'flex',\n alignItems: 'center',\n gap: '12px',\n }}\n onMouseDown={(e) => {\n // Prevent input blur\n e.preventDefault();\n }}\n >\n {/* Icon */}\n {icon && (\n <div\n style={{\n flexShrink: 0,\n width: '20px',\n height: '20px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '16px',\n color: isSelected || isHovered ? theme.colors.primary : theme.colors.textSecondary,\n }}\n >\n {typeof icon === 'string' ? icon : icon}\n </div>\n )}\n\n {/* Label and Description */}\n <div style={{ flex: 1, minWidth: 0 }}>\n <div\n style={{\n fontSize: '14px',\n fontWeight: 500,\n color: isSelected || isHovered ? theme.colors.text : theme.colors.textSecondary,\n marginBottom: description ? '2px' : 0,\n }}\n >\n {label}\n </div>\n {description && (\n <div\n style={{\n fontSize: '12px',\n color: theme.colors.textMuted,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {description}\n </div>\n )}\n </div>\n\n {/* Keyboard Shortcut */}\n {shortcut && (\n <div\n style={{\n flexShrink: 0,\n fontSize: '11px',\n color: theme.colors.textMuted,\n padding: '2px 8px',\n backgroundColor: theme.colors.background,\n border: `1px solid ${theme.colors.border}`,\n borderRadius: '4px',\n fontFamily: theme.fonts.monospace,\n }}\n >\n {shortcut}\n </div>\n )}\n </div>\n );\n }\n);\n\nCommandItem.displayName = 'CommandItem';\n","import React, { useEffect, useRef } from 'react';\nimport { useTheme } from '@principal-ade/industry-theme';\nimport type { Command } from '../types/command.types';\nimport { CommandItem } from './CommandItem';\n\ninterface CommandListProps {\n commands: Command[];\n selectedIndex: number;\n onSelect: (command: Command) => void;\n onHover: (index: number) => void;\n maxResults?: number;\n}\n\n/**\n * CommandList - List of filtered commands\n * Displays commands grouped by category with keyboard navigation support\n */\nexport const CommandList: React.FC<CommandListProps> = ({\n commands,\n selectedIndex,\n onSelect,\n onHover,\n maxResults = 10,\n}) => {\n const { theme } = useTheme();\n const listRef = useRef<HTMLDivElement>(null);\n const selectedItemRef = useRef<HTMLDivElement>(null);\n\n // Limit results\n const displayedCommands = commands.slice(0, maxResults);\n\n // Scroll selected item into view (only within the list container)\n useEffect(() => {\n if (selectedItemRef.current && listRef.current) {\n const item = selectedItemRef.current;\n const container = listRef.current;\n\n const itemTop = item.offsetTop;\n const itemBottom = itemTop + item.offsetHeight;\n const containerScrollTop = container.scrollTop;\n const containerHeight = container.clientHeight;\n\n // Scroll only if item is out of view\n if (itemTop < containerScrollTop) {\n // Item is above visible area\n container.scrollTop = itemTop - 8; // 8px padding\n } else if (itemBottom > containerScrollTop + containerHeight) {\n // Item is below visible area\n container.scrollTop = itemBottom - containerHeight + 8;\n }\n }\n }, [selectedIndex]);\n\n // Group commands by category\n const groupedCommands = displayedCommands.reduce((acc, command, index) => {\n const category = command.category || 'Other';\n if (!acc[category]) {\n acc[category] = [];\n }\n acc[category].push({ command, index });\n return acc;\n }, {} as Record<string, Array<{ command: Command; index: number }>>);\n\n // Sort categories\n const categories = Object.keys(groupedCommands).sort((a, b) => {\n // \"Other\" always last\n if (a === 'Other') return 1;\n if (b === 'Other') return -1;\n return a.localeCompare(b);\n });\n\n return (\n <div\n ref={listRef}\n style={{\n overflowY: 'auto',\n maxHeight: '400px',\n padding: '8px 0',\n }}\n >\n {categories.map((category) => (\n <div key={category}>\n {/* Category Header */}\n {categories.length > 1 && (\n <div\n style={{\n padding: '8px 16px 4px',\n fontSize: '11px',\n fontWeight: 600,\n textTransform: 'uppercase',\n color: theme.colors.textMuted,\n letterSpacing: '0.5px',\n }}\n >\n {category}\n </div>\n )}\n\n {/* Category Commands */}\n {groupedCommands[category].map(({ command, index }) => (\n <CommandItem\n key={command.id}\n command={command}\n isSelected={index === selectedIndex}\n onClick={() => onSelect(command)}\n onMouseEnter={() => onHover(index)}\n ref={index === selectedIndex ? selectedItemRef : undefined}\n />\n ))}\n </div>\n ))}\n\n {/* Show count if more results available */}\n {commands.length > maxResults && (\n <div\n style={{\n padding: '8px 16px',\n fontSize: '12px',\n color: theme.colors.textMuted,\n textAlign: 'center',\n borderTop: `1px solid ${theme.colors.border}`,\n }}\n >\n Showing {maxResults} of {commands.length} results\n </div>\n )}\n </div>\n );\n};\n","import React, { useEffect, useRef } from 'react';\nimport { useTheme } from '@principal-ade/industry-theme';\nimport type { CommandPaletteProps } from '../types/command.types';\nimport { CommandInput } from './CommandInput';\nimport { CommandList } from './CommandList';\n\n/**\n * CommandPalette - Vim-style command palette component\n * Displays at the bottom of the screen with an input field and command list\n */\nexport const CommandPalette: React.FC<CommandPaletteProps> = ({\n commandPalette,\n config,\n}) => {\n const { theme } = useTheme();\n const containerRef = useRef<HTMLDivElement>(null);\n const {\n isOpen,\n close,\n query,\n setQuery,\n filteredCommands,\n selectedIndex,\n setSelectedIndex,\n executeSelected,\n } = commandPalette;\n\n // Handle click outside to close\n useEffect(() => {\n if (!isOpen) return;\n\n const handleClickOutside = (e: MouseEvent) => {\n if (containerRef.current && !containerRef.current.contains(e.target as Node)) {\n close();\n }\n };\n\n // Add a small delay to prevent immediate close on open\n const timeoutId = setTimeout(() => {\n document.addEventListener('mousedown', handleClickOutside);\n }, 100);\n\n return () => {\n clearTimeout(timeoutId);\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, [isOpen, close]);\n\n\n if (!isOpen) {\n return null;\n }\n\n const maxHeight = config?.maxHeight || '50vh';\n const placeholder = config?.placeholder || '> Type a command...';\n\n return (\n <>\n {/* Backdrop */}\n <div\n style={{\n position: 'fixed',\n inset: 0,\n backgroundColor: 'rgba(0, 0, 0, 0.4)',\n backdropFilter: 'blur(2px)',\n zIndex: 999,\n }}\n onClick={close}\n />\n\n {/* Command Palette Container */}\n <div\n ref={containerRef}\n className={config?.className}\n style={{\n position: 'fixed',\n bottom: 0,\n left: 0,\n right: 0,\n maxHeight,\n backgroundColor: theme.colors.surface,\n borderTop: `1px solid ${theme.colors.border}`,\n boxShadow: theme.shadows[2],\n zIndex: 1000,\n display: 'flex',\n flexDirection: 'column-reverse',\n ...config?.style,\n }}\n >\n {/* Input Field (at bottom due to column-reverse) */}\n <div>\n <CommandInput\n value={query}\n onChange={setQuery}\n placeholder={placeholder}\n onClose={close}\n onEnter={executeSelected}\n />\n\n {/* Footer with keyboard hints */}\n <div\n style={{\n padding: '8px 16px',\n borderTop: `1px solid ${theme.colors.border}`,\n display: 'flex',\n gap: '16px',\n fontSize: '12px',\n color: theme.colors.textMuted,\n backgroundColor: theme.colors.background,\n }}\n >\n <span>\n <kbd style={{ padding: '2px 6px', backgroundColor: theme.colors.backgroundSecondary, borderRadius: '3px', border: `1px solid ${theme.colors.border}` }}>Enter</kbd> Execute\n </span>\n <span>\n <kbd style={{ padding: '2px 6px', backgroundColor: theme.colors.backgroundSecondary, borderRadius: '3px', border: `1px solid ${theme.colors.border}` }}>Esc</kbd> Close\n </span>\n </div>\n </div>\n\n {/* Results List (appears above due to column-reverse) */}\n {filteredCommands.length > 0 && (\n <CommandList\n commands={filteredCommands}\n selectedIndex={selectedIndex}\n onSelect={(command) => {\n commandPalette.executeCommand(command.id);\n }}\n onHover={setSelectedIndex}\n maxResults={config?.maxResults}\n />\n )}\n\n {/* No Results Message (appears above due to column-reverse) */}\n {query && filteredCommands.length === 0 && (\n <div\n style={{\n padding: '24px 16px',\n color: theme.colors.textMuted,\n textAlign: 'center',\n fontSize: '14px',\n }}\n >\n No commands found for \"{query}\"\n </div>\n )}\n </div>\n </>\n );\n};\n","import type { Command, CommandContext } from '../types/command.types';\n\n/**\n * Service for managing command registration and execution\n * Provides a centralized registry for commands that can be accessed via the command palette\n */\nexport class CommandRegistryService {\n private commands: Map<string, Command> = new Map();\n private listeners: Set<() => void> = new Set();\n\n /**\n * Register one or more commands\n * @param commands - Array of commands to register\n */\n registerCommands(commands: Command[]): void {\n commands.forEach((command) => {\n this.commands.set(command.id, command);\n });\n this.notifyListeners();\n }\n\n /**\n * Register a single command\n * @param command - Command to register\n */\n registerCommand(command: Command): void {\n this.commands.set(command.id, command);\n this.notifyListeners();\n }\n\n /**\n * Unregister commands by ID\n * @param commandIds - Array of command IDs to unregister\n */\n unregisterCommands(commandIds: string[]): void {\n commandIds.forEach((id) => {\n this.commands.delete(id);\n });\n this.notifyListeners();\n }\n\n /**\n * Unregister a single command\n * @param commandId - Command ID to unregister\n */\n unregisterCommand(commandId: string): void {\n this.commands.delete(commandId);\n this.notifyListeners();\n }\n\n /**\n * Get all registered commands\n * @param context - Command context for availability checks\n * @returns Array of available commands\n */\n getCommands(context?: CommandContext): Command[] {\n const allCommands = Array.from(this.commands.values());\n\n if (!context) {\n return allCommands;\n }\n\n // Filter by availability\n return allCommands.filter((command) => {\n if (!command.isAvailable) {\n return true; // No availability check means always available\n }\n return command.isAvailable(context);\n });\n }\n\n /**\n * Get a command by ID\n * @param commandId - Command ID\n * @returns Command if found, undefined otherwise\n */\n getCommand(commandId: string): Command | undefined {\n return this.commands.get(commandId);\n }\n\n /**\n * Execute a command by ID\n * @param commandId - Command ID to execute\n * @param context - Command context\n */\n async executeCommand(commandId: string, context: CommandContext): Promise<void> {\n const command = this.commands.get(commandId);\n if (!command) {\n console.warn(`Command not found: ${commandId}`);\n return;\n }\n\n // Check availability\n if (command.isAvailable && !command.isAvailable(context)) {\n console.warn(`Command not available: ${commandId}`);\n return;\n }\n\n try {\n await command.execute(context);\n\n // Emit event for analytics/logging\n context.events?.emit({\n type: 'command:executed',\n source: 'command-palette',\n timestamp: Date.now(),\n payload: {\n commandId: command.id,\n commandLabel: command.label,\n },\n });\n } catch (error) {\n console.error(`Error executing command ${commandId}:`, error);\n\n // Emit error event\n context.events?.emit({\n type: 'command:error',\n source: 'command-palette',\n timestamp: Date.now(),\n payload: {\n commandId: command.id,\n error: error instanceof Error ? error.message : String(error),\n },\n });\n }\n }\n\n /**\n * Search commands by query\n * @param query - Search query\n * @param context - Command context for availability checks\n * @returns Filtered and sorted commands\n */\n searchCommands(query: string, context?: CommandContext): Command[] {\n const availableCommands = this.getCommands(context);\n\n if (!query.trim()) {\n return this.sortCommands(availableCommands);\n }\n\n const lowerQuery = query.toLowerCase();\n\n // Score each command based on matching\n const scored = availableCommands.map((command) => {\n let score = 0;\n\n // Exact label match (highest priority)\n if (command.label.toLowerCase() === lowerQuery) {\n score += 1000;\n }\n // Label starts with query\n else if (command.label.toLowerCase().startsWith(lowerQuery)) {\n score += 500;\n }\n // Label contains query\n else if (command.label.toLowerCase().includes(lowerQuery)) {\n score += 250;\n }\n\n // Description contains query\n if (command.description?.toLowerCase().includes(lowerQuery)) {\n score += 100;\n }\n\n // Keywords match\n if (command.keywords) {\n const keywordMatch = command.keywords.some((keyword) =>\n keyword.toLowerCase().includes(lowerQuery)\n );\n if (keywordMatch) {\n score += 150;\n }\n }\n\n // Category match\n if (command.category?.toLowerCase().includes(lowerQuery)) {\n score += 50;\n }\n\n // Add priority to score\n if (command.priority) {\n score += command.priority;\n }\n\n return { command, score };\n });\n\n // Filter out commands with no match and sort by score\n return scored\n .filter((item) => item.score > 0)\n .sort((a, b) => b.score - a.score)\n .map((item) => item.command);\n }\n\n /**\n * Sort commands by priority and label\n * @param commands - Commands to sort\n * @returns Sorted commands\n */\n private sortCommands(commands: Command[]): Command[] {\n return commands.sort((a, b) => {\n // Sort by priority first (higher priority first)\n const priorityDiff = (b.priority || 0) - (a.priority || 0);\n if (priorityDiff !== 0) {\n return priorityDiff;\n }\n\n // Then by category\n const categoryA = a.category || '';\n const categoryB = b.category || '';\n const categoryDiff = categoryA.localeCompare(categoryB);\n if (categoryDiff !== 0) {\n return categoryDiff;\n }\n\n // Finally by label\n return a.label.localeCompare(b.label);\n });\n }\n\n /**\n * Subscribe to registry changes\n * @param listener - Callback function called when registry changes\n * @returns Unsubscribe function\n */\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n /**\n * Clear all commands\n */\n clear(): void {\n this.commands.clear();\n this.notifyListeners();\n }\n\n /**\n * Get count of registered commands\n */\n get size(): number {\n return this.commands.size;\n }\n\n /**\n * Notify all listeners of registry changes\n */\n private notifyListeners(): void {\n this.listeners.forEach((listener) => listener());\n }\n}\n\n// Singleton instance for global command registry\nlet globalRegistry: CommandRegistryService | null = null;\n\n/**\n * Get the global command registry instance\n * @returns Global CommandRegistryService instance\n */\nexport function getGlobalCommandRegistry(): CommandRegistryService {\n if (!globalRegistry) {\n globalRegistry = new CommandRegistryService();\n }\n return globalRegistry;\n}\n\n/**\n * Reset the global command registry (useful for testing)\n */\nexport function resetGlobalCommandRegistry(): void {\n globalRegistry = null;\n}\n","import { useState, useCallback, useEffect, useMemo } from 'react';\nimport type {\n Command,\n CommandContext,\n UseCommandPaletteReturn,\n CommandPaletteKeyboardConfig,\n CommandPaletteConfig,\n} from '../types/command.types';\nimport { CommandRegistryService } from '../services/CommandRegistryService';\n\ninterface UseCommandPaletteProps {\n /** Command context */\n context: CommandContext;\n /** Initial commands to register */\n commands?: Command[];\n /** Keyboard configuration */\n keyboard?: CommandPaletteKeyboardConfig;\n /** Command palette configuration */\n config?: CommandPaletteConfig;\n /** Command registry service (optional, uses global if not provided) */\n registry?: CommandRegistryService;\n}\n\n/**\n * Hook for managing command palette state and behavior\n * Handles command registration, filtering, keyboard navigation, and execution\n */\nexport function useCommandPalette({\n context,\n commands: initialCommands = [],\n keyboard = { key: ' ', altKey: true },\n config = {},\n registry: providedRegistry,\n}: UseCommandPaletteProps): UseCommandPaletteReturn {\n const [isOpen, setIsOpen] = useState(false);\n const [query, setQuery] = useState('');\n const [selectedIndex, setSelectedIndex] = useState(0);\n const [registeredCommands, setRegisteredCommands] = useState<Command[]>([]);\n\n // Use provided registry or create a new one\n const registry = useMemo(\n () => providedRegistry || new CommandRegistryService(),\n [providedRegistry]\n );\n\n // Create command context with close function (before effects)\n const commandContext = useMemo<CommandContext>(\n () => ({\n ...context,\n closeCommandPalette: () => setIsOpen(false),\n }),\n [context]\n );\n\n // Register initial commands and subscribe to changes\n useEffect(() => {\n let isSubscribed = true;\n\n // Subscribe to changes first\n const unsubscribe = registry.subscribe(() => {\n if (isSubscribed) {\n const updatedCommands = registry.getCommands(commandContext);\n setRegisteredCommands(updatedCommands);\n }\n });\n\n // Register commands after subscribing (this will trigger the subscription)\n if (initialCommands.length > 0) {\n registry.registerCommands(initialCommands);\n } else {\n // If no initial commands, still need to get current commands\n const commands = registry.getCommands(commandContext);\n setRegisteredCommands(commands);\n }\n\n return () => {\n isSubscribed = false;\n unsubscribe();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [registry]);\n\n // Filter commands based on query\n const filteredCommands = useMemo(() => {\n if (config.fuzzySearch === false) {\n // Simple substring matching\n return registry.searchCommands(query, commandContext);\n }\n\n // Use registry's built-in search\n return registry.searchCommands(query, commandContext);\n }, [query, registry, commandContext, config.fuzzySearch]);\n\n // Reset selected index when filtered commands change\n useEffect(() => {\n setSelectedIndex(0);\n }, [filteredCommands]);\n\n // Open command palette\n const open = useCallback(() => {\n setIsOpen(true);\n setQuery('');\n setSelectedIndex(0);\n\n // Emit event\n context.events?.emit({\n type: 'command-palette:opened',\n source: 'command-palette',\n timestamp: Date.now(),\n payload: {},\n });\n }, [context.events]);\n\n // Close command palette\n const close = useCallback(() => {\n setIsOpen(false);\n setQuery('');\n setSelectedIndex(0);\n\n // Emit event\n context.events?.emit({\n type: 'command-palette:closed',\n source: 'command-palette',\n timestamp: Date.now(),\n payload: {},\n });\n }, [context.events]);\n\n // Toggle command palette\n const toggle = useCallback(() => {\n if (isOpen) {\n close();\n } else {\n open();\n }\n }, [isOpen, open, close]);\n\n // Execute a command by ID\n const executeCommand = useCallback(\n async (commandId: string) => {\n await registry.executeCommand(commandId, commandContext);\n close();\n },\n [registry, commandContext, close]\n );\n\n // Navigate to next command\n const selectNext = useCallback(() => {\n setSelectedIndex((prev) => {\n const maxResults = config.maxResults || filteredCommands.length;\n const maxIndex = Math.min(filteredCommands.length, maxResults) - 1;\n return prev < maxIndex ? prev + 1 : 0;\n });\n }, [filteredCommands.length, config.maxResults]);\n\n // Navigate to previous command\n const selectPrevious = useCallback(() => {\n setSelectedIndex((prev) => {\n const maxResults = config.maxResults || filteredCommands.length;\n const maxIndex = Math.min(filteredCommands.length, maxResults) - 1;\n return prev > 0 ? prev - 1 : maxIndex;\n });\n }, [filteredCommands.length, config.maxResults]);\n\n // Execute the currently selected command (always first result)\n const executeSelected = useCallback(async () => {\n // Always execute the first filtered command\n const firstCommand = filteredCommands[0];\n\n if (firstCommand) {\n await executeCommand(firstCommand.id);\n }\n }, [filteredCommands, executeCommand]);\n\n // Register new commands\n const registerCommands = useCallback(\n (commands: Command[]) => {\n registry.registerCommands(commands);\n },\n [registry]\n );\n\n // Unregister commands\n const unregisterCommands = useCallback(\n (commandIds: string[]) => {\n registry.unregisterCommands(commandIds);\n },\n [registry]\n );\n\n // Handle keyboard shortcut to open command palette\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n const {\n key = ' ',\n altKey = true,\n ctrlKey = false,\n metaKey = false,\n shiftKey = false,\n } = keyboard;\n\n // Check if the keyboard shortcut matches\n const modifiersMatch =\n e.altKey === altKey &&\n e.ctrlKey === ctrlKey &&\n e.metaKey === metaKey &&\n e.shiftKey === shiftKey;\n\n // Use event.code for Space key to match usePanelKeyboardShortcuts pattern\n const keyMatches = key === ' ' ? e.code === 'Space' : e.key === key;\n\n if (keyMatches && modifiersMatch) {\n // Don't trigger if user is typing in an input field\n const target = e.target as HTMLElement;\n if (\n target.tagName === 'INPUT' ||\n target.tagName === 'TEXTAREA' ||\n target.isContentEditable\n ) {\n return;\n }\n\n e.preventDefault();\n toggle();\n }\n },\n [keyboard, toggle]\n );\n\n useEffect(() => {\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [handleKeyDown]);\n\n return {\n isOpen,\n open,\n close,\n toggle,\n query,\n setQuery,\n filteredCommands,\n executeCommand,\n selectedIndex,\n setSelectedIndex,\n selectNext,\n selectPrevious,\n executeSelected,\n commands: registeredCommands,\n registerCommands,\n unregisterCommands,\n };\n}\n","import type { Command } from '../types/command.types';\n\n/**\n * Built-in commands for panel navigation and control\n */\nexport const panelCommands: Command[] = [\n {\n id: 'panel.focus.left',\n label: 'Focus Left Panel',\n description: 'Set focus to the left panel',\n icon: '◀',\n category: 'Panel Navigation',\n shortcut: 'Alt+1',\n priority: 100,\n keywords: ['left', 'sidebar', 'focus', 'switch'],\n execute: (context) => {\n context.setFocus('left');\n },\n isAvailable: (context) => context.focusedPanel !== 'left',\n },\n {\n id: 'panel.focus.middle',\n label: 'Focus Middle Panel',\n description: 'Set focus to the middle panel',\n icon: '▣',\n category: 'Panel Navigation',\n shortcut: 'Alt+2',\n priority: 100,\n keywords: ['middle', 'center', 'main', 'focus', 'switch'],\n execute: (context) => {\n context.setFocus('middle');\n },\n isAvailable: (context) => context.focusedPanel !== 'middle',\n },\n {\n id: 'panel.focus.right',\n label: 'Focus Right Panel',\n description: 'Set focus to the right panel',\n icon: '▶',\n category: 'Panel Navigation',\n shortcut: 'Alt+3',\n priority: 100,\n keywords: ['right', 'sidebar', 'focus', 'switch'],\n execute: (context) => {\n context.setFocus('right');\n },\n isAvailable: (context) => context.focusedPanel !== 'right',\n },\n {\n id: 'panel.toggle.left',\n label: 'Toggle Left Panel',\n description: 'Expand or collapse the left panel',\n icon: '◀◀',\n category: 'Panel Control',\n keywords: ['toggle', 'left', 'collapse', 'expand', 'hide', 'show'],\n priority: 80,\n execute: (context) => {\n context.events?.emit({\n type: 'panel:toggle',\n source: 'command-palette',\n timestamp: Date.now(),\n payload: { panelId: 'left' },\n });\n },\n },\n {\n id: 'panel.toggle.right',\n label: 'Toggle Right Panel',\n description: 'Expand or collapse the right panel',\n icon: '▶▶',\n category: 'Panel Control',\n keywords: ['toggle', 'right', 'collapse', 'expand', 'hide', 'show'],\n priority: 80,\n execute: (context) => {\n context.events?.emit({\n type: 'panel:toggle',\n source: 'command-palette',\n timestamp: Date.now(),\n payload: { panelId: 'right' },\n });\n },\n },\n {\n id: 'panel.collapse.all',\n label: 'Collapse All Panels',\n description: 'Collapse all side panels to maximize middle panel',\n icon: '⬌',\n category: 'Panel Control',\n keywords: ['collapse', 'hide', 'all', 'maximize', 'focus mode'],\n priority: 70,\n execute: (context) => {\n context.events?.emit({\n type: 'panel:collapse-all',\n source: 'command-palette',\n timestamp: Date.now(),\n payload: {},\n });\n },\n },\n {\n id: 'panel.expand.all',\n label: 'Expand All Panels',\n description: 'Expand all side panels to default layout',\n icon: '⬍',\n category: 'Panel Control',\n keywords: ['expand', 'show', 'all', 'restore', 'default'],\n priority: 70,\n execute: (context) => {\n context.events?.emit({\n type: 'panel:expand-all',\n source: 'command-palette',\n timestamp: Date.now(),\n payload: {},\n });\n },\n },\n {\n id: 'panel.refresh',\n label: 'Refresh Panel Data',\n description: 'Reload data for the currently focused panel',\n icon: '↻',\n category: 'Panel Control',\n keywords: ['refresh', 'reload', 'update', 'sync'],\n priority: 60,\n execute: (context) => {\n const panelId = context.focusedPanel;\n if (!panelId) return;\n\n context.events?.emit({\n type: 'panel:refresh',\n source: 'command-palette',\n timestamp: Date.now(),\n payload: { panelId },\n });\n },\n isAvailable: (context) => context.focusedPanel !== null,\n },\n {\n id: 'panel.reset.layout',\n label: 'Reset Panel Layout',\n description: 'Reset panel sizes to default layout',\n icon: '⟲',\n category: 'Panel Control',\n keywords: ['reset', 'layout', 'default', 'restore'],\n priority: 50,\n execute: (context) => {\n context.events?.emit({\n type: 'panel:reset-layout',\n source: 'command-palette',\n timestamp: Date.now(),\n payload: {},\n });\n },\n },\n];\n\n/**\n * Get panel commands\n * @returns Array of panel-related commands\n */\nexport function getPanelCommands(): Command[] {\n return panelCommands;\n}\n"],"names":["LocalStoragePersistenceAdapter","__publicField","viewKey","stored","error","state","usePanelPersistence","options","defaultSizes","panelType","adapter","sizes","setSizes","useState","collapsed","setCollapsed","prevCollapsedRef","useRef","lastNonZeroSizesRef","saveTimeoutRef","pendingPersistSizesRef","useEffect","saved","updateLastNonZeroSizes","useCallback","incomingSizes","getFallbackSize","panel","storedSize","prevDefaultSizesRef","leftChanged","rightChanged","savePreferences","newSizes","handlePanelResize","sanitizedSizes","shouldPersist","leftCollapsed","leftSize","fallback","rightCollapsed","rightSize","pendingSizes","handleLeftCollapseComplete","handleLeftExpandComplete","handleRightCollapseComplete","handleRightExpandComplete","LocalStorageWorkspaceAdapter","presets","repositoryKey","key","allStates","i","parseError","WorkspaceLayoutService","builtInWorkspaces","id","userWorkspaces","workspace","updatedPresets","updates","existingWorkspace","updatedWorkspace","currentState","repoState","hasSizeDeviation","hasCollapsedDeviation","workspaceId","layout","workspaces","layout1","layout2","name","now","useWorkspace","autoInitialize","defaultWorkspaceId","setWorkspaces","repositoryState","setRepositoryState","activeWorkspace","setActiveWorkspace","loading","setLoading","setError","loadData","allWorkspaces","err","getWorkspace","createWorkspace","createOptions","updateWorkspace","deleteWorkspace","success","applyWorkspace","newState","updateSizes","updateCollapsed","resetToDefaults","refresh","usePanelFocus","initialFocus","onFocusChange","events","getPanelId","focusedPanel","setFocusedPanelState","setFocus","previousPanel","prevPanelId","panelId","clearFocus","getVisiblePanels","panels","focusNext","visiblePanels","currentIndex","nextIndex","focusPrevious","prevIndex","isFocused","usePanelKeyboardShortcuts","enabled","onExpand","onCollapse","focusedPanelRef","collapsedRef","panelTypeRef","handleKeyDown","event","code","currentFocused","currentCollapsed","currentPanelType","usePanelFocusListener","onFocus","onBlur","unsubscribeFocus","unsubscribeBlur","FocusIndicator","className","style","defaultStyles","jsx","CommandInput","value","onChange","placeholder","onClose","onEnter","theme","useTheme","inputRef","e","CommandItem","forwardRef","command","isSelected","onClick","onMouseEnter","ref","label","description","icon","shortcut","isHovered","setIsHovered","React","jsxs","CommandList","commands","selectedIndex","onSelect","onHover","maxResults","listRef","selectedItemRef","displayedCommands","item","container","itemTop","itemBottom","containerScrollTop","containerHeight","groupedCommands","acc","index","category","categories","a","b","CommandPalette","commandPalette","config","containerRef","isOpen","close","query","setQuery","filteredCommands","setSelectedIndex","executeSelected","handleClickOutside","timeoutId","maxHeight","Fragment","CommandRegistryService","commandIds","commandId","context","allCommands","_a","_b","availableCommands","lowerQuery","score","keyword","priorityDiff","categoryA","categoryB","categoryDiff","listener","globalRegistry","getGlobalCommandRegistry","resetGlobalCommandRegistry","useCommandPalette","initialCommands","keyboard","providedRegistry","setIsOpen","registeredCommands","setRegisteredCommands","registry","useMemo","commandContext","isSubscribed","unsubscribe","updatedCommands","open","toggle","executeCommand","selectNext","prev","maxIndex","selectPrevious","firstCommand","registerCommands","unregisterCommands","altKey","ctrlKey","metaKey","shiftKey","modifiersMatch","target","panelCommands","getPanelCommands"],"mappings":"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"}
1
+ {"version":3,"file":"index.esm.js","sources":["../src/hooks/usePanelPersistence.ts","../src/services/LocalStorageWorkspaceAdapter.ts","../src/services/WorkspaceLayoutService.ts","../src/hooks/useWorkspace.ts","../src/keyboard/hooks/usePanelFocus.ts","../src/keyboard/hooks/usePanelKeyboardShortcuts.ts","../src/keyboard/hooks/usePanelFocusListener.ts","../src/keyboard/components/FocusIndicator.tsx","../src/command-palette/components/CommandInput.tsx","../src/command-palette/components/CommandItem.tsx","../src/command-palette/components/CommandList.tsx","../src/command-palette/components/CommandPalette.tsx","../src/command-palette/services/CommandRegistryService.ts","../src/command-palette/hooks/useCommandPalette.ts","../src/command-palette/commands/panelCommands.ts"],"sourcesContent":["/**\n * usePanelPersistence Hook\n *\n * Extracted and adapted from electron-app/src/renderer/hooks/usePanelPersistence.ts\n * Manages saving and loading panel sizes and collapsed states with debounced persistence.\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react';\nimport type {\n UsePanelPersistenceOptions,\n PanelSizes,\n TwoPanelSizes,\n PanelCollapsed,\n PanelPersistence,\n PersistenceAdapter,\n} from '../types/persistence.types';\n\n/**\n * Default localStorage-based persistence adapter for web applications\n */\nexport class LocalStoragePersistenceAdapter implements PersistenceAdapter {\n private storageKey = 'panel-layouts';\n\n async load(viewKey: string) {\n try {\n const stored = localStorage.getItem(`${this.storageKey}:${viewKey}`);\n return stored ? JSON.parse(stored) : null;\n } catch (error) {\n console.error(`Failed to load panel layout for ${viewKey}:`, error);\n return null;\n }\n }\n\n async save(viewKey: string, state: { sizes: PanelSizes | TwoPanelSizes }) {\n try {\n localStorage.setItem(\n `${this.storageKey}:${viewKey}`,\n JSON.stringify(state),\n );\n } catch (error) {\n console.error(`Failed to save panel layout for ${viewKey}:`, error);\n }\n }\n}\n\n/**\n * Hook for persisting panel layouts across sessions\n *\n * Manages panel sizes and collapsed states with automatic debounced saving.\n * Supports both 2-panel and 3-panel layouts.\n *\n * @param options - Configuration options for persistence\n * @returns Panel state and handlers for resizing and collapsing\n *\n * @example\n * ```tsx\n * const persistence = usePanelPersistence({\n * viewKey: 'my-app',\n * defaultSizes: { left: 30, middle: 70, right: 0 },\n * collapsed: { left: false, right: true },\n * panelType: 'three-panel',\n * });\n *\n * <ConfigurablePanelLayout\n * {...otherProps}\n * defaultSizes={persistence.sizes}\n * collapsed={persistence.collapsed}\n * onPanelResize={persistence.handlePanelResize}\n * />\n * ```\n */\nexport function usePanelPersistence(\n options: UsePanelPersistenceOptions,\n): PanelPersistence {\n const {\n viewKey,\n defaultSizes,\n panelType,\n adapter = new LocalStoragePersistenceAdapter(),\n } = options;\n\n const [sizes, setSizes] = useState(defaultSizes);\n const [collapsed, setCollapsed] = useState(options.collapsed);\n const prevCollapsedRef = useRef(options.collapsed);\n const lastNonZeroSizesRef = useRef<Partial<PanelSizes & TwoPanelSizes>>({});\n const saveTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pendingPersistSizesRef = useRef<typeof sizes | null>(null);\n\n // Load saved state on mount\n useEffect(() => {\n const loadSavedState = async () => {\n const saved = await adapter.load(viewKey);\n if (saved?.sizes) {\n setSizes(saved.sizes as typeof sizes);\n updateLastNonZeroSizes(saved.sizes);\n }\n };\n loadSavedState();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [viewKey]);\n\n const updateLastNonZeroSizes = useCallback(\n (incomingSizes: PanelSizes | TwoPanelSizes) => {\n if ('left' in incomingSizes && incomingSizes.left > 0) {\n lastNonZeroSizesRef.current.left = incomingSizes.left;\n }\n\n if ('middle' in incomingSizes && incomingSizes.middle > 0) {\n lastNonZeroSizesRef.current.middle = incomingSizes.middle;\n }\n\n if ('right' in incomingSizes && incomingSizes.right > 0) {\n lastNonZeroSizesRef.current.right = incomingSizes.right;\n }\n },\n [],\n );\n\n const getFallbackSize = useCallback(\n (panel: 'left' | 'right') => {\n const storedSize = lastNonZeroSizesRef.current[panel];\n if (storedSize && storedSize > 0) {\n return storedSize;\n }\n\n if (panel === 'left' && 'left' in defaultSizes && defaultSizes.left > 0) {\n return defaultSizes.left;\n }\n\n if (\n panel === 'right' &&\n 'right' in defaultSizes &&\n defaultSizes.right > 0\n ) {\n return defaultSizes.right;\n }\n\n return undefined;\n },\n [defaultSizes],\n );\n\n // Update sizes when defaultSizes changes (parent has loaded preferences)\n const prevDefaultSizesRef = useRef(defaultSizes);\n useEffect(() => {\n // Only update if the actual values changed, not just the reference\n const hasChanged =\n ('left' in defaultSizes &&\n defaultSizes.left !== prevDefaultSizesRef.current.left) ||\n ('middle' in defaultSizes &&\n 'middle' in prevDefaultSizesRef.current &&\n defaultSizes.middle !==\n (prevDefaultSizesRef.current as PanelSizes).middle) ||\n ('right' in defaultSizes &&\n defaultSizes.right !== prevDefaultSizesRef.current.right);\n\n if (hasChanged) {\n setSizes(defaultSizes);\n updateLastNonZeroSizes(defaultSizes);\n prevDefaultSizesRef.current = defaultSizes;\n }\n }, [defaultSizes, updateLastNonZeroSizes]);\n\n // Sync with parent's collapsed state (e.g., from titlebar buttons)\n useEffect(() => {\n const leftChanged =\n options.collapsed.left !== prevCollapsedRef.current.left;\n const rightChanged =\n 'right' in options.collapsed &&\n 'right' in prevCollapsedRef.current &&\n (options.collapsed as PanelCollapsed).right !==\n (prevCollapsedRef.current as PanelCollapsed).right;\n\n if (leftChanged || rightChanged) {\n setCollapsed(options.collapsed);\n prevCollapsedRef.current = { ...options.collapsed };\n }\n }, [options.collapsed.left, (options.collapsed as PanelCollapsed).right]);\n\n // Save preferences helper (only saves sizes, not collapsed state)\n const savePreferences = useCallback(\n async (newSizes: typeof sizes) => {\n try {\n await adapter.save(viewKey, { sizes: newSizes });\n } catch (error) {\n console.error(\n `Failed to save panel preferences for ${viewKey}:`,\n error,\n );\n }\n },\n [viewKey, adapter],\n );\n\n // Handle panel resize (debounced)\n const handlePanelResize = useCallback(\n (newSizes: typeof sizes) => {\n const sanitizedSizes = { ...newSizes } as typeof newSizes;\n let shouldPersist = true;\n\n if ('left' in newSizes) {\n const leftCollapsed = Boolean((collapsed as PanelCollapsed)?.left);\n const leftSize = newSizes.left;\n\n if (leftCollapsed) {\n const fallback = getFallbackSize('left');\n if (fallback !== undefined && fallback > 0) {\n sanitizedSizes.left = fallback;\n } else {\n shouldPersist = false;\n }\n } else if (leftSize === 0) {\n shouldPersist = false;\n }\n }\n\n if (panelType === 'three-panel' && 'right' in newSizes) {\n const rightCollapsed = Boolean((collapsed as PanelCollapsed)?.right);\n const rightSize = newSizes.right;\n\n if (rightCollapsed) {\n const fallback = getFallbackSize('right');\n if (fallback !== undefined && fallback > 0) {\n sanitizedSizes.right = fallback;\n } else {\n shouldPersist = false;\n }\n } else if (rightSize === 0) {\n shouldPersist = false;\n }\n }\n\n setSizes(sanitizedSizes);\n updateLastNonZeroSizes(sanitizedSizes);\n\n if (saveTimeoutRef.current) {\n clearTimeout(saveTimeoutRef.current);\n saveTimeoutRef.current = null;\n }\n\n if (!shouldPersist) {\n pendingPersistSizesRef.current = null;\n return;\n }\n\n pendingPersistSizesRef.current = sanitizedSizes;\n saveTimeoutRef.current = setTimeout(() => {\n const pendingSizes = pendingPersistSizesRef.current;\n if (pendingSizes) {\n savePreferences(pendingSizes);\n pendingPersistSizesRef.current = null;\n }\n saveTimeoutRef.current = null;\n }, 500);\n },\n [\n collapsed,\n getFallbackSize,\n panelType,\n savePreferences,\n updateLastNonZeroSizes,\n ],\n );\n\n // Cleanup: save any pending changes on unmount\n useEffect(() => {\n return () => {\n if (saveTimeoutRef.current) {\n const pendingSizes = pendingPersistSizesRef.current;\n if (pendingSizes) {\n savePreferences(pendingSizes);\n pendingPersistSizesRef.current = null;\n }\n clearTimeout(saveTimeoutRef.current);\n saveTimeoutRef.current = null;\n }\n };\n }, [savePreferences]);\n\n // Collapse/expand handlers - no-ops because state is controlled by parent\n // The parent manages collapsed state via titlebar buttons and passes it down as props\n const handleLeftCollapseComplete = useCallback(async () => {\n // No-op: parent controls state\n }, []);\n\n const handleLeftExpandComplete = useCallback(async () => {\n // No-op: parent controls state\n }, []);\n\n const handleRightCollapseComplete = useCallback(async () => {\n // No-op: parent controls state\n }, []);\n\n const handleRightExpandComplete = useCallback(async () => {\n // No-op: parent controls state\n }, []);\n\n if (panelType === 'three-panel') {\n return {\n type: 'three-panel',\n sizes: sizes as PanelSizes,\n collapsed: collapsed as PanelCollapsed,\n handlePanelResize: handlePanelResize as (sizes: PanelSizes) => void,\n handleLeftCollapseComplete,\n handleLeftExpandComplete,\n handleRightCollapseComplete,\n handleRightExpandComplete,\n };\n } else {\n return {\n type: 'two-panel',\n sizes: sizes as TwoPanelSizes,\n collapsed: collapsed as { left?: boolean },\n handlePanelResize: handlePanelResize as (sizes: TwoPanelSizes) => void,\n handleLeftCollapseComplete,\n handleLeftExpandComplete,\n };\n }\n}\n","/**\n * LocalStorageWorkspaceAdapter - Browser localStorage implementation\n * Stores workspace presets and repository states in browser localStorage\n */\n\nimport type {\n WorkspaceLayout,\n WorkspaceStorageAdapter,\n RepositoryWorkspaceState,\n} from '../types/workspace.types';\n\nexport class LocalStorageWorkspaceAdapter implements WorkspaceStorageAdapter {\n private readonly PRESETS_KEY = 'panel-layouts:workspace-presets';\n private readonly REPO_STATE_PREFIX = 'panel-layouts:repo-state:';\n\n /**\n * Load all user-created workspace presets\n */\n async loadWorkspacePresets(): Promise<Record<string, WorkspaceLayout>> {\n try {\n const stored = localStorage.getItem(this.PRESETS_KEY);\n if (!stored) {\n return {};\n }\n return JSON.parse(stored);\n } catch (error) {\n console.error('Failed to load workspace presets:', error);\n return {};\n }\n }\n\n /**\n * Save workspace presets\n */\n async saveWorkspacePresets(\n presets: Record<string, WorkspaceLayout>,\n ): Promise<void> {\n try {\n localStorage.setItem(this.PRESETS_KEY, JSON.stringify(presets));\n } catch (error) {\n console.error('Failed to save workspace presets:', error);\n throw error;\n }\n }\n\n /**\n * Load repository-specific workspace state\n */\n async loadRepositoryState(\n repositoryKey: string,\n ): Promise<RepositoryWorkspaceState | null> {\n try {\n const key = `${this.REPO_STATE_PREFIX}${repositoryKey}`;\n const stored = localStorage.getItem(key);\n if (!stored) {\n return null;\n }\n return JSON.parse(stored);\n } catch (error) {\n console.error(\n `Failed to load repository state for ${repositoryKey}:`,\n error,\n );\n return null;\n }\n }\n\n /**\n * Save repository-specific workspace state\n */\n async saveRepositoryState(\n repositoryKey: string,\n state: RepositoryWorkspaceState,\n ): Promise<void> {\n try {\n const key = `${this.REPO_STATE_PREFIX}${repositoryKey}`;\n localStorage.setItem(key, JSON.stringify(state));\n } catch (error) {\n console.error(\n `Failed to save repository state for ${repositoryKey}:`,\n error,\n );\n throw error;\n }\n }\n\n /**\n * Load all repository states\n */\n async loadAllRepositoryStates(): Promise<\n Record<string, RepositoryWorkspaceState>\n > {\n try {\n const allStates: Record<string, RepositoryWorkspaceState> = {};\n\n // Iterate through all localStorage keys\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key && key.startsWith(this.REPO_STATE_PREFIX)) {\n const repositoryKey = key.substring(this.REPO_STATE_PREFIX.length);\n const stored = localStorage.getItem(key);\n if (stored) {\n try {\n allStates[repositoryKey] = JSON.parse(stored);\n } catch (parseError) {\n console.error(\n `Failed to parse repository state for ${repositoryKey}:`,\n parseError,\n );\n }\n }\n }\n }\n\n return allStates;\n } catch (error) {\n console.error('Failed to load all repository states:', error);\n return {};\n }\n }\n}\n","/**\n * WorkspaceLayoutService - Manages workspace layout presets\n * Extracted from electron-app/src/renderer/services/WorkspaceLayoutService.ts\n *\n * This service handles CRUD operations for workspace layouts (panel configuration presets)\n * and provides utilities for comparing layouts and managing built-in workspaces.\n */\n\nimport type { PanelLayout } from '@principal-ade/panels';\nimport type {\n WorkspaceLayout,\n WorkspaceStorageAdapter,\n RepositoryWorkspaceState,\n CreateWorkspaceOptions,\n UpdateWorkspaceOptions,\n} from '../types/workspace.types';\nimport { LocalStorageWorkspaceAdapter } from './LocalStorageWorkspaceAdapter';\n\nexport class WorkspaceLayoutService {\n private static adapter: WorkspaceStorageAdapter =\n new LocalStorageWorkspaceAdapter();\n\n /**\n * Configure a custom storage adapter (for Electron IPC or remote storage)\n */\n static setAdapter(adapter: WorkspaceStorageAdapter): void {\n this.adapter = adapter;\n }\n\n /**\n * Get all workspace layouts (including built-in)\n */\n static async getWorkspaceLayouts(): Promise<Record<string, WorkspaceLayout>> {\n const builtInWorkspaces = this.getBuiltInWorkspaceLayouts();\n const userWorkspaces = await this.adapter.loadWorkspacePresets();\n\n // Merge built-in and user workspaces, built-in takes precedence\n return {\n ...userWorkspaces,\n ...builtInWorkspaces,\n };\n }\n\n /**\n * Get a specific workspace layout by ID\n */\n static async getWorkspaceLayout(id: string): Promise<WorkspaceLayout | null> {\n const workspaces = await this.getWorkspaceLayouts();\n return workspaces[id] || null;\n }\n\n /**\n * Create a new workspace layout\n */\n static async createWorkspaceLayout(\n options: CreateWorkspaceOptions,\n ): Promise<WorkspaceLayout> {\n const userWorkspaces = await this.adapter.loadWorkspacePresets();\n const id = this.generateWorkspaceId(options.name);\n\n const workspace: WorkspaceLayout = {\n id,\n name: options.name,\n description: options.description,\n layout: options.layout,\n defaultSizes: options.defaultSizes,\n defaultCollapsed: options.defaultCollapsed,\n createdAt: Date.now(),\n updatedAt: Date.now(),\n isBuiltIn: false,\n };\n\n const updatedPresets = {\n ...userWorkspaces,\n [id]: workspace,\n };\n\n await this.adapter.saveWorkspacePresets(updatedPresets);\n\n return workspace;\n }\n\n /**\n * Update an existing workspace layout\n */\n static async updateWorkspaceLayout(\n id: string,\n updates: UpdateWorkspaceOptions,\n ): Promise<WorkspaceLayout | null> {\n const userWorkspaces = await this.adapter.loadWorkspacePresets();\n const existingWorkspace = userWorkspaces[id];\n\n if (!existingWorkspace) {\n console.error(`Workspace layout ${id} not found`);\n return null;\n }\n\n // Don't allow updating built-in workspaces\n if (existingWorkspace.isBuiltIn) {\n console.error(`Cannot update built-in workspace layout ${id}`);\n return null;\n }\n\n const updatedWorkspace: WorkspaceLayout = {\n ...existingWorkspace,\n ...updates,\n id, // Preserve ID\n createdAt: existingWorkspace.createdAt, // Preserve creation time\n updatedAt: Date.now(),\n };\n\n const updatedPresets = {\n ...userWorkspaces,\n [id]: updatedWorkspace,\n };\n\n await this.adapter.saveWorkspacePresets(updatedPresets);\n\n return updatedWorkspace;\n }\n\n /**\n * Delete a workspace layout\n */\n static async deleteWorkspaceLayout(id: string): Promise<boolean> {\n const userWorkspaces = await this.adapter.loadWorkspacePresets();\n const workspace = userWorkspaces[id];\n\n if (!workspace) {\n console.error(`Workspace layout ${id} not found`);\n return false;\n }\n\n // Don't allow deleting built-in workspaces\n if (workspace.isBuiltIn) {\n console.error(`Cannot delete built-in workspace layout ${id}`);\n return false;\n }\n\n const updatedPresets = { ...userWorkspaces };\n delete updatedPresets[id];\n\n await this.adapter.saveWorkspacePresets(updatedPresets);\n\n return true;\n }\n\n /**\n * Get repository state (which workspace + current sizes/collapsed)\n */\n static async getRepositoryState(\n repositoryKey: string,\n ): Promise<RepositoryWorkspaceState | null> {\n return await this.adapter.loadRepositoryState(repositoryKey);\n }\n\n /**\n * Set repository state (which workspace + current sizes/collapsed/layout)\n */\n static async setRepositoryState(\n repositoryKey: string,\n state: RepositoryWorkspaceState,\n ): Promise<void> {\n await this.adapter.saveRepositoryState(repositoryKey, state);\n }\n\n /**\n * Update only sizes in repository state\n */\n static async updateRepositorySizes(\n repositoryKey: string,\n sizes: { left: number; middle: number; right: number },\n ): Promise<void> {\n const currentState = await this.getRepositoryState(repositoryKey);\n if (!currentState) return;\n\n await this.setRepositoryState(repositoryKey, {\n ...currentState,\n sizes,\n });\n }\n\n /**\n * Update only collapsed state in repository state\n */\n static async updateRepositoryCollapsed(\n repositoryKey: string,\n collapsed: { left?: boolean; right?: boolean },\n ): Promise<void> {\n const currentState = await this.getRepositoryState(repositoryKey);\n if (!currentState) return;\n\n await this.setRepositoryState(repositoryKey, {\n ...currentState,\n collapsed,\n });\n }\n\n /**\n * Check if repository state differs from workspace defaults\n */\n static hasStateDeviation(\n repoState: {\n workspaceId: string | null;\n sizes: { left: number; middle: number; right: number };\n collapsed: { left?: boolean; right?: boolean };\n },\n workspace: WorkspaceLayout,\n ): {\n hasSizeDeviation: boolean;\n hasCollapsedDeviation: boolean;\n } {\n const hasSizeDeviation = workspace.defaultSizes\n ? JSON.stringify(repoState.sizes) !==\n JSON.stringify(workspace.defaultSizes)\n : false;\n\n const hasCollapsedDeviation = workspace.defaultCollapsed\n ? JSON.stringify(repoState.collapsed) !==\n JSON.stringify(workspace.defaultCollapsed)\n : false;\n\n return { hasSizeDeviation, hasCollapsedDeviation };\n }\n\n /**\n * Update workspace defaults from repository state\n */\n static async updateWorkspaceFromRepositoryState(\n workspaceId: string,\n repositoryKey: string,\n ): Promise<void> {\n const workspace = await this.getWorkspaceLayout(workspaceId);\n const repoState = await this.getRepositoryState(repositoryKey);\n\n if (!workspace || !repoState || workspace.isBuiltIn) {\n console.error(\n 'Cannot update built-in workspace or workspace/state not found',\n );\n return;\n }\n\n await this.updateWorkspaceLayout(workspaceId, {\n defaultSizes: repoState.sizes,\n defaultCollapsed: repoState.collapsed,\n });\n }\n\n /**\n * Reset repository state to workspace defaults\n */\n static async resetRepositoryToWorkspaceDefaults(\n repositoryKey: string,\n workspaceId: string,\n ): Promise<void> {\n const workspace = await this.getWorkspaceLayout(workspaceId);\n if (!workspace) {\n console.error(`Workspace ${workspaceId} not found`);\n return;\n }\n\n const currentState = await this.getRepositoryState(repositoryKey);\n if (!currentState) return;\n\n await this.setRepositoryState(repositoryKey, {\n ...currentState,\n sizes: workspace.defaultSizes || { left: 20, middle: 45, right: 35 },\n collapsed: workspace.defaultCollapsed || { left: false, right: false },\n });\n }\n\n /**\n * Check if a layout matches a workspace layout\n */\n static isLayoutMatchingWorkspace(\n layout: PanelLayout,\n workspace: WorkspaceLayout,\n ): boolean {\n return this.areLayoutsEqual(layout, workspace.layout);\n }\n\n /**\n * Find workspace ID that matches the given layout\n */\n static async findMatchingWorkspace(\n layout: PanelLayout,\n ): Promise<string | null> {\n const workspaces = await this.getWorkspaceLayouts();\n\n for (const [id, workspace] of Object.entries(workspaces)) {\n if (this.isLayoutMatchingWorkspace(layout, workspace)) {\n return id;\n }\n }\n\n return null;\n }\n\n /**\n * Deep comparison of two panel layouts\n */\n private static areLayoutsEqual(\n layout1: PanelLayout,\n layout2: PanelLayout,\n ): boolean {\n return JSON.stringify(layout1) === JSON.stringify(layout2);\n }\n\n /**\n * Generate a unique ID from a workspace name\n */\n private static generateWorkspaceId(name: string): string {\n const base = name.toLowerCase().replace(/[^a-z0-9]+/g, '-');\n return `${base}-${Date.now()}`;\n }\n\n /**\n * Get built-in workspace layouts\n */\n static getBuiltInWorkspaceLayouts(): Record<string, WorkspaceLayout> {\n const now = Date.now();\n\n return {\n 'project-management': {\n id: 'project-management',\n name: 'Project Management',\n description:\n 'Tasks, dependencies, issues, file tree, docs, drawings, multi terminal, city visualization, code viewer, markdown slides, and excalidraw',\n layout: {\n left: {\n type: 'tabs',\n panels: [\n 'tasks',\n 'dependencies',\n 'gitIssues',\n 'fileTree',\n 'docs',\n 'drawings',\n ],\n config: { defaultActiveTab: 0, tabPosition: 'top' },\n },\n middle: 'multiTerminal',\n right: {\n type: 'tabs',\n panels: [\n 'cityVisualization',\n 'codeViewer',\n 'markdownViewer',\n 'excalidrawDiagram',\n ],\n config: { defaultActiveTab: 0, tabPosition: 'top' },\n },\n },\n defaultSizes: { left: 20, middle: 45, right: 35 },\n defaultCollapsed: { left: false, right: false },\n createdAt: now,\n updatedAt: now,\n isBuiltIn: true,\n },\n 'code-review': {\n id: 'code-review',\n name: 'Code Review',\n description:\n 'Git changes, pull requests, and file tree on left, git diff and code viewer in middle, city map on right',\n layout: {\n left: {\n type: 'tabs',\n panels: ['gitChanges', 'gitPullRequests', 'fileTree'],\n config: { defaultActiveTab: 0, tabPosition: 'top' },\n },\n middle: {\n type: 'tabs',\n panels: ['gitDiff', 'codeViewer'],\n config: { defaultActiveTab: 0, tabPosition: 'top' },\n },\n right: 'cityVisualization',\n },\n defaultSizes: { left: 20, middle: 50, right: 30 },\n defaultCollapsed: { left: false, right: false },\n createdAt: now,\n updatedAt: now,\n isBuiltIn: true,\n },\n documentation: {\n id: 'documentation',\n name: 'Documentation',\n description: 'Docs, markdown viewer, and code viewer',\n layout: {\n left: 'docs',\n middle: 'markdownViewer',\n right: 'codeViewer',\n },\n defaultSizes: { left: 20, middle: 50, right: 30 },\n defaultCollapsed: { left: false, right: true },\n createdAt: now,\n updatedAt: now,\n isBuiltIn: true,\n },\n 'agent-work': {\n id: 'agent-work',\n name: 'Agent Work',\n description:\n 'Tasks, agent sessions, file tree, agent context, git changes, docs, multi terminal, city map, agent events, code viewer, and markdown slides',\n layout: {\n left: {\n type: 'tabs',\n panels: [\n 'tasks',\n 'agentSessions',\n 'fileTree',\n 'agentContext',\n 'gitChanges',\n 'docs',\n ],\n config: { defaultActiveTab: 0, tabPosition: 'top' },\n },\n middle: 'multiTerminal',\n right: {\n type: 'tabs',\n panels: [\n 'cityVisualization',\n 'agentEvents',\n 'codeViewer',\n 'markdownViewer',\n ],\n config: { defaultActiveTab: 0, tabPosition: 'top' },\n },\n },\n defaultSizes: { left: 20, middle: 45, right: 35 },\n defaultCollapsed: { left: false, right: false },\n createdAt: now,\n updatedAt: now,\n isBuiltIn: true,\n },\n 'quality-check': {\n id: 'quality-check',\n name: 'Quality Check',\n description:\n 'Package information, tools, and dependencies on left; city visualization map in middle; multi terminal and code viewer on right (collapsed)',\n layout: {\n left: {\n type: 'tabs',\n panels: ['packageInfo', 'tools', 'dependencies'],\n config: { defaultActiveTab: 0, tabPosition: 'top' },\n },\n middle: 'cityVisualization',\n right: {\n type: 'tabs',\n panels: ['multiTerminal', 'codeViewer'],\n config: { defaultActiveTab: 0, tabPosition: 'top' },\n },\n },\n defaultSizes: { left: 20, middle: 45, right: 35 },\n defaultCollapsed: { left: false, right: true },\n createdAt: now,\n updatedAt: now,\n isBuiltIn: true,\n },\n drawing: {\n id: 'drawing',\n name: 'Drawing',\n description:\n 'Drawings and docs, excalidraw diagram, multi terminal and markdown viewer',\n layout: {\n left: {\n type: 'tabs',\n panels: ['drawings', 'docs'],\n config: { defaultActiveTab: 0, tabPosition: 'top' },\n },\n middle: 'excalidrawDiagram',\n right: {\n type: 'tabs',\n panels: ['multiTerminal', 'markdownViewer'],\n config: { defaultActiveTab: 0, tabPosition: 'top' },\n },\n },\n defaultSizes: { left: 20, middle: 50, right: 30 },\n defaultCollapsed: { left: false, right: true },\n createdAt: now,\n updatedAt: now,\n isBuiltIn: true,\n },\n 'old-school': {\n id: 'old-school',\n name: 'Old School',\n description:\n 'File tree, search, git changes, and docs on left; code viewer and markdown viewer in middle; multi terminal and city map on right (collapsed)',\n layout: {\n left: {\n type: 'tabs',\n panels: ['fileTree', 'search', 'gitChanges', 'docs'],\n config: { defaultActiveTab: 0, tabPosition: 'top' },\n },\n middle: {\n type: 'tabs',\n panels: ['codeViewer', 'markdownViewer'],\n config: { defaultActiveTab: 0, tabPosition: 'top' },\n },\n right: {\n type: 'tabs',\n panels: ['multiTerminal', 'cityVisualization'],\n config: { defaultActiveTab: 0, tabPosition: 'top' },\n },\n },\n defaultSizes: { left: 20, middle: 50, right: 30 },\n defaultCollapsed: { left: false, right: true },\n createdAt: now,\n updatedAt: now,\n isBuiltIn: true,\n },\n 'principal-office': {\n id: 'principal-office',\n name: 'Principal Office',\n description:\n 'Alexandria docs on left, MDX editor in middle, multi terminal on right',\n layout: {\n left: 'docs',\n middle: 'mdxEditor',\n right: 'multiTerminal',\n },\n defaultSizes: { left: 20, middle: 50, right: 30 },\n defaultCollapsed: { left: false, right: false },\n createdAt: now,\n updatedAt: now,\n isBuiltIn: true,\n },\n };\n }\n\n /**\n * Initialize workspace layouts with built-in defaults if none exist\n */\n static async initializeWorkspaceLayouts(): Promise<void> {\n const userWorkspaces = await this.adapter.loadWorkspacePresets();\n\n // Only initialize if there are no user workspaces yet\n // Built-in workspaces are always available via getBuiltInWorkspaceLayouts()\n if (Object.keys(userWorkspaces).length === 0) {\n // Nothing to do - built-in workspaces are always available\n // This method exists for compatibility with electron-app\n }\n }\n}\n","/**\n * useWorkspace - React hook for workspace management\n * Provides easy access to workspace operations and state\n */\n\nimport { useState, useEffect, useCallback } from 'react';\nimport { WorkspaceLayoutService } from '../services/WorkspaceLayoutService';\nimport type {\n WorkspaceLayout,\n RepositoryWorkspaceState,\n CreateWorkspaceOptions,\n UpdateWorkspaceOptions,\n} from '../types/workspace.types';\n\nexport interface UseWorkspaceOptions {\n /**\n * Optional repository key for repository-specific state\n * If provided, the hook will manage repository state\n */\n repositoryKey?: string;\n\n /**\n * Auto-initialize repository state if it doesn't exist\n */\n autoInitialize?: boolean;\n\n /**\n * Default workspace to use for auto-initialization\n */\n defaultWorkspaceId?: string;\n}\n\nexport interface UseWorkspaceReturn {\n /**\n * All available workspaces (built-in + user-created)\n */\n workspaces: Record<string, WorkspaceLayout>;\n\n /**\n * Current repository state (if repositoryKey provided)\n */\n repositoryState: RepositoryWorkspaceState | null;\n\n /**\n * Current active workspace (if repositoryKey provided)\n */\n activeWorkspace: WorkspaceLayout | null;\n\n /**\n * Loading state\n */\n loading: boolean;\n\n /**\n * Error state\n */\n error: Error | null;\n\n /**\n * Get a specific workspace by ID\n */\n getWorkspace: (id: string) => Promise<WorkspaceLayout | null>;\n\n /**\n * Create a new workspace\n */\n createWorkspace: (options: CreateWorkspaceOptions) => Promise<WorkspaceLayout>;\n\n /**\n * Update an existing workspace\n */\n updateWorkspace: (\n id: string,\n updates: UpdateWorkspaceOptions,\n ) => Promise<WorkspaceLayout | null>;\n\n /**\n * Delete a workspace\n */\n deleteWorkspace: (id: string) => Promise<boolean>;\n\n /**\n * Apply a workspace to the current repository\n */\n applyWorkspace: (workspaceId: string) => Promise<void>;\n\n /**\n * Update repository sizes\n */\n updateSizes: (sizes: {\n left: number;\n middle: number;\n right: number;\n }) => Promise<void>;\n\n /**\n * Update repository collapsed state\n */\n updateCollapsed: (collapsed: {\n left?: boolean;\n right?: boolean;\n }) => Promise<void>;\n\n /**\n * Reset repository to workspace defaults\n */\n resetToDefaults: () => Promise<void>;\n\n /**\n * Refresh workspace data\n */\n refresh: () => Promise<void>;\n}\n\nexport function useWorkspace(\n options: UseWorkspaceOptions = {},\n): UseWorkspaceReturn {\n const { repositoryKey, autoInitialize = false, defaultWorkspaceId } = options;\n\n const [workspaces, setWorkspaces] = useState<Record<string, WorkspaceLayout>>(\n {},\n );\n const [repositoryState, setRepositoryState] =\n useState<RepositoryWorkspaceState | null>(null);\n const [activeWorkspace, setActiveWorkspace] =\n useState<WorkspaceLayout | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n /**\n * Load all workspaces and repository state\n */\n const loadData = useCallback(async () => {\n try {\n setLoading(true);\n setError(null);\n\n // Load all workspaces\n const allWorkspaces =\n await WorkspaceLayoutService.getWorkspaceLayouts();\n setWorkspaces(allWorkspaces);\n\n // Load repository state if repositoryKey provided\n if (repositoryKey) {\n let repoState =\n await WorkspaceLayoutService.getRepositoryState(repositoryKey);\n\n // Auto-initialize if requested and state doesn't exist\n if (!repoState && autoInitialize) {\n const workspaceId =\n defaultWorkspaceId || 'project-management'; // Default to project-management\n const workspace =\n await WorkspaceLayoutService.getWorkspaceLayout(workspaceId);\n\n if (workspace) {\n repoState = {\n workspaceId,\n sizes: workspace.defaultSizes || {\n left: 20,\n middle: 45,\n right: 35,\n },\n collapsed: workspace.defaultCollapsed || {\n left: false,\n right: false,\n },\n };\n\n await WorkspaceLayoutService.setRepositoryState(\n repositoryKey,\n repoState,\n );\n }\n }\n\n setRepositoryState(repoState);\n\n // Load active workspace if repository has one\n if (repoState?.workspaceId) {\n const workspace = await WorkspaceLayoutService.getWorkspaceLayout(\n repoState.workspaceId,\n );\n setActiveWorkspace(workspace);\n } else {\n setActiveWorkspace(null);\n }\n }\n } catch (err) {\n setError(err as Error);\n console.error('Failed to load workspace data:', err);\n } finally {\n setLoading(false);\n }\n }, [repositoryKey, autoInitialize, defaultWorkspaceId]);\n\n /**\n * Initial load\n */\n useEffect(() => {\n loadData();\n }, [loadData]);\n\n /**\n * Get a specific workspace\n */\n const getWorkspace = useCallback(\n async (id: string) => {\n return await WorkspaceLayoutService.getWorkspaceLayout(id);\n },\n [],\n );\n\n /**\n * Create a new workspace\n */\n const createWorkspace = useCallback(\n async (createOptions: CreateWorkspaceOptions) => {\n const workspace =\n await WorkspaceLayoutService.createWorkspaceLayout(createOptions);\n await loadData(); // Refresh\n return workspace;\n },\n [loadData],\n );\n\n /**\n * Update an existing workspace\n */\n const updateWorkspace = useCallback(\n async (id: string, updates: UpdateWorkspaceOptions) => {\n const workspace =\n await WorkspaceLayoutService.updateWorkspaceLayout(id, updates);\n await loadData(); // Refresh\n return workspace;\n },\n [loadData],\n );\n\n /**\n * Delete a workspace\n */\n const deleteWorkspace = useCallback(\n async (id: string) => {\n const success = await WorkspaceLayoutService.deleteWorkspaceLayout(id);\n if (success) {\n await loadData(); // Refresh\n }\n return success;\n },\n [loadData],\n );\n\n /**\n * Apply a workspace to the current repository\n */\n const applyWorkspace = useCallback(\n async (workspaceId: string) => {\n if (!repositoryKey) {\n console.error('Cannot apply workspace without repositoryKey');\n return;\n }\n\n const workspace =\n await WorkspaceLayoutService.getWorkspaceLayout(workspaceId);\n if (!workspace) {\n console.error(`Workspace ${workspaceId} not found`);\n return;\n }\n\n const newState: RepositoryWorkspaceState = {\n workspaceId,\n sizes: workspace.defaultSizes || { left: 20, middle: 45, right: 35 },\n collapsed: workspace.defaultCollapsed || {\n left: false,\n right: false,\n },\n };\n\n await WorkspaceLayoutService.setRepositoryState(repositoryKey, newState);\n await loadData(); // Refresh\n },\n [repositoryKey, loadData],\n );\n\n /**\n * Update repository sizes\n */\n const updateSizes = useCallback(\n async (sizes: { left: number; middle: number; right: number }) => {\n if (!repositoryKey) {\n console.error('Cannot update sizes without repositoryKey');\n return;\n }\n\n await WorkspaceLayoutService.updateRepositorySizes(repositoryKey, sizes);\n await loadData(); // Refresh\n },\n [repositoryKey, loadData],\n );\n\n /**\n * Update repository collapsed state\n */\n const updateCollapsed = useCallback(\n async (collapsed: { left?: boolean; right?: boolean }) => {\n if (!repositoryKey) {\n console.error('Cannot update collapsed without repositoryKey');\n return;\n }\n\n await WorkspaceLayoutService.updateRepositoryCollapsed(\n repositoryKey,\n collapsed,\n );\n await loadData(); // Refresh\n },\n [repositoryKey, loadData],\n );\n\n /**\n * Reset repository to workspace defaults\n */\n const resetToDefaults = useCallback(async () => {\n if (!repositoryKey || !repositoryState?.workspaceId) {\n console.error('Cannot reset without repositoryKey and active workspace');\n return;\n }\n\n await WorkspaceLayoutService.resetRepositoryToWorkspaceDefaults(\n repositoryKey,\n repositoryState.workspaceId,\n );\n await loadData(); // Refresh\n }, [repositoryKey, repositoryState?.workspaceId, loadData]);\n\n /**\n * Refresh workspace data\n */\n const refresh = useCallback(async () => {\n await loadData();\n }, [loadData]);\n\n return {\n workspaces,\n repositoryState,\n activeWorkspace,\n loading,\n error,\n getWorkspace,\n createWorkspace,\n updateWorkspace,\n deleteWorkspace,\n applyWorkspace,\n updateSizes,\n updateCollapsed,\n resetToDefaults,\n refresh,\n };\n}\n","/**\n * usePanelFocus - Hook for managing panel focus state\n */\n\nimport { useState, useCallback } from 'react';\nimport type {\n PanelEventEmitter,\n PanelFocusEventPayload,\n PanelBlurEventPayload,\n} from '@principal-ade/panel-framework-core';\nimport type { PanelSlotId, PanelFocusState, PanelFocusActions } from '../types';\nimport type { PanelCollapsed } from '../../types/persistence.types';\n\nexport interface UsePanelFocusOptions {\n /** Initial focused panel (optional) */\n initialFocus?: PanelSlotId | null;\n\n /** Collapsed state to determine which panels are visible */\n collapsed?: PanelCollapsed;\n\n /** Whether this is a two-panel or three-panel layout */\n panelType?: 'two-panel' | 'three-panel';\n\n /** Callback when focus changes */\n onFocusChange?: (panel: PanelSlotId | null) => void;\n\n /** Event emitter from panel framework (optional, for focus events) */\n events?: PanelEventEmitter;\n\n /** Function to map panel slot to panel ID (optional, required for event emission) */\n getPanelId?: (slot: PanelSlotId) => string | undefined;\n}\n\nexport interface UsePanelFocusReturn extends PanelFocusState, PanelFocusActions {\n /** Check if a specific panel is focused */\n isFocused: (panel: PanelSlotId) => boolean;\n}\n\n/**\n * Hook for managing panel focus state with keyboard shortcuts\n */\nexport function usePanelFocus(\n options: UsePanelFocusOptions = {}\n): UsePanelFocusReturn {\n const {\n initialFocus = null,\n collapsed = {},\n panelType = 'three-panel',\n onFocusChange,\n events,\n getPanelId,\n } = options;\n\n const [focusedPanel, setFocusedPanelState] = useState<PanelSlotId | null>(\n initialFocus\n );\n\n const setFocus = useCallback(\n (panel: PanelSlotId) => {\n const previousPanel = focusedPanel;\n setFocusedPanelState(panel);\n onFocusChange?.(panel);\n\n // Emit framework events if event emitter is provided\n if (events && getPanelId) {\n // Emit blur event for previous panel\n if (previousPanel) {\n const prevPanelId = getPanelId(previousPanel);\n if (prevPanelId) {\n events.emit<PanelBlurEventPayload>({\n type: 'panel:blur',\n source: 'panel-layouts',\n timestamp: Date.now(),\n payload: {\n panelId: prevPanelId,\n panelSlot: previousPanel,\n nextPanelId: getPanelId(panel),\n },\n });\n }\n }\n\n // Emit focus event for new panel\n const panelId = getPanelId(panel);\n if (panelId) {\n events.emit<PanelFocusEventPayload>({\n type: 'panel:focus',\n source: 'panel-layouts',\n timestamp: Date.now(),\n payload: {\n panelId,\n panelSlot: panel,\n source: 'keyboard-shortcut',\n },\n });\n }\n }\n },\n [focusedPanel, onFocusChange, events, getPanelId]\n );\n\n const clearFocus = useCallback(() => {\n const previousPanel = focusedPanel;\n setFocusedPanelState(null);\n onFocusChange?.(null);\n\n // Emit blur event when clearing focus\n if (events && getPanelId && previousPanel) {\n const prevPanelId = getPanelId(previousPanel);\n if (prevPanelId) {\n events.emit<PanelBlurEventPayload>({\n type: 'panel:blur',\n source: 'panel-layouts',\n timestamp: Date.now(),\n payload: {\n panelId: prevPanelId,\n panelSlot: previousPanel,\n },\n });\n }\n }\n }, [focusedPanel, onFocusChange, events, getPanelId]);\n\n const getVisiblePanels = useCallback((): PanelSlotId[] => {\n const panels: PanelSlotId[] = [];\n\n if (!collapsed.left) {\n panels.push('left');\n }\n panels.push('middle'); // Middle is always visible\n if (panelType === 'three-panel' && !collapsed.right) {\n panels.push('right');\n }\n\n return panels;\n }, [collapsed, panelType]);\n\n const focusNext = useCallback(() => {\n const visiblePanels = getVisiblePanels();\n if (visiblePanels.length === 0) return;\n\n if (focusedPanel === null) {\n // No panel focused, focus first visible panel\n setFocus(visiblePanels[0]);\n return;\n }\n\n const currentIndex = visiblePanels.indexOf(focusedPanel);\n if (currentIndex === -1) {\n // Current panel is not visible, focus first visible panel\n setFocus(visiblePanels[0]);\n return;\n }\n\n // Move to next panel (wrap around)\n const nextIndex = (currentIndex + 1) % visiblePanels.length;\n setFocus(visiblePanels[nextIndex]);\n }, [focusedPanel, getVisiblePanels, setFocus]);\n\n const focusPrevious = useCallback(() => {\n const visiblePanels = getVisiblePanels();\n if (visiblePanels.length === 0) return;\n\n if (focusedPanel === null) {\n // No panel focused, focus last visible panel\n setFocus(visiblePanels[visiblePanels.length - 1]);\n return;\n }\n\n const currentIndex = visiblePanels.indexOf(focusedPanel);\n if (currentIndex === -1) {\n // Current panel is not visible, focus last visible panel\n setFocus(visiblePanels[visiblePanels.length - 1]);\n return;\n }\n\n // Move to previous panel (wrap around)\n const prevIndex =\n currentIndex === 0 ? visiblePanels.length - 1 : currentIndex - 1;\n setFocus(visiblePanels[prevIndex]);\n }, [focusedPanel, getVisiblePanels, setFocus]);\n\n const isFocused = useCallback(\n (panel: PanelSlotId) => focusedPanel === panel,\n [focusedPanel]\n );\n\n return {\n focusedPanel,\n setFocus,\n clearFocus,\n focusNext,\n focusPrevious,\n isFocused,\n };\n}\n","/**\n * usePanelKeyboardShortcuts - Hook for keyboard shortcuts to control panel focus and collapse\n */\n\nimport { useEffect, useCallback, useRef } from 'react';\nimport type { PanelSlotId } from '../types';\nimport type { PanelCollapsed } from '../../types/persistence.types';\n\nexport interface UsePanelKeyboardShortcutsOptions {\n /** Whether keyboard shortcuts are enabled */\n enabled?: boolean;\n\n /** Current focused panel */\n focusedPanel: PanelSlotId | null;\n\n /** Current collapsed state */\n collapsed: PanelCollapsed;\n\n /** Panel type (two-panel or three-panel) */\n panelType: 'two-panel' | 'three-panel';\n\n /** Set focus to a specific panel */\n setFocus: (panel: PanelSlotId) => void;\n\n /** Callback to expand a panel */\n onExpand: (panel: 'left' | 'right') => void | Promise<void>;\n\n /** Callback to collapse a panel */\n onCollapse: (panel: 'left' | 'right') => void | Promise<void>;\n}\n\n/**\n * Hook for handling Alt+1/2/3 keyboard shortcuts for panel toggle and focus\n *\n * Behavior:\n * - Alt+1 (Left Panel):\n * 1. If collapsed: expand (no focus change)\n * 2. If expanded but not focused: focus it\n * 3. If focused: collapse and focus middle\n *\n * - Alt+2 (Middle Panel):\n * - Always focus middle (never collapses)\n *\n * - Alt+3 (Right Panel):\n * 1. If collapsed: expand (no focus change)\n * 2. If expanded but not focused: focus it\n * 3. If focused: collapse and focus middle\n */\nexport function usePanelKeyboardShortcuts(\n options: UsePanelKeyboardShortcutsOptions\n): void {\n const {\n enabled = true,\n focusedPanel,\n collapsed,\n panelType,\n setFocus,\n onExpand,\n onCollapse,\n } = options;\n\n // Use refs to avoid recreating event listener on every render\n const focusedPanelRef = useRef(focusedPanel);\n const collapsedRef = useRef(collapsed);\n const panelTypeRef = useRef(panelType);\n\n useEffect(() => {\n focusedPanelRef.current = focusedPanel;\n }, [focusedPanel]);\n\n useEffect(() => {\n collapsedRef.current = collapsed;\n }, [collapsed]);\n\n useEffect(() => {\n panelTypeRef.current = panelType;\n }, [panelType]);\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent) => {\n // Only handle Alt+Number shortcuts\n if (!event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {\n return;\n }\n\n // Use event.code instead of event.key to handle international keyboards\n // event.code gives us 'Digit1', 'Digit2', etc. regardless of keyboard layout\n const code = event.code;\n const currentFocused = focusedPanelRef.current;\n const currentCollapsed = collapsedRef.current;\n const currentPanelType = panelTypeRef.current;\n\n // Alt+1: Toggle left panel\n if (code === 'Digit1' || code === 'Numpad1') {\n event.preventDefault();\n\n if (currentCollapsed.left) {\n // State 1: Collapsed -> Expand (no focus change)\n onExpand('left');\n } else if (currentFocused !== 'left') {\n // State 2: Expanded but not focused -> Focus\n setFocus('left');\n } else {\n // State 3: Focused -> Collapse and focus middle\n onCollapse('left');\n setFocus('middle');\n }\n }\n // Alt+2: Focus middle panel\n else if (code === 'Digit2' || code === 'Numpad2') {\n event.preventDefault();\n setFocus('middle');\n }\n // Alt+3: Toggle right panel (only for three-panel layouts)\n else if ((code === 'Digit3' || code === 'Numpad3') && currentPanelType === 'three-panel') {\n event.preventDefault();\n\n if (currentCollapsed.right) {\n // State 1: Collapsed -> Expand (no focus change)\n onExpand('right');\n } else if (currentFocused !== 'right') {\n // State 2: Expanded but not focused -> Focus\n setFocus('right');\n } else {\n // State 3: Focused -> Collapse and focus middle\n onCollapse('right');\n setFocus('middle');\n }\n }\n },\n [setFocus, onExpand, onCollapse]\n );\n\n useEffect(() => {\n if (!enabled) {\n return;\n }\n\n window.addEventListener('keydown', handleKeyDown);\n\n return () => {\n window.removeEventListener('keydown', handleKeyDown);\n };\n }, [enabled, handleKeyDown]);\n}\n","/**\n * usePanelFocusListener - Helper hook for panels to listen to focus events\n */\n\nimport { useEffect } from 'react';\nimport type {\n PanelEventEmitter,\n PanelFocusEventPayload,\n PanelBlurEventPayload,\n} from '@principal-ade/panel-framework-core';\n\n/**\n * Hook for panels to listen to focus events from the framework\n *\n * This is a convenience hook that panels can use to respond to focus changes\n * from keyboard shortcuts, mouse clicks, or programmatic navigation.\n *\n * @param panelId - The ID of this panel (from panel metadata)\n * @param events - Event emitter from PanelComponentProps\n * @param onFocus - Callback when this panel receives focus\n * @param onBlur - Optional callback when this panel loses focus\n *\n * @example\n * ```typescript\n * function TerminalPanel({ context, actions, events }: PanelComponentProps) {\n * const xtermRef = useRef<Terminal>();\n *\n * usePanelFocusListener(\n * 'terminal',\n * events,\n * () => xtermRef.current?.focus(),\n * () => xtermRef.current?.blur()\n * );\n *\n * return <div id=\"xterm-container\" />;\n * }\n * ```\n */\nexport function usePanelFocusListener(\n panelId: string,\n events: PanelEventEmitter,\n onFocus: () => void,\n onBlur?: () => void\n): void {\n useEffect(() => {\n // Listen for focus events\n const unsubscribeFocus = events.on<PanelFocusEventPayload>(\n 'panel:focus',\n (event) => {\n if (event.payload.panelId === panelId) {\n onFocus();\n }\n }\n );\n\n // Listen for blur events (optional)\n let unsubscribeBlur: (() => void) | undefined;\n if (onBlur) {\n unsubscribeBlur = events.on<PanelBlurEventPayload>(\n 'panel:blur',\n (event) => {\n if (event.payload.panelId === panelId) {\n onBlur();\n }\n }\n );\n }\n\n return () => {\n unsubscribeFocus();\n unsubscribeBlur?.();\n };\n }, [panelId, events, onFocus, onBlur]);\n}\n","/**\n * FocusIndicator - Visual indicator for focused panel\n */\n\nimport React from 'react';\n\nexport interface FocusIndicatorProps {\n /** Whether this panel is currently focused */\n isFocused: boolean;\n\n /** Custom class name */\n className?: string;\n\n /** Custom styles */\n style?: React.CSSProperties;\n}\n\n/**\n * Visual indicator that highlights the focused panel\n *\n * Renders a subtle border/glow around the focused panel for keyboard navigation feedback\n */\nexport const FocusIndicator: React.FC<FocusIndicatorProps> = ({\n isFocused,\n className = '',\n style = {},\n}) => {\n if (!isFocused) {\n return null;\n }\n\n const defaultStyles: React.CSSProperties = {\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n pointerEvents: 'none',\n border: '2px solid var(--panel-focus-border-color, #0066cc)',\n borderRadius: '4px',\n boxShadow: '0 0 0 1px var(--panel-focus-shadow-color, rgba(0, 102, 204, 0.2))',\n zIndex: 1000,\n transition: 'opacity 0.15s ease-in-out',\n ...style,\n };\n\n return (\n <div\n className={`panel-focus-indicator ${className}`}\n style={defaultStyles}\n role=\"presentation\"\n aria-hidden=\"true\"\n />\n );\n};\n","import React, { useEffect, useRef } from 'react';\nimport { useTheme } from '@principal-ade/industry-theme';\n\ninterface CommandInputProps {\n value: string;\n onChange: (value: string) => void;\n placeholder?: string;\n onClose: () => void;\n onEnter?: () => void;\n}\n\n/**\n * CommandInput - Input field for the command palette\n * Auto-focuses on mount and handles input changes\n */\nexport const CommandInput: React.FC<CommandInputProps> = ({\n value,\n onChange,\n placeholder = '> Type a command...',\n onClose,\n onEnter,\n}) => {\n const { theme } = useTheme();\n const inputRef = useRef<HTMLInputElement>(null);\n\n // Auto-focus on mount\n useEffect(() => {\n if (inputRef.current) {\n inputRef.current.focus();\n }\n }, []);\n\n // Handle keyboard events\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n switch (e.key) {\n case 'Enter':\n e.preventDefault();\n onEnter?.();\n break;\n case 'Escape':\n e.preventDefault();\n onClose();\n break;\n }\n };\n\n return (\n <div\n style={{\n padding: '0',\n borderBottom: `1px solid ${theme.colors.border}`,\n backgroundColor: theme.colors.background,\n }}\n >\n <input\n ref={inputRef}\n type=\"text\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n style={{\n width: '100%',\n padding: '16px 20px',\n fontSize: '16px',\n fontFamily: theme.fonts.monospace,\n backgroundColor: 'transparent',\n border: 'none',\n outline: 'none',\n color: theme.colors.text,\n caretColor: theme.colors.primary,\n }}\n autoComplete=\"off\"\n autoCorrect=\"off\"\n autoCapitalize=\"off\"\n spellCheck={false}\n />\n </div>\n );\n};\n","import React, { forwardRef } from 'react';\nimport { useTheme } from '@principal-ade/industry-theme';\nimport type { Command } from '../types/command.types';\n\ninterface CommandItemProps {\n command: Command;\n isSelected: boolean;\n onClick: () => void;\n onMouseEnter: () => void;\n}\n\n/**\n * CommandItem - Individual command item in the list\n * Displays command label, description, icon, and keyboard shortcut\n */\nexport const CommandItem = forwardRef<HTMLDivElement, CommandItemProps>(\n ({ command, isSelected, onClick, onMouseEnter }, ref) => {\n const { theme } = useTheme();\n const { label, description, icon, shortcut } = command;\n const [isHovered, setIsHovered] = React.useState(false);\n\n return (\n <div\n ref={ref}\n onClick={onClick}\n onMouseEnter={() => {\n setIsHovered(true);\n onMouseEnter();\n }}\n onMouseLeave={() => setIsHovered(false)}\n style={{\n padding: '10px 16px',\n cursor: 'pointer',\n backgroundColor: isSelected || isHovered\n ? theme.colors.backgroundSecondary\n : 'transparent',\n borderLeft: isSelected || isHovered\n ? `3px solid ${theme.colors.primary}`\n : '3px solid transparent',\n transition: 'all 0.1s ease',\n display: 'flex',\n alignItems: 'center',\n gap: '12px',\n }}\n onMouseDown={(e) => {\n // Prevent input blur\n e.preventDefault();\n }}\n >\n {/* Icon */}\n {icon && (\n <div\n style={{\n flexShrink: 0,\n width: '20px',\n height: '20px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '16px',\n color: isSelected || isHovered ? theme.colors.primary : theme.colors.textSecondary,\n }}\n >\n {typeof icon === 'string' ? icon : icon}\n </div>\n )}\n\n {/* Label and Description */}\n <div style={{ flex: 1, minWidth: 0 }}>\n <div\n style={{\n fontSize: '14px',\n fontWeight: 500,\n color: isSelected || isHovered ? theme.colors.text : theme.colors.textSecondary,\n marginBottom: description ? '2px' : 0,\n }}\n >\n {label}\n </div>\n {description && (\n <div\n style={{\n fontSize: '12px',\n color: theme.colors.textMuted,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {description}\n </div>\n )}\n </div>\n\n {/* Keyboard Shortcut */}\n {shortcut && (\n <div\n style={{\n flexShrink: 0,\n fontSize: '11px',\n color: theme.colors.textMuted,\n padding: '2px 8px',\n backgroundColor: theme.colors.background,\n border: `1px solid ${theme.colors.border}`,\n borderRadius: '4px',\n fontFamily: theme.fonts.monospace,\n }}\n >\n {shortcut}\n </div>\n )}\n </div>\n );\n }\n);\n\nCommandItem.displayName = 'CommandItem';\n","import React, { useEffect, useRef } from 'react';\nimport { useTheme } from '@principal-ade/industry-theme';\nimport type { Command } from '../types/command.types';\nimport { CommandItem } from './CommandItem';\n\ninterface CommandListProps {\n commands: Command[];\n selectedIndex: number;\n onSelect: (command: Command) => void;\n onHover: (index: number) => void;\n maxResults?: number;\n}\n\n/**\n * CommandList - List of filtered commands\n * Displays commands grouped by category with keyboard navigation support\n */\nexport const CommandList: React.FC<CommandListProps> = ({\n commands,\n selectedIndex,\n onSelect,\n onHover,\n maxResults = 10,\n}) => {\n const { theme } = useTheme();\n const listRef = useRef<HTMLDivElement>(null);\n const selectedItemRef = useRef<HTMLDivElement>(null);\n\n // Limit results\n const displayedCommands = commands.slice(0, maxResults);\n\n // Scroll selected item into view (only within the list container)\n useEffect(() => {\n if (selectedItemRef.current && listRef.current) {\n const item = selectedItemRef.current;\n const container = listRef.current;\n\n const itemTop = item.offsetTop;\n const itemBottom = itemTop + item.offsetHeight;\n const containerScrollTop = container.scrollTop;\n const containerHeight = container.clientHeight;\n\n // Scroll only if item is out of view\n if (itemTop < containerScrollTop) {\n // Item is above visible area\n container.scrollTop = itemTop - 8; // 8px padding\n } else if (itemBottom > containerScrollTop + containerHeight) {\n // Item is below visible area\n container.scrollTop = itemBottom - containerHeight + 8;\n }\n }\n }, [selectedIndex]);\n\n // Group commands by category\n const groupedCommands = displayedCommands.reduce((acc, command, index) => {\n const category = command.category || 'Other';\n if (!acc[category]) {\n acc[category] = [];\n }\n acc[category].push({ command, index });\n return acc;\n }, {} as Record<string, Array<{ command: Command; index: number }>>);\n\n // Sort categories\n const categories = Object.keys(groupedCommands).sort((a, b) => {\n // \"Other\" always last\n if (a === 'Other') return 1;\n if (b === 'Other') return -1;\n return a.localeCompare(b);\n });\n\n return (\n <div\n ref={listRef}\n style={{\n overflowY: 'auto',\n maxHeight: '400px',\n padding: '8px 0',\n }}\n >\n {categories.map((category) => (\n <div key={category}>\n {/* Category Header */}\n {categories.length > 1 && (\n <div\n style={{\n padding: '8px 16px 4px',\n fontSize: '11px',\n fontWeight: 600,\n textTransform: 'uppercase',\n color: theme.colors.textMuted,\n letterSpacing: '0.5px',\n }}\n >\n {category}\n </div>\n )}\n\n {/* Category Commands */}\n {groupedCommands[category].map(({ command, index }) => (\n <CommandItem\n key={command.id}\n command={command}\n isSelected={index === selectedIndex}\n onClick={() => onSelect(command)}\n onMouseEnter={() => onHover(index)}\n ref={index === selectedIndex ? selectedItemRef : undefined}\n />\n ))}\n </div>\n ))}\n\n {/* Show count if more results available */}\n {commands.length > maxResults && (\n <div\n style={{\n padding: '8px 16px',\n fontSize: '12px',\n color: theme.colors.textMuted,\n textAlign: 'center',\n borderTop: `1px solid ${theme.colors.border}`,\n }}\n >\n Showing {maxResults} of {commands.length} results\n </div>\n )}\n </div>\n );\n};\n","import React, { useEffect, useRef } from 'react';\nimport { useTheme } from '@principal-ade/industry-theme';\nimport type { CommandPaletteProps } from '../types/command.types';\nimport { CommandInput } from './CommandInput';\nimport { CommandList } from './CommandList';\n\n/**\n * CommandPalette - Vim-style command palette component\n * Displays at the bottom of the screen with an input field and command list\n */\nexport const CommandPalette: React.FC<CommandPaletteProps> = ({\n commandPalette,\n config,\n}) => {\n const { theme } = useTheme();\n const containerRef = useRef<HTMLDivElement>(null);\n const {\n isOpen,\n close,\n query,\n setQuery,\n filteredCommands,\n selectedIndex,\n setSelectedIndex,\n executeSelected,\n } = commandPalette;\n\n // Handle click outside to close\n useEffect(() => {\n if (!isOpen) return;\n\n const handleClickOutside = (e: MouseEvent) => {\n if (containerRef.current && !containerRef.current.contains(e.target as Node)) {\n close();\n }\n };\n\n // Add a small delay to prevent immediate close on open\n const timeoutId = setTimeout(() => {\n document.addEventListener('mousedown', handleClickOutside);\n }, 100);\n\n return () => {\n clearTimeout(timeoutId);\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, [isOpen, close]);\n\n\n if (!isOpen) {\n return null;\n }\n\n const maxHeight = config?.maxHeight || '50vh';\n const placeholder = config?.placeholder || '> Type a command...';\n\n return (\n <>\n {/* Backdrop */}\n <div\n style={{\n position: 'fixed',\n inset: 0,\n backgroundColor: 'rgba(0, 0, 0, 0.4)',\n backdropFilter: 'blur(2px)',\n zIndex: 999,\n }}\n onClick={close}\n />\n\n {/* Command Palette Container */}\n <div\n ref={containerRef}\n className={config?.className}\n style={{\n position: 'fixed',\n bottom: 0,\n left: 0,\n right: 0,\n maxHeight,\n backgroundColor: theme.colors.surface,\n borderTop: `1px solid ${theme.colors.border}`,\n boxShadow: theme.shadows[2],\n zIndex: 1000,\n display: 'flex',\n flexDirection: 'column-reverse',\n ...config?.style,\n }}\n >\n {/* Input Field (at bottom due to column-reverse) */}\n <div>\n <CommandInput\n value={query}\n onChange={setQuery}\n placeholder={placeholder}\n onClose={close}\n onEnter={executeSelected}\n />\n\n {/* Footer with keyboard hints */}\n <div\n style={{\n padding: '8px 16px',\n borderTop: `1px solid ${theme.colors.border}`,\n display: 'flex',\n gap: '16px',\n fontSize: '12px',\n color: theme.colors.textMuted,\n backgroundColor: theme.colors.background,\n }}\n >\n <span>\n <kbd style={{ padding: '2px 6px', backgroundColor: theme.colors.backgroundSecondary, borderRadius: '3px', border: `1px solid ${theme.colors.border}` }}>Enter</kbd> Execute\n </span>\n <span>\n <kbd style={{ padding: '2px 6px', backgroundColor: theme.colors.backgroundSecondary, borderRadius: '3px', border: `1px solid ${theme.colors.border}` }}>Esc</kbd> Close\n </span>\n </div>\n </div>\n\n {/* Results List (appears above due to column-reverse) */}\n {filteredCommands.length > 0 && (\n <CommandList\n commands={filteredCommands}\n selectedIndex={selectedIndex}\n onSelect={(command) => {\n commandPalette.executeCommand(command.id);\n }}\n onHover={setSelectedIndex}\n maxResults={config?.maxResults}\n />\n )}\n\n {/* No Results Message (appears above due to column-reverse) */}\n {query && filteredCommands.length === 0 && (\n <div\n style={{\n padding: '24px 16px',\n color: theme.colors.textMuted,\n textAlign: 'center',\n fontSize: '14px',\n }}\n >\n No commands found for \"{query}\"\n </div>\n )}\n </div>\n </>\n );\n};\n","import type { Command, CommandContext } from '../types/command.types';\n\n/**\n * Service for managing command registration and execution\n * Provides a centralized registry for commands that can be accessed via the command palette\n */\nexport class CommandRegistryService {\n private commands: Map<string, Command> = new Map();\n private listeners: Set<() => void> = new Set();\n\n /**\n * Register one or more commands\n * @param commands - Array of commands to register\n */\n registerCommands(commands: Command[]): void {\n commands.forEach((command) => {\n this.commands.set(command.id, command);\n });\n this.notifyListeners();\n }\n\n /**\n * Register a single command\n * @param command - Command to register\n */\n registerCommand(command: Command): void {\n this.commands.set(command.id, command);\n this.notifyListeners();\n }\n\n /**\n * Unregister commands by ID\n * @param commandIds - Array of command IDs to unregister\n */\n unregisterCommands(commandIds: string[]): void {\n commandIds.forEach((id) => {\n this.commands.delete(id);\n });\n this.notifyListeners();\n }\n\n /**\n * Unregister a single command\n * @param commandId - Command ID to unregister\n */\n unregisterCommand(commandId: string): void {\n this.commands.delete(commandId);\n this.notifyListeners();\n }\n\n /**\n * Get all registered commands\n * @param context - Command context for availability checks\n * @returns Array of available commands\n */\n getCommands(context?: CommandContext): Command[] {\n const allCommands = Array.from(this.commands.values());\n\n if (!context) {\n return allCommands;\n }\n\n // Filter by availability\n return allCommands.filter((command) => {\n if (!command.isAvailable) {\n return true; // No availability check means always available\n }\n return command.isAvailable(context);\n });\n }\n\n /**\n * Get a command by ID\n * @param commandId - Command ID\n * @returns Command if found, undefined otherwise\n */\n getCommand(commandId: string): Command | undefined {\n return this.commands.get(commandId);\n }\n\n /**\n * Execute a command by ID\n * @param commandId - Command ID to execute\n * @param context - Command context\n */\n async executeCommand(commandId: string, context: CommandContext): Promise<void> {\n const command = this.commands.get(commandId);\n if (!command) {\n console.warn(`Command not found: ${commandId}`);\n return;\n }\n\n // Check availability\n if (command.isAvailable && !command.isAvailable(context)) {\n console.warn(`Command not available: ${commandId}`);\n return;\n }\n\n try {\n await command.execute(context);\n\n // Emit event for analytics/logging\n context.events?.emit({\n type: 'command:executed',\n source: 'command-palette',\n timestamp: Date.now(),\n payload: {\n commandId: command.id,\n commandLabel: command.label,\n },\n });\n } catch (error) {\n console.error(`Error executing command ${commandId}:`, error);\n\n // Emit error event\n context.events?.emit({\n type: 'command:error',\n source: 'command-palette',\n timestamp: Date.now(),\n payload: {\n commandId: command.id,\n error: error instanceof Error ? error.message : String(error),\n },\n });\n }\n }\n\n /**\n * Search commands by query\n * @param query - Search query\n * @param context - Command context for availability checks\n * @returns Filtered and sorted commands\n */\n searchCommands(query: string, context?: CommandContext): Command[] {\n const availableCommands = this.getCommands(context);\n\n if (!query.trim()) {\n return this.sortCommands(availableCommands);\n }\n\n const lowerQuery = query.toLowerCase();\n\n // Score each command based on matching\n const scored = availableCommands.map((command) => {\n let score = 0;\n\n // Exact label match (highest priority)\n if (command.label.toLowerCase() === lowerQuery) {\n score += 1000;\n }\n // Label starts with query\n else if (command.label.toLowerCase().startsWith(lowerQuery)) {\n score += 500;\n }\n // Label contains query\n else if (command.label.toLowerCase().includes(lowerQuery)) {\n score += 250;\n }\n\n // Description contains query\n if (command.description?.toLowerCase().includes(lowerQuery)) {\n score += 100;\n }\n\n // Keywords match\n if (command.keywords) {\n const keywordMatch = command.keywords.some((keyword) =>\n keyword.toLowerCase().includes(lowerQuery)\n );\n if (keywordMatch) {\n score += 150;\n }\n }\n\n // Category match\n if (command.category?.toLowerCase().includes(lowerQuery)) {\n score += 50;\n }\n\n // Only add priority as a tiebreaker if there's already a match\n if (score > 0 && command.priority) {\n score += command.priority;\n }\n\n return { command, score };\n });\n\n // Filter out commands with no match and sort by score\n return scored\n .filter((item) => item.score > 0)\n .sort((a, b) => b.score - a.score)\n .map((item) => item.command);\n }\n\n /**\n * Sort commands by priority and label\n * @param commands - Commands to sort\n * @returns Sorted commands\n */\n private sortCommands(commands: Command[]): Command[] {\n return commands.sort((a, b) => {\n // Sort by priority first (higher priority first)\n const priorityDiff = (b.priority || 0) - (a.priority || 0);\n if (priorityDiff !== 0) {\n return priorityDiff;\n }\n\n // Then by category\n const categoryA = a.category || '';\n const categoryB = b.category || '';\n const categoryDiff = categoryA.localeCompare(categoryB);\n if (categoryDiff !== 0) {\n return categoryDiff;\n }\n\n // Finally by label\n return a.label.localeCompare(b.label);\n });\n }\n\n /**\n * Subscribe to registry changes\n * @param listener - Callback function called when registry changes\n * @returns Unsubscribe function\n */\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n /**\n * Clear all commands\n */\n clear(): void {\n this.commands.clear();\n this.notifyListeners();\n }\n\n /**\n * Get count of registered commands\n */\n get size(): number {\n return this.commands.size;\n }\n\n /**\n * Notify all listeners of registry changes\n */\n private notifyListeners(): void {\n this.listeners.forEach((listener) => listener());\n }\n}\n\n// Singleton instance for global command registry\nlet globalRegistry: CommandRegistryService | null = null;\n\n/**\n * Get the global command registry instance\n * @returns Global CommandRegistryService instance\n */\nexport function getGlobalCommandRegistry(): CommandRegistryService {\n if (!globalRegistry) {\n globalRegistry = new CommandRegistryService();\n }\n return globalRegistry;\n}\n\n/**\n * Reset the global command registry (useful for testing)\n */\nexport function resetGlobalCommandRegistry(): void {\n globalRegistry = null;\n}\n","import { useState, useCallback, useEffect, useMemo } from 'react';\nimport type {\n Command,\n CommandContext,\n UseCommandPaletteReturn,\n CommandPaletteKeyboardConfig,\n CommandPaletteConfig,\n} from '../types/command.types';\nimport { CommandRegistryService } from '../services/CommandRegistryService';\n\ninterface UseCommandPaletteProps {\n /** Command context */\n context: CommandContext;\n /** Initial commands to register */\n commands?: Command[];\n /** Keyboard configuration */\n keyboard?: CommandPaletteKeyboardConfig;\n /** Command palette configuration */\n config?: CommandPaletteConfig;\n /** Command registry service (optional, uses global if not provided) */\n registry?: CommandRegistryService;\n}\n\n/**\n * Hook for managing command palette state and behavior\n * Handles command registration, filtering, keyboard navigation, and execution\n */\nexport function useCommandPalette({\n context,\n commands: initialCommands = [],\n keyboard = { key: ' ', altKey: true },\n config = {},\n registry: providedRegistry,\n}: UseCommandPaletteProps): UseCommandPaletteReturn {\n const [isOpen, setIsOpen] = useState(false);\n const [query, setQuery] = useState('');\n const [selectedIndex, setSelectedIndex] = useState(0);\n const [registeredCommands, setRegisteredCommands] = useState<Command[]>([]);\n\n // Use provided registry or create a new one\n const registry = useMemo(\n () => providedRegistry || new CommandRegistryService(),\n [providedRegistry]\n );\n\n // Create command context with close function (before effects)\n const commandContext = useMemo<CommandContext>(\n () => ({\n ...context,\n closeCommandPalette: () => setIsOpen(false),\n }),\n [context]\n );\n\n // Register initial commands and subscribe to changes\n useEffect(() => {\n let isSubscribed = true;\n\n // Subscribe to changes first\n const unsubscribe = registry.subscribe(() => {\n if (isSubscribed) {\n const updatedCommands = registry.getCommands(commandContext);\n setRegisteredCommands(updatedCommands);\n }\n });\n\n // Register commands after subscribing (this will trigger the subscription)\n if (initialCommands.length > 0) {\n registry.registerCommands(initialCommands);\n } else {\n // If no initial commands, still need to get current commands\n const commands = registry.getCommands(commandContext);\n setRegisteredCommands(commands);\n }\n\n return () => {\n isSubscribed = false;\n unsubscribe();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [registry]);\n\n // Filter commands based on query\n const filteredCommands = useMemo(() => {\n if (config.fuzzySearch === false) {\n // Simple substring matching\n return registry.searchCommands(query, commandContext);\n }\n\n // Use registry's built-in search\n return registry.searchCommands(query, commandContext);\n }, [query, registry, commandContext, config.fuzzySearch]);\n\n // Reset selected index when filtered commands change\n useEffect(() => {\n setSelectedIndex(0);\n }, [filteredCommands]);\n\n // Open command palette\n const open = useCallback(() => {\n setIsOpen(true);\n setQuery('');\n setSelectedIndex(0);\n\n // Emit event\n context.events?.emit({\n type: 'command-palette:opened',\n source: 'command-palette',\n timestamp: Date.now(),\n payload: {},\n });\n }, [context.events]);\n\n // Close command palette\n const close = useCallback(() => {\n setIsOpen(false);\n setQuery('');\n setSelectedIndex(0);\n\n // Emit event\n context.events?.emit({\n type: 'command-palette:closed',\n source: 'command-palette',\n timestamp: Date.now(),\n payload: {},\n });\n }, [context.events]);\n\n // Toggle command palette\n const toggle = useCallback(() => {\n if (isOpen) {\n close();\n } else {\n open();\n }\n }, [isOpen, open, close]);\n\n // Execute a command by ID\n const executeCommand = useCallback(\n async (commandId: string) => {\n await registry.executeCommand(commandId, commandContext);\n close();\n },\n [registry, commandContext, close]\n );\n\n // Navigate to next command\n const selectNext = useCallback(() => {\n setSelectedIndex((prev) => {\n const maxResults = config.maxResults || filteredCommands.length;\n const maxIndex = Math.min(filteredCommands.length, maxResults) - 1;\n return prev < maxIndex ? prev + 1 : 0;\n });\n }, [filteredCommands.length, config.maxResults]);\n\n // Navigate to previous command\n const selectPrevious = useCallback(() => {\n setSelectedIndex((prev) => {\n const maxResults = config.maxResults || filteredCommands.length;\n const maxIndex = Math.min(filteredCommands.length, maxResults) - 1;\n return prev > 0 ? prev - 1 : maxIndex;\n });\n }, [filteredCommands.length, config.maxResults]);\n\n // Execute the currently selected command (always first result)\n const executeSelected = useCallback(async () => {\n // Always execute the first filtered command\n const firstCommand = filteredCommands[0];\n\n if (firstCommand) {\n await executeCommand(firstCommand.id);\n }\n }, [filteredCommands, executeCommand]);\n\n // Register new commands\n const registerCommands = useCallback(\n (commands: Command[]) => {\n registry.registerCommands(commands);\n },\n [registry]\n );\n\n // Unregister commands\n const unregisterCommands = useCallback(\n (commandIds: string[]) => {\n registry.unregisterCommands(commandIds);\n },\n [registry]\n );\n\n // Handle keyboard shortcut to open command palette\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n const {\n key = ' ',\n altKey = true,\n ctrlKey = false,\n metaKey = false,\n shiftKey = false,\n } = keyboard;\n\n // Check if the keyboard shortcut matches\n const modifiersMatch =\n e.altKey === altKey &&\n e.ctrlKey === ctrlKey &&\n e.metaKey === metaKey &&\n e.shiftKey === shiftKey;\n\n // Use event.code for Space key to match usePanelKeyboardShortcuts pattern\n const keyMatches = key === ' ' ? e.code === 'Space' : e.key === key;\n\n if (keyMatches && modifiersMatch) {\n // Don't trigger if user is typing in an input field\n const target = e.target as HTMLElement;\n if (\n target.tagName === 'INPUT' ||\n target.tagName === 'TEXTAREA' ||\n target.isContentEditable\n ) {\n return;\n }\n\n e.preventDefault();\n toggle();\n }\n },\n [keyboard, toggle]\n );\n\n useEffect(() => {\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [handleKeyDown]);\n\n return {\n isOpen,\n open,\n close,\n toggle,\n query,\n setQuery,\n filteredCommands,\n executeCommand,\n selectedIndex,\n setSelectedIndex,\n selectNext,\n selectPrevious,\n executeSelected,\n commands: registeredCommands,\n registerCommands,\n unregisterCommands,\n };\n}\n","import type { Command } from '../types/command.types';\n\n/**\n * Built-in commands for panel navigation and control\n */\nexport const panelCommands: Command[] = [\n {\n id: 'panel.focus.left',\n label: 'Focus Left Panel',\n description: 'Set focus to the left panel',\n icon: '◀',\n category: 'Panel Navigation',\n shortcut: 'Alt+1',\n priority: 100,\n keywords: ['left', 'sidebar', 'focus', 'switch'],\n execute: (context) => {\n context.setFocus('left');\n },\n isAvailable: (context) => context.focusedPanel !== 'left',\n },\n {\n id: 'panel.focus.middle',\n label: 'Focus Middle Panel',\n description: 'Set focus to the middle panel',\n icon: '▣',\n category: 'Panel Navigation',\n shortcut: 'Alt+2',\n priority: 100,\n keywords: ['middle', 'center', 'main', 'focus', 'switch'],\n execute: (context) => {\n context.setFocus('middle');\n },\n isAvailable: (context) => context.focusedPanel !== 'middle',\n },\n {\n id: 'panel.focus.right',\n label: 'Focus Right Panel',\n description: 'Set focus to the right panel',\n icon: '▶',\n category: 'Panel Navigation',\n shortcut: 'Alt+3',\n priority: 100,\n keywords: ['right', 'sidebar', 'focus', 'switch'],\n execute: (context) => {\n context.setFocus('right');\n },\n isAvailable: (context) => context.focusedPanel !== 'right',\n },\n {\n id: 'panel.toggle.left',\n label: 'Toggle Left Panel',\n description: 'Expand or collapse the left panel',\n icon: '◀◀',\n category: 'Panel Control',\n keywords: ['toggle', 'left', 'collapse', 'expand', 'hide', 'show'],\n priority: 80,\n execute: (context) => {\n context.events?.emit({\n type: 'panel:toggle',\n source: 'command-palette',\n timestamp: Date.now(),\n payload: { panelId: 'left' },\n });\n },\n },\n {\n id: 'panel.toggle.right',\n label: 'Toggle Right Panel',\n description: 'Expand or collapse the right panel',\n icon: '▶▶',\n category: 'Panel Control',\n keywords: ['toggle', 'right', 'collapse', 'expand', 'hide', 'show'],\n priority: 80,\n execute: (context) => {\n context.events?.emit({\n type: 'panel:toggle',\n source: 'command-palette',\n timestamp: Date.now(),\n payload: { panelId: 'right' },\n });\n },\n },\n {\n id: 'panel.collapse.all',\n label: 'Collapse All Panels',\n description: 'Collapse all side panels to maximize middle panel',\n icon: '⬌',\n category: 'Panel Control',\n keywords: ['collapse', 'hide', 'all', 'maximize', 'focus mode'],\n priority: 70,\n execute: (context) => {\n context.events?.emit({\n type: 'panel:collapse-all',\n source: 'command-palette',\n timestamp: Date.now(),\n payload: {},\n });\n },\n },\n {\n id: 'panel.expand.all',\n label: 'Expand All Panels',\n description: 'Expand all side panels to default layout',\n icon: '⬍',\n category: 'Panel Control',\n keywords: ['expand', 'show', 'all', 'restore', 'default'],\n priority: 70,\n execute: (context) => {\n context.events?.emit({\n type: 'panel:expand-all',\n source: 'command-palette',\n timestamp: Date.now(),\n payload: {},\n });\n },\n },\n {\n id: 'panel.refresh',\n label: 'Refresh Panel Data',\n description: 'Reload data for the currently focused panel',\n icon: '↻',\n category: 'Panel Control',\n keywords: ['refresh', 'reload', 'update', 'sync'],\n priority: 60,\n execute: (context) => {\n const panelId = context.focusedPanel;\n if (!panelId) return;\n\n context.events?.emit({\n type: 'panel:refresh',\n source: 'command-palette',\n timestamp: Date.now(),\n payload: { panelId },\n });\n },\n isAvailable: (context) => context.focusedPanel !== null,\n },\n {\n id: 'panel.reset.layout',\n label: 'Reset Panel Layout',\n description: 'Reset panel sizes to default layout',\n icon: '⟲',\n category: 'Panel Control',\n keywords: ['reset', 'layout', 'default', 'restore'],\n priority: 50,\n execute: (context) => {\n context.events?.emit({\n type: 'panel:reset-layout',\n source: 'command-palette',\n timestamp: Date.now(),\n payload: {},\n });\n },\n },\n];\n\n/**\n * Get panel commands\n * @returns Array of panel-related commands\n */\nexport function getPanelCommands(): Command[] {\n return panelCommands;\n}\n"],"names":["LocalStoragePersistenceAdapter","__publicField","viewKey","stored","error","state","usePanelPersistence","options","defaultSizes","panelType","adapter","sizes","setSizes","useState","collapsed","setCollapsed","prevCollapsedRef","useRef","lastNonZeroSizesRef","saveTimeoutRef","pendingPersistSizesRef","useEffect","saved","updateLastNonZeroSizes","useCallback","incomingSizes","getFallbackSize","panel","storedSize","prevDefaultSizesRef","leftChanged","rightChanged","savePreferences","newSizes","handlePanelResize","sanitizedSizes","shouldPersist","leftCollapsed","leftSize","fallback","rightCollapsed","rightSize","pendingSizes","handleLeftCollapseComplete","handleLeftExpandComplete","handleRightCollapseComplete","handleRightExpandComplete","LocalStorageWorkspaceAdapter","presets","repositoryKey","key","allStates","i","parseError","WorkspaceLayoutService","builtInWorkspaces","id","userWorkspaces","workspace","updatedPresets","updates","existingWorkspace","updatedWorkspace","currentState","repoState","hasSizeDeviation","hasCollapsedDeviation","workspaceId","layout","workspaces","layout1","layout2","name","now","useWorkspace","autoInitialize","defaultWorkspaceId","setWorkspaces","repositoryState","setRepositoryState","activeWorkspace","setActiveWorkspace","loading","setLoading","setError","loadData","allWorkspaces","err","getWorkspace","createWorkspace","createOptions","updateWorkspace","deleteWorkspace","success","applyWorkspace","newState","updateSizes","updateCollapsed","resetToDefaults","refresh","usePanelFocus","initialFocus","onFocusChange","events","getPanelId","focusedPanel","setFocusedPanelState","setFocus","previousPanel","prevPanelId","panelId","clearFocus","getVisiblePanels","panels","focusNext","visiblePanels","currentIndex","nextIndex","focusPrevious","prevIndex","isFocused","usePanelKeyboardShortcuts","enabled","onExpand","onCollapse","focusedPanelRef","collapsedRef","panelTypeRef","handleKeyDown","event","code","currentFocused","currentCollapsed","currentPanelType","usePanelFocusListener","onFocus","onBlur","unsubscribeFocus","unsubscribeBlur","FocusIndicator","className","style","defaultStyles","jsx","CommandInput","value","onChange","placeholder","onClose","onEnter","theme","useTheme","inputRef","e","CommandItem","forwardRef","command","isSelected","onClick","onMouseEnter","ref","label","description","icon","shortcut","isHovered","setIsHovered","React","jsxs","CommandList","commands","selectedIndex","onSelect","onHover","maxResults","listRef","selectedItemRef","displayedCommands","item","container","itemTop","itemBottom","containerScrollTop","containerHeight","groupedCommands","acc","index","category","categories","a","b","CommandPalette","commandPalette","config","containerRef","isOpen","close","query","setQuery","filteredCommands","setSelectedIndex","executeSelected","handleClickOutside","timeoutId","maxHeight","Fragment","CommandRegistryService","commandIds","commandId","context","allCommands","_a","_b","availableCommands","lowerQuery","score","keyword","priorityDiff","categoryA","categoryB","categoryDiff","listener","globalRegistry","getGlobalCommandRegistry","resetGlobalCommandRegistry","useCommandPalette","initialCommands","keyboard","providedRegistry","setIsOpen","registeredCommands","setRegisteredCommands","registry","useMemo","commandContext","isSubscribed","unsubscribe","updatedCommands","open","toggle","executeCommand","selectNext","prev","maxIndex","selectPrevious","firstCommand","registerCommands","unregisterCommands","altKey","ctrlKey","metaKey","shiftKey","modifiersMatch","target","panelCommands","getPanelCommands"],"mappings":";;;;;;;AAoBO,MAAMA,EAA6D;AAAA,EAAnE;AACG,IAAAC,EAAA,oBAAa;AAAA;AAAA,EAErB,MAAM,KAAKC,GAAiB;AAC1B,QAAI;AACF,YAAMC,IAAS,aAAa,QAAQ,GAAG,KAAK,UAAU,IAAID,CAAO,EAAE;AACnE,aAAOC,IAAS,KAAK,MAAMA,CAAM,IAAI;AAAA,IACvC,SAASC,GAAO;AACd,qBAAQ,MAAM,mCAAmCF,CAAO,KAAKE,CAAK,GAC3D;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,KAAKF,GAAiBG,GAA8C;AACxE,QAAI;AACF,mBAAa;AAAA,QACX,GAAG,KAAK,UAAU,IAAIH,CAAO;AAAA,QAC7B,KAAK,UAAUG,CAAK;AAAA,MAAA;AAAA,IAExB,SAASD,GAAO;AACd,cAAQ,MAAM,mCAAmCF,CAAO,KAAKE,CAAK;AAAA,IACpE;AAAA,EACF;AACF;AA4BO,SAASE,GACdC,GACkB;AAClB,QAAM;AAAA,IACJ,SAAAL;AAAA,IACA,cAAAM;AAAA,IACA,WAAAC;AAAA,IACA,SAAAC,IAAU,IAAIV,EAAA;AAAA,EAA+B,IAC3CO,GAEE,CAACI,GAAOC,CAAQ,IAAIC,EAASL,CAAY,GACzC,CAACM,GAAWC,CAAY,IAAIF,EAASN,EAAQ,SAAS,GACtDS,IAAmBC,EAAOV,EAAQ,SAAS,GAC3CW,IAAsBD,EAA4C,EAAE,GACpEE,IAAiBF,EAA6C,IAAI,GAClEG,IAAyBH,EAA4B,IAAI;AAG/D,EAAAI,EAAU,MAAM;AAQd,KAPuB,YAAY;AACjC,YAAMC,IAAQ,MAAMZ,EAAQ,KAAKR,CAAO;AACxC,MAAIoB,KAAA,QAAAA,EAAO,UACTV,EAASU,EAAM,KAAqB,GACpCC,EAAuBD,EAAM,KAAK;AAAA,IAEtC,GACA;AAAA,EAEF,GAAG,CAACpB,CAAO,CAAC;AAEZ,QAAMqB,IAAyBC;AAAA,IAC7B,CAACC,MAA8C;AAC7C,MAAI,UAAUA,KAAiBA,EAAc,OAAO,MAClDP,EAAoB,QAAQ,OAAOO,EAAc,OAG/C,YAAYA,KAAiBA,EAAc,SAAS,MACtDP,EAAoB,QAAQ,SAASO,EAAc,SAGjD,WAAWA,KAAiBA,EAAc,QAAQ,MACpDP,EAAoB,QAAQ,QAAQO,EAAc;AAAA,IAEtD;AAAA,IACA,CAAA;AAAA,EAAC,GAGGC,IAAkBF;AAAA,IACtB,CAACG,MAA4B;AAC3B,YAAMC,IAAaV,EAAoB,QAAQS,CAAK;AACpD,UAAIC,KAAcA,IAAa;AAC7B,eAAOA;AAGT,UAAID,MAAU,UAAU,UAAUnB,KAAgBA,EAAa,OAAO;AACpE,eAAOA,EAAa;AAGtB,UACEmB,MAAU,WACV,WAAWnB,KACXA,EAAa,QAAQ;AAErB,eAAOA,EAAa;AAAA,IAIxB;AAAA,IACA,CAACA,CAAY;AAAA,EAAA,GAITqB,IAAsBZ,EAAOT,CAAY;AAC/C,EAAAa,EAAU,MAAM;AAYd,KATG,UAAUb,KACTA,EAAa,SAASqB,EAAoB,QAAQ,QACnD,YAAYrB,KACX,YAAYqB,EAAoB,WAChCrB,EAAa,WACVqB,EAAoB,QAAuB,UAC/C,WAAWrB,KACVA,EAAa,UAAUqB,EAAoB,QAAQ,WAGrDjB,EAASJ,CAAY,GACrBe,EAAuBf,CAAY,GACnCqB,EAAoB,UAAUrB;AAAA,EAElC,GAAG,CAACA,GAAce,CAAsB,CAAC,GAGzCF,EAAU,MAAM;AACd,UAAMS,IACJvB,EAAQ,UAAU,SAASS,EAAiB,QAAQ,MAChDe,IACJ,WAAWxB,EAAQ,aACnB,WAAWS,EAAiB,WAC3BT,EAAQ,UAA6B,UACnCS,EAAiB,QAA2B;AAEjD,KAAIc,KAAeC,OACjBhB,EAAaR,EAAQ,SAAS,GAC9BS,EAAiB,UAAU,EAAE,GAAGT,EAAQ,UAAA;AAAA,EAE5C,GAAG,CAACA,EAAQ,UAAU,MAAOA,EAAQ,UAA6B,KAAK,CAAC;AAGxE,QAAMyB,IAAkBR;AAAA,IACtB,OAAOS,MAA2B;AAChC,UAAI;AACF,cAAMvB,EAAQ,KAAKR,GAAS,EAAE,OAAO+B,GAAU;AAAA,MACjD,SAAS7B,GAAO;AACd,gBAAQ;AAAA,UACN,wCAAwCF,CAAO;AAAA,UAC/CE;AAAA,QAAA;AAAA,MAEJ;AAAA,IACF;AAAA,IACA,CAACF,GAASQ,CAAO;AAAA,EAAA,GAIbwB,IAAoBV;AAAA,IACxB,CAACS,MAA2B;AAC1B,YAAME,IAAiB,EAAE,GAAGF,EAAA;AAC5B,UAAIG,IAAgB;AAEpB,UAAI,UAAUH,GAAU;AACtB,cAAMI,IAAgB,GAASvB,KAAA,QAAAA,EAA8B,OACvDwB,IAAWL,EAAS;AAE1B,YAAII,GAAe;AACjB,gBAAME,IAAWb,EAAgB,MAAM;AACvC,UAAIa,MAAa,UAAaA,IAAW,IACvCJ,EAAe,OAAOI,IAEtBH,IAAgB;AAAA,QAEpB,MAAA,CAAWE,MAAa,MACtBF,IAAgB;AAAA,MAEpB;AAEA,UAAI3B,MAAc,iBAAiB,WAAWwB,GAAU;AACtD,cAAMO,IAAiB,GAAS1B,KAAA,QAAAA,EAA8B,QACxD2B,IAAYR,EAAS;AAE3B,YAAIO,GAAgB;AAClB,gBAAMD,IAAWb,EAAgB,OAAO;AACxC,UAAIa,MAAa,UAAaA,IAAW,IACvCJ,EAAe,QAAQI,IAEvBH,IAAgB;AAAA,QAEpB,MAAA,CAAWK,MAAc,MACvBL,IAAgB;AAAA,MAEpB;AAUA,UARAxB,EAASuB,CAAc,GACvBZ,EAAuBY,CAAc,GAEjChB,EAAe,YACjB,aAAaA,EAAe,OAAO,GACnCA,EAAe,UAAU,OAGvB,CAACiB,GAAe;AAClB,QAAAhB,EAAuB,UAAU;AACjC;AAAA,MACF;AAEA,MAAAA,EAAuB,UAAUe,GACjChB,EAAe,UAAU,WAAW,MAAM;AACxC,cAAMuB,IAAetB,EAAuB;AAC5C,QAAIsB,MACFV,EAAgBU,CAAY,GAC5BtB,EAAuB,UAAU,OAEnCD,EAAe,UAAU;AAAA,MAC3B,GAAG,GAAG;AAAA,IACR;AAAA,IACA;AAAA,MACEL;AAAA,MACAY;AAAA,MACAjB;AAAA,MACAuB;AAAA,MACAT;AAAA,IAAA;AAAA,EACF;AAIF,EAAAF,EAAU,MACD,MAAM;AACX,QAAIF,EAAe,SAAS;AAC1B,YAAMuB,IAAetB,EAAuB;AAC5C,MAAIsB,MACFV,EAAgBU,CAAY,GAC5BtB,EAAuB,UAAU,OAEnC,aAAaD,EAAe,OAAO,GACnCA,EAAe,UAAU;AAAA,IAC3B;AAAA,EACF,GACC,CAACa,CAAe,CAAC;AAIpB,QAAMW,IAA6BnB,EAAY,YAAY;AAAA,EAE3D,GAAG,CAAA,CAAE,GAECoB,IAA2BpB,EAAY,YAAY;AAAA,EAEzD,GAAG,CAAA,CAAE,GAECqB,IAA8BrB,EAAY,YAAY;AAAA,EAE5D,GAAG,CAAA,CAAE,GAECsB,IAA4BtB,EAAY,YAAY;AAAA,EAE1D,GAAG,CAAA,CAAE;AAEL,SAAIf,MAAc,gBACT;AAAA,IACL,MAAM;AAAA,IACN,OAAAE;AAAA,IACA,WAAAG;AAAA,IACA,mBAAAoB;AAAA,IACA,4BAAAS;AAAA,IACA,0BAAAC;AAAA,IACA,6BAAAC;AAAA,IACA,2BAAAC;AAAA,EAAA,IAGK;AAAA,IACL,MAAM;AAAA,IACN,OAAAnC;AAAA,IACA,WAAAG;AAAA,IACA,mBAAAoB;AAAA,IACA,4BAAAS;AAAA,IACA,0BAAAC;AAAA,EAAA;AAGN;ACnTO,MAAMG,EAAgE;AAAA,EAAtE;AACY,IAAA9C,EAAA,qBAAc;AACd,IAAAA,EAAA,2BAAoB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKrC,MAAM,uBAAiE;AACrE,QAAI;AACF,YAAME,IAAS,aAAa,QAAQ,KAAK,WAAW;AACpD,aAAKA,IAGE,KAAK,MAAMA,CAAM,IAFf,CAAA;AAAA,IAGX,SAASC,GAAO;AACd,qBAAQ,MAAM,qCAAqCA,CAAK,GACjD,CAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,qBACJ4C,GACe;AACf,QAAI;AACF,mBAAa,QAAQ,KAAK,aAAa,KAAK,UAAUA,CAAO,CAAC;AAAA,IAChE,SAAS5C,GAAO;AACd,oBAAQ,MAAM,qCAAqCA,CAAK,GAClDA;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,oBACJ6C,GAC0C;AAC1C,QAAI;AACF,YAAMC,IAAM,GAAG,KAAK,iBAAiB,GAAGD,CAAa,IAC/C9C,IAAS,aAAa,QAAQ+C,CAAG;AACvC,aAAK/C,IAGE,KAAK,MAAMA,CAAM,IAFf;AAAA,IAGX,SAASC,GAAO;AACd,qBAAQ;AAAA,QACN,uCAAuC6C,CAAa;AAAA,QACpD7C;AAAA,MAAA,GAEK;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,oBACJ6C,GACA5C,GACe;AACf,QAAI;AACF,YAAM6C,IAAM,GAAG,KAAK,iBAAiB,GAAGD,CAAa;AACrD,mBAAa,QAAQC,GAAK,KAAK,UAAU7C,CAAK,CAAC;AAAA,IACjD,SAASD,GAAO;AACd,oBAAQ;AAAA,QACN,uCAAuC6C,CAAa;AAAA,QACpD7C;AAAA,MAAA,GAEIA;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,0BAEJ;AACA,QAAI;AACF,YAAM+C,IAAsD,CAAA;AAG5D,eAASC,IAAI,GAAGA,IAAI,aAAa,QAAQA,KAAK;AAC5C,cAAMF,IAAM,aAAa,IAAIE,CAAC;AAC9B,YAAIF,KAAOA,EAAI,WAAW,KAAK,iBAAiB,GAAG;AACjD,gBAAMD,IAAgBC,EAAI,UAAU,KAAK,kBAAkB,MAAM,GAC3D/C,IAAS,aAAa,QAAQ+C,CAAG;AACvC,cAAI/C;AACF,gBAAI;AACF,cAAAgD,EAAUF,CAAa,IAAI,KAAK,MAAM9C,CAAM;AAAA,YAC9C,SAASkD,GAAY;AACnB,sBAAQ;AAAA,gBACN,wCAAwCJ,CAAa;AAAA,gBACrDI;AAAA,cAAA;AAAA,YAEJ;AAAA,QAEJ;AAAA,MACF;AAEA,aAAOF;AAAA,IACT,SAAS/C,GAAO;AACd,qBAAQ,MAAM,yCAAyCA,CAAK,GACrD,CAAA;AAAA,IACT;AAAA,EACF;AACF;ACtGO,MAAMkD,EAAuB;AAAA;AAAA;AAAA;AAAA,EAOlC,OAAO,WAAW5C,GAAwC;AACxD,SAAK,UAAUA;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,sBAAgE;AAC3E,UAAM6C,IAAoB,KAAK,2BAAA;AAI/B,WAAO;AAAA,MACL,GAJqB,MAAM,KAAK,QAAQ,qBAAA;AAAA,MAKxC,GAAGA;AAAA,IAAA;AAAA,EAEP;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,mBAAmBC,GAA6C;AAE3E,YADmB,MAAM,KAAK,oBAAA,GACZA,CAAE,KAAK;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,sBACXjD,GAC0B;AAC1B,UAAMkD,IAAiB,MAAM,KAAK,QAAQ,qBAAA,GACpCD,IAAK,KAAK,oBAAoBjD,EAAQ,IAAI,GAE1CmD,IAA6B;AAAA,MACjC,IAAAF;AAAA,MACA,MAAMjD,EAAQ;AAAA,MACd,aAAaA,EAAQ;AAAA,MACrB,QAAQA,EAAQ;AAAA,MAChB,cAAcA,EAAQ;AAAA,MACtB,kBAAkBA,EAAQ;AAAA,MAC1B,WAAW,KAAK,IAAA;AAAA,MAChB,WAAW,KAAK,IAAA;AAAA,MAChB,WAAW;AAAA,IAAA,GAGPoD,IAAiB;AAAA,MACrB,GAAGF;AAAA,MACH,CAACD,CAAE,GAAGE;AAAA,IAAA;AAGR,iBAAM,KAAK,QAAQ,qBAAqBC,CAAc,GAE/CD;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,sBACXF,GACAI,GACiC;AACjC,UAAMH,IAAiB,MAAM,KAAK,QAAQ,qBAAA,GACpCI,IAAoBJ,EAAeD,CAAE;AAE3C,QAAI,CAACK;AACH,qBAAQ,MAAM,oBAAoBL,CAAE,YAAY,GACzC;AAIT,QAAIK,EAAkB;AACpB,qBAAQ,MAAM,2CAA2CL,CAAE,EAAE,GACtD;AAGT,UAAMM,IAAoC;AAAA,MACxC,GAAGD;AAAA,MACH,GAAGD;AAAA,MACH,IAAAJ;AAAA;AAAA,MACA,WAAWK,EAAkB;AAAA;AAAA,MAC7B,WAAW,KAAK,IAAA;AAAA,IAAI,GAGhBF,IAAiB;AAAA,MACrB,GAAGF;AAAA,MACH,CAACD,CAAE,GAAGM;AAAA,IAAA;AAGR,iBAAM,KAAK,QAAQ,qBAAqBH,CAAc,GAE/CG;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,sBAAsBN,GAA8B;AAC/D,UAAMC,IAAiB,MAAM,KAAK,QAAQ,qBAAA,GACpCC,IAAYD,EAAeD,CAAE;AAEnC,QAAI,CAACE;AACH,qBAAQ,MAAM,oBAAoBF,CAAE,YAAY,GACzC;AAIT,QAAIE,EAAU;AACZ,qBAAQ,MAAM,2CAA2CF,CAAE,EAAE,GACtD;AAGT,UAAMG,IAAiB,EAAE,GAAGF,EAAA;AAC5B,kBAAOE,EAAeH,CAAE,GAExB,MAAM,KAAK,QAAQ,qBAAqBG,CAAc,GAE/C;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,mBACXV,GAC0C;AAC1C,WAAO,MAAM,KAAK,QAAQ,oBAAoBA,CAAa;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,mBACXA,GACA5C,GACe;AACf,UAAM,KAAK,QAAQ,oBAAoB4C,GAAe5C,CAAK;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,sBACX4C,GACAtC,GACe;AACf,UAAMoD,IAAe,MAAM,KAAK,mBAAmBd,CAAa;AAChE,IAAKc,KAEL,MAAM,KAAK,mBAAmBd,GAAe;AAAA,MAC3C,GAAGc;AAAA,MACH,OAAApD;AAAA,IAAA,CACD;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,0BACXsC,GACAnC,GACe;AACf,UAAMiD,IAAe,MAAM,KAAK,mBAAmBd,CAAa;AAChE,IAAKc,KAEL,MAAM,KAAK,mBAAmBd,GAAe;AAAA,MAC3C,GAAGc;AAAA,MACH,WAAAjD;AAAA,IAAA,CACD;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,kBACLkD,GAKAN,GAIA;AACA,UAAMO,IAAmBP,EAAU,eAC/B,KAAK,UAAUM,EAAU,KAAK,MAC9B,KAAK,UAAUN,EAAU,YAAY,IACrC,IAEEQ,IAAwBR,EAAU,mBACpC,KAAK,UAAUM,EAAU,SAAS,MAClC,KAAK,UAAUN,EAAU,gBAAgB,IACzC;AAEJ,WAAO,EAAE,kBAAAO,GAAkB,uBAAAC,EAAA;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,mCACXC,GACAlB,GACe;AACf,UAAMS,IAAY,MAAM,KAAK,mBAAmBS,CAAW,GACrDH,IAAY,MAAM,KAAK,mBAAmBf,CAAa;AAE7D,QAAI,CAACS,KAAa,CAACM,KAAaN,EAAU,WAAW;AACnD,cAAQ;AAAA,QACN;AAAA,MAAA;AAEF;AAAA,IACF;AAEA,UAAM,KAAK,sBAAsBS,GAAa;AAAA,MAC5C,cAAcH,EAAU;AAAA,MACxB,kBAAkBA,EAAU;AAAA,IAAA,CAC7B;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,mCACXf,GACAkB,GACe;AACf,UAAMT,IAAY,MAAM,KAAK,mBAAmBS,CAAW;AAC3D,QAAI,CAACT,GAAW;AACd,cAAQ,MAAM,aAAaS,CAAW,YAAY;AAClD;AAAA,IACF;AAEA,UAAMJ,IAAe,MAAM,KAAK,mBAAmBd,CAAa;AAChE,IAAKc,KAEL,MAAM,KAAK,mBAAmBd,GAAe;AAAA,MAC3C,GAAGc;AAAA,MACH,OAAOL,EAAU,gBAAgB,EAAE,MAAM,IAAI,QAAQ,IAAI,OAAO,GAAA;AAAA,MAChE,WAAWA,EAAU,oBAAoB,EAAE,MAAM,IAAO,OAAO,GAAA;AAAA,IAAM,CACtE;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,0BACLU,GACAV,GACS;AACT,WAAO,KAAK,gBAAgBU,GAAQV,EAAU,MAAM;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,sBACXU,GACwB;AACxB,UAAMC,IAAa,MAAM,KAAK,oBAAA;AAE9B,eAAW,CAACb,GAAIE,CAAS,KAAK,OAAO,QAAQW,CAAU;AACrD,UAAI,KAAK,0BAA0BD,GAAQV,CAAS;AAClD,eAAOF;AAIX,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAe,gBACbc,GACAC,GACS;AACT,WAAO,KAAK,UAAUD,CAAO,MAAM,KAAK,UAAUC,CAAO;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA,EAKA,OAAe,oBAAoBC,GAAsB;AAEvD,WAAO,GADMA,EAAK,YAAA,EAAc,QAAQ,eAAe,GAAG,CAC5C,IAAI,KAAK,KAAK;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,6BAA8D;AACnE,UAAMC,IAAM,KAAK,IAAA;AAEjB,WAAO;AAAA,MACL,sBAAsB;AAAA,QACpB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,aACE;AAAA,QACF,QAAQ;AAAA,UACN,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,QAAQ;AAAA,cACN;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YAAA;AAAA,YAEF,QAAQ,EAAE,kBAAkB,GAAG,aAAa,MAAA;AAAA,UAAM;AAAA,UAEpD,QAAQ;AAAA,UACR,OAAO;AAAA,YACL,MAAM;AAAA,YACN,QAAQ;AAAA,cACN;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YAAA;AAAA,YAEF,QAAQ,EAAE,kBAAkB,GAAG,aAAa,MAAA;AAAA,UAAM;AAAA,QACpD;AAAA,QAEF,cAAc,EAAE,MAAM,IAAI,QAAQ,IAAI,OAAO,GAAA;AAAA,QAC7C,kBAAkB,EAAE,MAAM,IAAO,OAAO,GAAA;AAAA,QACxC,WAAWA;AAAA,QACX,WAAWA;AAAA,QACX,WAAW;AAAA,MAAA;AAAA,MAEb,eAAe;AAAA,QACb,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,aACE;AAAA,QACF,QAAQ;AAAA,UACN,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,QAAQ,CAAC,cAAc,mBAAmB,UAAU;AAAA,YACpD,QAAQ,EAAE,kBAAkB,GAAG,aAAa,MAAA;AAAA,UAAM;AAAA,UAEpD,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,QAAQ,CAAC,WAAW,YAAY;AAAA,YAChC,QAAQ,EAAE,kBAAkB,GAAG,aAAa,MAAA;AAAA,UAAM;AAAA,UAEpD,OAAO;AAAA,QAAA;AAAA,QAET,cAAc,EAAE,MAAM,IAAI,QAAQ,IAAI,OAAO,GAAA;AAAA,QAC7C,kBAAkB,EAAE,MAAM,IAAO,OAAO,GAAA;AAAA,QACxC,WAAWA;AAAA,QACX,WAAWA;AAAA,QACX,WAAW;AAAA,MAAA;AAAA,MAEb,eAAe;AAAA,QACb,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,aAAa;AAAA,QACb,QAAQ;AAAA,UACN,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,OAAO;AAAA,QAAA;AAAA,QAET,cAAc,EAAE,MAAM,IAAI,QAAQ,IAAI,OAAO,GAAA;AAAA,QAC7C,kBAAkB,EAAE,MAAM,IAAO,OAAO,GAAA;AAAA,QACxC,WAAWA;AAAA,QACX,WAAWA;AAAA,QACX,WAAW;AAAA,MAAA;AAAA,MAEb,cAAc;AAAA,QACZ,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,aACE;AAAA,QACF,QAAQ;AAAA,UACN,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,QAAQ;AAAA,cACN;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YAAA;AAAA,YAEF,QAAQ,EAAE,kBAAkB,GAAG,aAAa,MAAA;AAAA,UAAM;AAAA,UAEpD,QAAQ;AAAA,UACR,OAAO;AAAA,YACL,MAAM;AAAA,YACN,QAAQ;AAAA,cACN;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YAAA;AAAA,YAEF,QAAQ,EAAE,kBAAkB,GAAG,aAAa,MAAA;AAAA,UAAM;AAAA,QACpD;AAAA,QAEF,cAAc,EAAE,MAAM,IAAI,QAAQ,IAAI,OAAO,GAAA;AAAA,QAC7C,kBAAkB,EAAE,MAAM,IAAO,OAAO,GAAA;AAAA,QACxC,WAAWA;AAAA,QACX,WAAWA;AAAA,QACX,WAAW;AAAA,MAAA;AAAA,MAEb,iBAAiB;AAAA,QACf,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,aACE;AAAA,QACF,QAAQ;AAAA,UACN,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,QAAQ,CAAC,eAAe,SAAS,cAAc;AAAA,YAC/C,QAAQ,EAAE,kBAAkB,GAAG,aAAa,MAAA;AAAA,UAAM;AAAA,UAEpD,QAAQ;AAAA,UACR,OAAO;AAAA,YACL,MAAM;AAAA,YACN,QAAQ,CAAC,iBAAiB,YAAY;AAAA,YACtC,QAAQ,EAAE,kBAAkB,GAAG,aAAa,MAAA;AAAA,UAAM;AAAA,QACpD;AAAA,QAEF,cAAc,EAAE,MAAM,IAAI,QAAQ,IAAI,OAAO,GAAA;AAAA,QAC7C,kBAAkB,EAAE,MAAM,IAAO,OAAO,GAAA;AAAA,QACxC,WAAWA;AAAA,QACX,WAAWA;AAAA,QACX,WAAW;AAAA,MAAA;AAAA,MAEb,SAAS;AAAA,QACP,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,aACE;AAAA,QACF,QAAQ;AAAA,UACN,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,QAAQ,CAAC,YAAY,MAAM;AAAA,YAC3B,QAAQ,EAAE,kBAAkB,GAAG,aAAa,MAAA;AAAA,UAAM;AAAA,UAEpD,QAAQ;AAAA,UACR,OAAO;AAAA,YACL,MAAM;AAAA,YACN,QAAQ,CAAC,iBAAiB,gBAAgB;AAAA,YAC1C,QAAQ,EAAE,kBAAkB,GAAG,aAAa,MAAA;AAAA,UAAM;AAAA,QACpD;AAAA,QAEF,cAAc,EAAE,MAAM,IAAI,QAAQ,IAAI,OAAO,GAAA;AAAA,QAC7C,kBAAkB,EAAE,MAAM,IAAO,OAAO,GAAA;AAAA,QACxC,WAAWA;AAAA,QACX,WAAWA;AAAA,QACX,WAAW;AAAA,MAAA;AAAA,MAEb,cAAc;AAAA,QACZ,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,aACE;AAAA,QACF,QAAQ;AAAA,UACN,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,QAAQ,CAAC,YAAY,UAAU,cAAc,MAAM;AAAA,YACnD,QAAQ,EAAE,kBAAkB,GAAG,aAAa,MAAA;AAAA,UAAM;AAAA,UAEpD,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,QAAQ,CAAC,cAAc,gBAAgB;AAAA,YACvC,QAAQ,EAAE,kBAAkB,GAAG,aAAa,MAAA;AAAA,UAAM;AAAA,UAEpD,OAAO;AAAA,YACL,MAAM;AAAA,YACN,QAAQ,CAAC,iBAAiB,mBAAmB;AAAA,YAC7C,QAAQ,EAAE,kBAAkB,GAAG,aAAa,MAAA;AAAA,UAAM;AAAA,QACpD;AAAA,QAEF,cAAc,EAAE,MAAM,IAAI,QAAQ,IAAI,OAAO,GAAA;AAAA,QAC7C,kBAAkB,EAAE,MAAM,IAAO,OAAO,GAAA;AAAA,QACxC,WAAWA;AAAA,QACX,WAAWA;AAAA,QACX,WAAW;AAAA,MAAA;AAAA,MAEb,oBAAoB;AAAA,QAClB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,aACE;AAAA,QACF,QAAQ;AAAA,UACN,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,OAAO;AAAA,QAAA;AAAA,QAET,cAAc,EAAE,MAAM,IAAI,QAAQ,IAAI,OAAO,GAAA;AAAA,QAC7C,kBAAkB,EAAE,MAAM,IAAO,OAAO,GAAA;AAAA,QACxC,WAAWA;AAAA,QACX,WAAWA;AAAA,QACX,WAAW;AAAA,MAAA;AAAA,IACb;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,6BAA4C;AACvD,UAAMhB,IAAiB,MAAM,KAAK,QAAQ,qBAAA;AAI1C,IAAI,OAAO,KAAKA,CAAc,EAAE;AAAA,EAIlC;AACF;AA3gBExD,EADWqD,GACI,WACb,IAAIP,EAAA;AC8FD,SAAS2B,GACdnE,IAA+B,IACX;AACpB,QAAM,EAAE,eAAA0C,GAAe,gBAAA0B,IAAiB,IAAO,oBAAAC,MAAuBrE,GAEhE,CAAC8D,GAAYQ,CAAa,IAAIhE;AAAA,IAClC,CAAA;AAAA,EAAC,GAEG,CAACiE,GAAiBC,CAAkB,IACxClE,EAA0C,IAAI,GAC1C,CAACmE,GAAiBC,CAAkB,IACxCpE,EAAiC,IAAI,GACjC,CAACqE,GAASC,CAAU,IAAItE,EAAS,EAAI,GACrC,CAACT,GAAOgF,CAAQ,IAAIvE,EAAuB,IAAI,GAK/CwE,IAAW7D,EAAY,YAAY;AACvC,QAAI;AACF,MAAA2D,EAAW,EAAI,GACfC,EAAS,IAAI;AAGb,YAAME,IACJ,MAAMhC,EAAuB,oBAAA;AAI/B,UAHAuB,EAAcS,CAAa,GAGvBrC,GAAe;AACjB,YAAIe,IACF,MAAMV,EAAuB,mBAAmBL,CAAa;AAG/D,YAAI,CAACe,KAAaW,GAAgB;AAChC,gBAAMR,IACJS,KAAsB,sBAClBlB,IACJ,MAAMJ,EAAuB,mBAAmBa,CAAW;AAE7D,UAAIT,MACFM,IAAY;AAAA,YACV,aAAAG;AAAA,YACA,OAAOT,EAAU,gBAAgB;AAAA,cAC/B,MAAM;AAAA,cACN,QAAQ;AAAA,cACR,OAAO;AAAA,YAAA;AAAA,YAET,WAAWA,EAAU,oBAAoB;AAAA,cACvC,MAAM;AAAA,cACN,OAAO;AAAA,YAAA;AAAA,UACT,GAGF,MAAMJ,EAAuB;AAAA,YAC3BL;AAAA,YACAe;AAAA,UAAA;AAAA,QAGN;AAKA,YAHAe,EAAmBf,CAAS,GAGxBA,KAAA,QAAAA,EAAW,aAAa;AAC1B,gBAAMN,IAAY,MAAMJ,EAAuB;AAAA,YAC7CU,EAAU;AAAA,UAAA;AAEZ,UAAAiB,EAAmBvB,CAAS;AAAA,QAC9B;AACE,UAAAuB,EAAmB,IAAI;AAAA,MAE3B;AAAA,IACF,SAASM,GAAK;AACZ,MAAAH,EAASG,CAAY,GACrB,QAAQ,MAAM,kCAAkCA,CAAG;AAAA,IACrD,UAAA;AACE,MAAAJ,EAAW,EAAK;AAAA,IAClB;AAAA,EACF,GAAG,CAAClC,GAAe0B,GAAgBC,CAAkB,CAAC;AAKtD,EAAAvD,EAAU,MAAM;AACd,IAAAgE,EAAA;AAAA,EACF,GAAG,CAACA,CAAQ,CAAC;AAKb,QAAMG,IAAehE;AAAA,IACnB,OAAOgC,MACE,MAAMF,EAAuB,mBAAmBE,CAAE;AAAA,IAE3D,CAAA;AAAA,EAAC,GAMGiC,IAAkBjE;AAAA,IACtB,OAAOkE,MAA0C;AAC/C,YAAMhC,IACJ,MAAMJ,EAAuB,sBAAsBoC,CAAa;AAClE,mBAAML,EAAA,GACC3B;AAAA,IACT;AAAA,IACA,CAAC2B,CAAQ;AAAA,EAAA,GAMLM,IAAkBnE;AAAA,IACtB,OAAOgC,GAAYI,MAAoC;AACrD,YAAMF,IACJ,MAAMJ,EAAuB,sBAAsBE,GAAII,CAAO;AAChE,mBAAMyB,EAAA,GACC3B;AAAA,IACT;AAAA,IACA,CAAC2B,CAAQ;AAAA,EAAA,GAMLO,IAAkBpE;AAAA,IACtB,OAAOgC,MAAe;AACpB,YAAMqC,IAAU,MAAMvC,EAAuB,sBAAsBE,CAAE;AACrE,aAAIqC,KACF,MAAMR,EAAA,GAEDQ;AAAA,IACT;AAAA,IACA,CAACR,CAAQ;AAAA,EAAA,GAMLS,IAAiBtE;AAAA,IACrB,OAAO2C,MAAwB;AAC7B,UAAI,CAAClB,GAAe;AAClB,gBAAQ,MAAM,8CAA8C;AAC5D;AAAA,MACF;AAEA,YAAMS,IACJ,MAAMJ,EAAuB,mBAAmBa,CAAW;AAC7D,UAAI,CAACT,GAAW;AACd,gBAAQ,MAAM,aAAaS,CAAW,YAAY;AAClD;AAAA,MACF;AAEA,YAAM4B,IAAqC;AAAA,QACzC,aAAA5B;AAAA,QACA,OAAOT,EAAU,gBAAgB,EAAE,MAAM,IAAI,QAAQ,IAAI,OAAO,GAAA;AAAA,QAChE,WAAWA,EAAU,oBAAoB;AAAA,UACvC,MAAM;AAAA,UACN,OAAO;AAAA,QAAA;AAAA,MACT;AAGF,YAAMJ,EAAuB,mBAAmBL,GAAe8C,CAAQ,GACvE,MAAMV,EAAA;AAAA,IACR;AAAA,IACA,CAACpC,GAAeoC,CAAQ;AAAA,EAAA,GAMpBW,IAAcxE;AAAA,IAClB,OAAOb,MAA2D;AAChE,UAAI,CAACsC,GAAe;AAClB,gBAAQ,MAAM,2CAA2C;AACzD;AAAA,MACF;AAEA,YAAMK,EAAuB,sBAAsBL,GAAetC,CAAK,GACvE,MAAM0E,EAAA;AAAA,IACR;AAAA,IACA,CAACpC,GAAeoC,CAAQ;AAAA,EAAA,GAMpBY,IAAkBzE;AAAA,IACtB,OAAOV,MAAmD;AACxD,UAAI,CAACmC,GAAe;AAClB,gBAAQ,MAAM,+CAA+C;AAC7D;AAAA,MACF;AAEA,YAAMK,EAAuB;AAAA,QAC3BL;AAAA,QACAnC;AAAA,MAAA,GAEF,MAAMuE,EAAA;AAAA,IACR;AAAA,IACA,CAACpC,GAAeoC,CAAQ;AAAA,EAAA,GAMpBa,IAAkB1E,EAAY,YAAY;AAC9C,QAAI,CAACyB,KAAiB,EAAC6B,KAAA,QAAAA,EAAiB,cAAa;AACnD,cAAQ,MAAM,yDAAyD;AACvE;AAAA,IACF;AAEA,UAAMxB,EAAuB;AAAA,MAC3BL;AAAA,MACA6B,EAAgB;AAAA,IAAA,GAElB,MAAMO,EAAA;AAAA,EACR,GAAG,CAACpC,GAAe6B,KAAA,gBAAAA,EAAiB,aAAaO,CAAQ,CAAC,GAKpDc,IAAU3E,EAAY,YAAY;AACtC,UAAM6D,EAAA;AAAA,EACR,GAAG,CAACA,CAAQ,CAAC;AAEb,SAAO;AAAA,IACL,YAAAhB;AAAA,IACA,iBAAAS;AAAA,IACA,iBAAAE;AAAA,IACA,SAAAE;AAAA,IACA,OAAA9E;AAAA,IACA,cAAAoF;AAAA,IACA,iBAAAC;AAAA,IACA,iBAAAE;AAAA,IACA,iBAAAC;AAAA,IACA,gBAAAE;AAAA,IACA,aAAAE;AAAA,IACA,iBAAAC;AAAA,IACA,iBAAAC;AAAA,IACA,SAAAC;AAAA,EAAA;AAEJ;AC7TO,SAASC,GACd7F,IAAgC,IACX;AACrB,QAAM;AAAA,IACJ,cAAA8F,IAAe;AAAA,IACf,WAAAvF,IAAY,CAAA;AAAA,IACZ,WAAAL,IAAY;AAAA,IACZ,eAAA6F;AAAA,IACA,QAAAC;AAAA,IACA,YAAAC;AAAA,EAAA,IACEjG,GAEE,CAACkG,GAAcC,CAAoB,IAAI7F;AAAA,IAC3CwF;AAAA,EAAA,GAGIM,IAAWnF;AAAA,IACf,CAACG,MAAuB;AACtB,YAAMiF,IAAgBH;AAKtB,UAJAC,EAAqB/E,CAAK,GAC1B2E,KAAA,QAAAA,EAAgB3E,IAGZ4E,KAAUC,GAAY;AAExB,YAAII,GAAe;AACjB,gBAAMC,IAAcL,EAAWI,CAAa;AAC5C,UAAIC,KACFN,EAAO,KAA4B;AAAA,YACjC,MAAM;AAAA,YACN,QAAQ;AAAA,YACR,WAAW,KAAK,IAAA;AAAA,YAChB,SAAS;AAAA,cACP,SAASM;AAAA,cACT,WAAWD;AAAA,cACX,aAAaJ,EAAW7E,CAAK;AAAA,YAAA;AAAA,UAC/B,CACD;AAAA,QAEL;AAGA,cAAMmF,IAAUN,EAAW7E,CAAK;AAChC,QAAImF,KACFP,EAAO,KAA6B;AAAA,UAClC,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,WAAW,KAAK,IAAA;AAAA,UAChB,SAAS;AAAA,YACP,SAAAO;AAAA,YACA,WAAWnF;AAAA,YACX,QAAQ;AAAA,UAAA;AAAA,QACV,CACD;AAAA,MAEL;AAAA,IACF;AAAA,IACA,CAAC8E,GAAcH,GAAeC,GAAQC,CAAU;AAAA,EAAA,GAG5CO,IAAavF,EAAY,MAAM;AACnC,UAAMoF,IAAgBH;AAKtB,QAJAC,EAAqB,IAAI,GACzBJ,KAAA,QAAAA,EAAgB,OAGZC,KAAUC,KAAcI,GAAe;AACzC,YAAMC,IAAcL,EAAWI,CAAa;AAC5C,MAAIC,KACFN,EAAO,KAA4B;AAAA,QACjC,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,WAAW,KAAK,IAAA;AAAA,QAChB,SAAS;AAAA,UACP,SAASM;AAAA,UACT,WAAWD;AAAA,QAAA;AAAA,MACb,CACD;AAAA,IAEL;AAAA,EACF,GAAG,CAACH,GAAcH,GAAeC,GAAQC,CAAU,CAAC,GAE9CQ,IAAmBxF,EAAY,MAAqB;AACxD,UAAMyF,IAAwB,CAAA;AAE9B,WAAKnG,EAAU,QACbmG,EAAO,KAAK,MAAM,GAEpBA,EAAO,KAAK,QAAQ,GAChBxG,MAAc,iBAAiB,CAACK,EAAU,SAC5CmG,EAAO,KAAK,OAAO,GAGdA;AAAA,EACT,GAAG,CAACnG,GAAWL,CAAS,CAAC,GAEnByG,IAAY1F,EAAY,MAAM;AAClC,UAAM2F,IAAgBH,EAAA;AACtB,QAAIG,EAAc,WAAW,EAAG;AAEhC,QAAIV,MAAiB,MAAM;AAEzB,MAAAE,EAASQ,EAAc,CAAC,CAAC;AACzB;AAAA,IACF;AAEA,UAAMC,IAAeD,EAAc,QAAQV,CAAY;AACvD,QAAIW,MAAiB,IAAI;AAEvB,MAAAT,EAASQ,EAAc,CAAC,CAAC;AACzB;AAAA,IACF;AAGA,UAAME,KAAaD,IAAe,KAAKD,EAAc;AACrD,IAAAR,EAASQ,EAAcE,CAAS,CAAC;AAAA,EACnC,GAAG,CAACZ,GAAcO,GAAkBL,CAAQ,CAAC,GAEvCW,IAAgB9F,EAAY,MAAM;AACtC,UAAM2F,IAAgBH,EAAA;AACtB,QAAIG,EAAc,WAAW,EAAG;AAEhC,QAAIV,MAAiB,MAAM;AAEzB,MAAAE,EAASQ,EAAcA,EAAc,SAAS,CAAC,CAAC;AAChD;AAAA,IACF;AAEA,UAAMC,IAAeD,EAAc,QAAQV,CAAY;AACvD,QAAIW,MAAiB,IAAI;AAEvB,MAAAT,EAASQ,EAAcA,EAAc,SAAS,CAAC,CAAC;AAChD;AAAA,IACF;AAGA,UAAMI,IACJH,MAAiB,IAAID,EAAc,SAAS,IAAIC,IAAe;AACjE,IAAAT,EAASQ,EAAcI,CAAS,CAAC;AAAA,EACnC,GAAG,CAACd,GAAcO,GAAkBL,CAAQ,CAAC,GAEvCa,IAAYhG;AAAA,IAChB,CAACG,MAAuB8E,MAAiB9E;AAAA,IACzC,CAAC8E,CAAY;AAAA,EAAA;AAGf,SAAO;AAAA,IACL,cAAAA;AAAA,IACA,UAAAE;AAAA,IACA,YAAAI;AAAA,IACA,WAAAG;AAAA,IACA,eAAAI;AAAA,IACA,WAAAE;AAAA,EAAA;AAEJ;ACnJO,SAASC,GACdlH,GACM;AACN,QAAM;AAAA,IACJ,SAAAmH,IAAU;AAAA,IACV,cAAAjB;AAAA,IACA,WAAA3F;AAAA,IACA,WAAAL;AAAA,IACA,UAAAkG;AAAA,IACA,UAAAgB;AAAA,IACA,YAAAC;AAAA,EAAA,IACErH,GAGEsH,IAAkB5G,EAAOwF,CAAY,GACrCqB,IAAe7G,EAAOH,CAAS,GAC/BiH,IAAe9G,EAAOR,CAAS;AAErC,EAAAY,EAAU,MAAM;AACd,IAAAwG,EAAgB,UAAUpB;AAAA,EAC5B,GAAG,CAACA,CAAY,CAAC,GAEjBpF,EAAU,MAAM;AACd,IAAAyG,EAAa,UAAUhH;AAAA,EACzB,GAAG,CAACA,CAAS,CAAC,GAEdO,EAAU,MAAM;AACd,IAAA0G,EAAa,UAAUtH;AAAA,EACzB,GAAG,CAACA,CAAS,CAAC;AAEd,QAAMuH,IAAgBxG;AAAA,IACpB,CAACyG,MAAyB;AAExB,UAAI,CAACA,EAAM,UAAUA,EAAM,WAAWA,EAAM,WAAWA,EAAM;AAC3D;AAKF,YAAMC,IAAOD,EAAM,MACbE,IAAiBN,EAAgB,SACjCO,IAAmBN,EAAa,SAChCO,IAAmBN,EAAa;AAGtC,MAAIG,MAAS,YAAYA,MAAS,aAChCD,EAAM,eAAA,GAEFG,EAAiB,OAEnBT,EAAS,MAAM,IACNQ,MAAmB,SAE5BxB,EAAS,MAAM,KAGfiB,EAAW,MAAM,GACjBjB,EAAS,QAAQ,MAIZuB,MAAS,YAAYA,MAAS,aACrCD,EAAM,eAAA,GACNtB,EAAS,QAAQ,MAGTuB,MAAS,YAAYA,MAAS,cAAcG,MAAqB,kBACzEJ,EAAM,eAAA,GAEFG,EAAiB,QAEnBT,EAAS,OAAO,IACPQ,MAAmB,UAE5BxB,EAAS,OAAO,KAGhBiB,EAAW,OAAO,GAClBjB,EAAS,QAAQ;AAAA,IAGvB;AAAA,IACA,CAACA,GAAUgB,GAAUC,CAAU;AAAA,EAAA;AAGjC,EAAAvG,EAAU,MAAM;AACd,QAAKqG;AAIL,oBAAO,iBAAiB,WAAWM,CAAa,GAEzC,MAAM;AACX,eAAO,oBAAoB,WAAWA,CAAa;AAAA,MACrD;AAAA,EACF,GAAG,CAACN,GAASM,CAAa,CAAC;AAC7B;AC1GO,SAASM,GACdxB,GACAP,GACAgC,GACAC,GACM;AACN,EAAAnH,EAAU,MAAM;AAEd,UAAMoH,IAAmBlC,EAAO;AAAA,MAC9B;AAAA,MACA,CAAC0B,MAAU;AACT,QAAIA,EAAM,QAAQ,YAAYnB,KAC5ByB,EAAA;AAAA,MAEJ;AAAA,IAAA;AAIF,QAAIG;AACJ,WAAIF,MACFE,IAAkBnC,EAAO;AAAA,MACvB;AAAA,MACA,CAAC0B,MAAU;AACT,QAAIA,EAAM,QAAQ,YAAYnB,KAC5B0B,EAAA;AAAA,MAEJ;AAAA,IAAA,IAIG,MAAM;AACX,MAAAC,EAAA,GACAC,KAAA,QAAAA;AAAA,IACF;AAAA,EACF,GAAG,CAAC5B,GAASP,GAAQgC,GAASC,CAAM,CAAC;AACvC;ACnDO,MAAMG,KAAgD,CAAC;AAAA,EAC5D,WAAAnB;AAAA,EACA,WAAAoB,IAAY;AAAA,EACZ,OAAAC,IAAQ,CAAA;AACV,MAAM;AACJ,MAAI,CAACrB;AACH,WAAO;AAGT,QAAMsB,IAAqC;AAAA,IACzC,UAAU;AAAA,IACV,KAAK;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,eAAe;AAAA,IACf,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,GAAGD;AAAA,EAAA;AAGL,SACE,gBAAAE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,yBAAyBH,CAAS;AAAA,MAC7C,OAAOE;AAAA,MACP,MAAK;AAAA,MACL,eAAY;AAAA,IAAA;AAAA,EAAA;AAGlB,GCvCaE,KAA4C,CAAC;AAAA,EACxD,OAAAC;AAAA,EACA,UAAAC;AAAA,EACA,aAAAC,IAAc;AAAA,EACd,SAAAC;AAAA,EACA,SAAAC;AACF,MAAM;AACJ,QAAM,EAAE,OAAAC,EAAA,IAAUC,EAAA,GACZC,IAAWvI,EAAyB,IAAI;AAG9C,EAAAI,EAAU,MAAM;AACd,IAAImI,EAAS,WACXA,EAAS,QAAQ,MAAA;AAAA,EAErB,GAAG,CAAA,CAAE;AAGL,QAAMxB,IAAgB,CAACyB,MAA6C;AAClE,YAAQA,EAAE,KAAA;AAAA,MACR,KAAK;AACH,QAAAA,EAAE,eAAA,GACFJ,KAAA,QAAAA;AACA;AAAA,MACF,KAAK;AACH,QAAAI,EAAE,eAAA,GACFL,EAAA;AACA;AAAA,IAAA;AAAA,EAEN;AAEA,SACE,gBAAAL;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,OAAO;AAAA,QACL,SAAS;AAAA,QACT,cAAc,aAAaO,EAAM,OAAO,MAAM;AAAA,QAC9C,iBAAiBA,EAAM,OAAO;AAAA,MAAA;AAAA,MAGhC,UAAA,gBAAAP;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,KAAKS;AAAA,UACL,MAAK;AAAA,UACL,OAAAP;AAAA,UACA,UAAU,CAACQ,MAAMP,EAASO,EAAE,OAAO,KAAK;AAAA,UACxC,WAAWzB;AAAA,UACX,aAAAmB;AAAA,UACA,OAAO;AAAA,YACL,OAAO;AAAA,YACP,SAAS;AAAA,YACT,UAAU;AAAA,YACV,YAAYG,EAAM,MAAM;AAAA,YACxB,iBAAiB;AAAA,YACjB,QAAQ;AAAA,YACR,SAAS;AAAA,YACT,OAAOA,EAAM,OAAO;AAAA,YACpB,YAAYA,EAAM,OAAO;AAAA,UAAA;AAAA,UAE3B,cAAa;AAAA,UACb,aAAY;AAAA,UACZ,gBAAe;AAAA,UACf,YAAY;AAAA,QAAA;AAAA,MAAA;AAAA,IACd;AAAA,EAAA;AAGN,GChEaI,IAAcC;AAAA,EACzB,CAAC,EAAE,SAAAC,GAAS,YAAAC,GAAY,SAAAC,GAAS,cAAAC,EAAA,GAAgBC,MAAQ;AACvD,UAAM,EAAE,OAAAV,EAAA,IAAUC,EAAA,GACZ,EAAE,OAAAU,GAAO,aAAAC,GAAa,MAAAC,GAAM,UAAAC,MAAaR,GACzC,CAACS,GAAWC,CAAY,IAAIC,EAAM,SAAS,EAAK;AAEtD,WACE,gBAAAC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAR;AAAA,QACA,SAAAF;AAAA,QACA,cAAc,MAAM;AAClB,UAAAQ,EAAa,EAAI,GACjBP,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAMO,EAAa,EAAK;AAAA,QACtC,OAAO;AAAA,UACL,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,iBAAiBT,KAAcQ,IAC3Bf,EAAM,OAAO,sBACb;AAAA,UACJ,YAAYO,KAAcQ,IACtB,aAAaf,EAAM,OAAO,OAAO,KACjC;AAAA,UACJ,YAAY;AAAA,UACZ,SAAS;AAAA,UACT,YAAY;AAAA,UACZ,KAAK;AAAA,QAAA;AAAA,QAEP,aAAa,CAACG,MAAM;AAElB,UAAAA,EAAE,eAAA;AAAA,QACJ;AAAA,QAGC,UAAA;AAAA,UAAAU,KACC,gBAAApB;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO;AAAA,gBACL,YAAY;AAAA,gBACZ,OAAO;AAAA,gBACP,QAAQ;AAAA,gBACR,SAAS;AAAA,gBACT,YAAY;AAAA,gBACZ,gBAAgB;AAAA,gBAChB,UAAU;AAAA,gBACV,OAAOc,KAAcQ,IAAYf,EAAM,OAAO,UAAUA,EAAM,OAAO;AAAA,cAAA;AAAA,cAGtE,UAA2Ba;AAAA,YAAO;AAAA,UAAA;AAAA,UAKvC,gBAAAK,EAAC,SAAI,OAAO,EAAE,MAAM,GAAG,UAAU,KAC/B,UAAA;AAAA,YAAA,gBAAAzB;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,OAAO;AAAA,kBACL,UAAU;AAAA,kBACV,YAAY;AAAA,kBACZ,OAAOc,KAAcQ,IAAYf,EAAM,OAAO,OAAOA,EAAM,OAAO;AAAA,kBAClE,cAAcY,IAAc,QAAQ;AAAA,gBAAA;AAAA,gBAGrC,UAAAD;AAAA,cAAA;AAAA,YAAA;AAAA,YAEFC,KACC,gBAAAnB;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,OAAO;AAAA,kBACL,UAAU;AAAA,kBACV,OAAOO,EAAM,OAAO;AAAA,kBACpB,UAAU;AAAA,kBACV,cAAc;AAAA,kBACd,YAAY;AAAA,gBAAA;AAAA,gBAGb,UAAAY;AAAA,cAAA;AAAA,YAAA;AAAA,UACH,GAEJ;AAAA,UAGCE,KACC,gBAAArB;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO;AAAA,gBACL,YAAY;AAAA,gBACZ,UAAU;AAAA,gBACV,OAAOO,EAAM,OAAO;AAAA,gBACpB,SAAS;AAAA,gBACT,iBAAiBA,EAAM,OAAO;AAAA,gBAC9B,QAAQ,aAAaA,EAAM,OAAO,MAAM;AAAA,gBACxC,cAAc;AAAA,gBACd,YAAYA,EAAM,MAAM;AAAA,cAAA;AAAA,cAGzB,UAAAc;AAAA,YAAA;AAAA,UAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEAV,EAAY,cAAc;ACnGnB,MAAMe,KAA0C,CAAC;AAAA,EACtD,UAAAC;AAAA,EACA,eAAAC;AAAA,EACA,UAAAC;AAAA,EACA,SAAAC;AAAA,EACA,YAAAC,IAAa;AACf,MAAM;AACJ,QAAM,EAAE,OAAAxB,EAAA,IAAUC,EAAA,GACZwB,IAAU9J,EAAuB,IAAI,GACrC+J,IAAkB/J,EAAuB,IAAI,GAG7CgK,IAAoBP,EAAS,MAAM,GAAGI,CAAU;AAGtD,EAAAzJ,EAAU,MAAM;AACd,QAAI2J,EAAgB,WAAWD,EAAQ,SAAS;AAC9C,YAAMG,IAAOF,EAAgB,SACvBG,IAAYJ,EAAQ,SAEpBK,IAAUF,EAAK,WACfG,IAAaD,IAAUF,EAAK,cAC5BI,IAAqBH,EAAU,WAC/BI,IAAkBJ,EAAU;AAGlC,MAAIC,IAAUE,IAEZH,EAAU,YAAYC,IAAU,IACvBC,IAAaC,IAAqBC,MAE3CJ,EAAU,YAAYE,IAAaE,IAAkB;AAAA,IAEzD;AAAA,EACF,GAAG,CAACZ,CAAa,CAAC;AAGlB,QAAMa,IAAkBP,EAAkB,OAAO,CAACQ,GAAK7B,GAAS8B,MAAU;AACxE,UAAMC,IAAW/B,EAAQ,YAAY;AACrC,WAAK6B,EAAIE,CAAQ,MACfF,EAAIE,CAAQ,IAAI,CAAA,IAElBF,EAAIE,CAAQ,EAAE,KAAK,EAAE,SAAA/B,GAAS,OAAA8B,GAAO,GAC9BD;AAAA,EACT,GAAG,CAAA,CAAgE,GAG7DG,IAAa,OAAO,KAAKJ,CAAe,EAAE,KAAK,CAACK,GAAGC,MAEnDD,MAAM,UAAgB,IACtBC,MAAM,UAAgB,KACnBD,EAAE,cAAcC,CAAC,CACzB;AAED,SACE,gBAAAtB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAKO;AAAA,MACL,OAAO;AAAA,QACL,WAAW;AAAA,QACX,WAAW;AAAA,QACX,SAAS;AAAA,MAAA;AAAA,MAGV,UAAA;AAAA,QAAAa,EAAW,IAAI,CAACD,MACf,gBAAAnB,EAAC,OAAA,EAEE,UAAA;AAAA,UAAAoB,EAAW,SAAS,KACnB,gBAAA7C;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO;AAAA,gBACL,SAAS;AAAA,gBACT,UAAU;AAAA,gBACV,YAAY;AAAA,gBACZ,eAAe;AAAA,gBACf,OAAOO,EAAM,OAAO;AAAA,gBACpB,eAAe;AAAA,cAAA;AAAA,cAGhB,UAAAqC;AAAA,YAAA;AAAA,UAAA;AAAA,UAKJH,EAAgBG,CAAQ,EAAE,IAAI,CAAC,EAAE,SAAA/B,GAAS,OAAA8B,QACzC,gBAAA3C;AAAA,YAACW;AAAA,YAAA;AAAA,cAEC,SAAAE;AAAA,cACA,YAAY8B,MAAUf;AAAA,cACtB,SAAS,MAAMC,EAAShB,CAAO;AAAA,cAC/B,cAAc,MAAMiB,EAAQa,CAAK;AAAA,cACjC,KAAKA,MAAUf,IAAgBK,IAAkB;AAAA,YAAA;AAAA,YAL5CpB,EAAQ;AAAA,UAAA,CAOhB;AAAA,QAAA,EAAA,GA3BO+B,CA4BV,CACD;AAAA,QAGAjB,EAAS,SAASI,KACjB,gBAAAN;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,OAAO;AAAA,cACL,SAAS;AAAA,cACT,UAAU;AAAA,cACV,OAAOlB,EAAM,OAAO;AAAA,cACpB,WAAW;AAAA,cACX,WAAW,aAAaA,EAAM,OAAO,MAAM;AAAA,YAAA;AAAA,YAE9C,UAAA;AAAA,cAAA;AAAA,cACUwB;AAAA,cAAW;AAAA,cAAKJ,EAAS;AAAA,cAAO;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MAC3C;AAAA,IAAA;AAAA,EAAA;AAIR,GCtHaqB,KAAgD,CAAC;AAAA,EAC5D,gBAAAC;AAAA,EACA,QAAAC;AACF,MAAM;AACJ,QAAM,EAAE,OAAA3C,EAAA,IAAUC,EAAA,GACZ2C,IAAejL,EAAuB,IAAI,GAC1C;AAAA,IACJ,QAAAkL;AAAA,IACA,OAAAC;AAAA,IACA,OAAAC;AAAA,IACA,UAAAC;AAAA,IACA,kBAAAC;AAAA,IACA,eAAA5B;AAAA,IACA,kBAAA6B;AAAA,IACA,iBAAAC;AAAA,EAAA,IACET;AAwBJ,MArBA3K,EAAU,MAAM;AACd,QAAI,CAAC8K,EAAQ;AAEb,UAAMO,IAAqB,CAACjD,MAAkB;AAC5C,MAAIyC,EAAa,WAAW,CAACA,EAAa,QAAQ,SAASzC,EAAE,MAAc,KACzE2C,EAAA;AAAA,IAEJ,GAGMO,IAAY,WAAW,MAAM;AACjC,eAAS,iBAAiB,aAAaD,CAAkB;AAAA,IAC3D,GAAG,GAAG;AAEN,WAAO,MAAM;AACX,mBAAaC,CAAS,GACtB,SAAS,oBAAoB,aAAaD,CAAkB;AAAA,IAC9D;AAAA,EACF,GAAG,CAACP,GAAQC,CAAK,CAAC,GAGd,CAACD;AACH,WAAO;AAGT,QAAMS,KAAYX,KAAA,gBAAAA,EAAQ,cAAa,QACjC9C,KAAc8C,KAAA,gBAAAA,EAAQ,gBAAe;AAE3C,SACE,gBAAAzB,EAAAqC,GAAA,EAEE,UAAA;AAAA,IAAA,gBAAA9D;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,OAAO;AAAA,UACL,UAAU;AAAA,UACV,OAAO;AAAA,UACP,iBAAiB;AAAA,UACjB,gBAAgB;AAAA,UAChB,QAAQ;AAAA,QAAA;AAAA,QAEV,SAASqD;AAAA,MAAA;AAAA,IAAA;AAAA,IAIX,gBAAA5B;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAK0B;AAAA,QACL,WAAWD,KAAA,gBAAAA,EAAQ;AAAA,QACnB,OAAO;AAAA,UACL,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,MAAM;AAAA,UACN,OAAO;AAAA,UACP,WAAAW;AAAA,UACA,iBAAiBtD,EAAM,OAAO;AAAA,UAC9B,WAAW,aAAaA,EAAM,OAAO,MAAM;AAAA,UAC3C,WAAWA,EAAM,QAAQ,CAAC;AAAA,UAC1B,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,eAAe;AAAA,UACf,GAAG2C,KAAA,gBAAAA,EAAQ;AAAA,QAAA;AAAA,QAIb,UAAA;AAAA,UAAA,gBAAAzB,EAAC,OAAA,EACC,UAAA;AAAA,YAAA,gBAAAzB;AAAA,cAACC;AAAA,cAAA;AAAA,gBACC,OAAOqD;AAAA,gBACP,UAAUC;AAAA,gBACV,aAAAnD;AAAA,gBACA,SAASiD;AAAA,gBACT,SAASK;AAAA,cAAA;AAAA,YAAA;AAAA,YAIX,gBAAAjC;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,OAAO;AAAA,kBACL,SAAS;AAAA,kBACT,WAAW,aAAalB,EAAM,OAAO,MAAM;AAAA,kBAC3C,SAAS;AAAA,kBACT,KAAK;AAAA,kBACL,UAAU;AAAA,kBACV,OAAOA,EAAM,OAAO;AAAA,kBACpB,iBAAiBA,EAAM,OAAO;AAAA,gBAAA;AAAA,gBAGhC,UAAA;AAAA,kBAAA,gBAAAkB,EAAC,QAAA,EACC,UAAA;AAAA,oBAAA,gBAAAzB,EAAC,SAAI,OAAO,EAAE,SAAS,WAAW,iBAAiBO,EAAM,OAAO,qBAAqB,cAAc,OAAO,QAAQ,aAAaA,EAAM,OAAO,MAAM,GAAA,GAAM,UAAA,SAAK;AAAA,oBAAM;AAAA,kBAAA,GACrK;AAAA,oCACC,QAAA,EACC,UAAA;AAAA,oBAAA,gBAAAP,EAAC,SAAI,OAAO,EAAE,SAAS,WAAW,iBAAiBO,EAAM,OAAO,qBAAqB,cAAc,OAAO,QAAQ,aAAaA,EAAM,OAAO,MAAM,GAAA,GAAM,UAAA,OAAG;AAAA,oBAAM;AAAA,kBAAA,EAAA,CACnK;AAAA,gBAAA;AAAA,cAAA;AAAA,YAAA;AAAA,UACF,GACF;AAAA,UAGCiD,EAAiB,SAAS,KACzB,gBAAAxD;AAAA,YAAC0B;AAAA,YAAA;AAAA,cACC,UAAU8B;AAAA,cACV,eAAA5B;AAAA,cACA,UAAU,CAACf,MAAY;AACrB,gBAAAoC,EAAe,eAAepC,EAAQ,EAAE;AAAA,cAC1C;AAAA,cACA,SAAS4C;AAAA,cACT,YAAYP,KAAA,gBAAAA,EAAQ;AAAA,YAAA;AAAA,UAAA;AAAA,UAKvBI,KAASE,EAAiB,WAAW,KACpC,gBAAA/B;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO;AAAA,gBACL,SAAS;AAAA,gBACT,OAAOlB,EAAM,OAAO;AAAA,gBACpB,WAAW;AAAA,gBACX,UAAU;AAAA,cAAA;AAAA,cAEb,UAAA;AAAA,gBAAA;AAAA,gBACyB+C;AAAA,gBAAM;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QAChC;AAAA,MAAA;AAAA,IAAA;AAAA,EAEJ,GACF;AAEJ;AC/IO,MAAMS,EAAuB;AAAA,EAA7B;AACG,IAAA7M,EAAA,sCAAqC,IAAA;AACrC,IAAAA,EAAA,uCAAiC,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMzC,iBAAiByK,GAA2B;AAC1C,IAAAA,EAAS,QAAQ,CAACd,MAAY;AAC5B,WAAK,SAAS,IAAIA,EAAQ,IAAIA,CAAO;AAAA,IACvC,CAAC,GACD,KAAK,gBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgBA,GAAwB;AACtC,SAAK,SAAS,IAAIA,EAAQ,IAAIA,CAAO,GACrC,KAAK,gBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,mBAAmBmD,GAA4B;AAC7C,IAAAA,EAAW,QAAQ,CAACvJ,MAAO;AACzB,WAAK,SAAS,OAAOA,CAAE;AAAA,IACzB,CAAC,GACD,KAAK,gBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kBAAkBwJ,GAAyB;AACzC,SAAK,SAAS,OAAOA,CAAS,GAC9B,KAAK,gBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAAYC,GAAqC;AAC/C,UAAMC,IAAc,MAAM,KAAK,KAAK,SAAS,QAAQ;AAErD,WAAKD,IAKEC,EAAY,OAAO,CAACtD,MACpBA,EAAQ,cAGNA,EAAQ,YAAYqD,CAAO,IAFzB,EAGV,IATQC;AAAA,EAUX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAWF,GAAwC;AACjD,WAAO,KAAK,SAAS,IAAIA,CAAS;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,eAAeA,GAAmBC,GAAwC;;AAC9E,UAAMrD,IAAU,KAAK,SAAS,IAAIoD,CAAS;AAC3C,QAAI,CAACpD,GAAS;AACZ,cAAQ,KAAK,sBAAsBoD,CAAS,EAAE;AAC9C;AAAA,IACF;AAGA,QAAIpD,EAAQ,eAAe,CAACA,EAAQ,YAAYqD,CAAO,GAAG;AACxD,cAAQ,KAAK,0BAA0BD,CAAS,EAAE;AAClD;AAAA,IACF;AAEA,QAAI;AACF,YAAMpD,EAAQ,QAAQqD,CAAO,IAG7BE,IAAAF,EAAQ,WAAR,QAAAE,EAAgB,KAAK;AAAA,QACnB,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,WAAW,KAAK,IAAA;AAAA,QAChB,SAAS;AAAA,UACP,WAAWvD,EAAQ;AAAA,UACnB,cAAcA,EAAQ;AAAA,QAAA;AAAA,MACxB;AAAA,IAEJ,SAASxJ,GAAO;AACd,cAAQ,MAAM,2BAA2B4M,CAAS,KAAK5M,CAAK,IAG5DgN,IAAAH,EAAQ,WAAR,QAAAG,EAAgB,KAAK;AAAA,QACnB,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,WAAW,KAAK,IAAA;AAAA,QAChB,SAAS;AAAA,UACP,WAAWxD,EAAQ;AAAA,UACnB,OAAOxJ,aAAiB,QAAQA,EAAM,UAAU,OAAOA,CAAK;AAAA,QAAA;AAAA,MAC9D;AAAA,IAEJ;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,eAAeiM,GAAeY,GAAqC;AACjE,UAAMI,IAAoB,KAAK,YAAYJ,CAAO;AAElD,QAAI,CAACZ,EAAM;AACT,aAAO,KAAK,aAAagB,CAAiB;AAG5C,UAAMC,IAAajB,EAAM,YAAA;AAgDzB,WA7CegB,EAAkB,IAAI,CAACzD,MAAY;;AAChD,UAAI2D,IAAQ;AAGZ,aAAI3D,EAAQ,MAAM,YAAA,MAAkB0D,IAClCC,KAAS,MAGF3D,EAAQ,MAAM,cAAc,WAAW0D,CAAU,IACxDC,KAAS,MAGF3D,EAAQ,MAAM,cAAc,SAAS0D,CAAU,MACtDC,KAAS,OAIPJ,IAAAvD,EAAQ,gBAAR,QAAAuD,EAAqB,cAAc,SAASG,OAC9CC,KAAS,MAIP3D,EAAQ,YACWA,EAAQ,SAAS;AAAA,QAAK,CAAC4D,MAC1CA,EAAQ,YAAA,EAAc,SAASF,CAAU;AAAA,MAAA,MAGzCC,KAAS,OAKTH,IAAAxD,EAAQ,aAAR,QAAAwD,EAAkB,cAAc,SAASE,OAC3CC,KAAS,KAIPA,IAAQ,KAAK3D,EAAQ,aACvB2D,KAAS3D,EAAQ,WAGZ,EAAE,SAAAA,GAAS,OAAA2D,EAAA;AAAA,IACpB,CAAC,EAIE,OAAO,CAACrC,MAASA,EAAK,QAAQ,CAAC,EAC/B,KAAK,CAACW,GAAGC,MAAMA,EAAE,QAAQD,EAAE,KAAK,EAChC,IAAI,CAACX,MAASA,EAAK,OAAO;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,aAAaR,GAAgC;AACnD,WAAOA,EAAS,KAAK,CAACmB,GAAGC,MAAM;AAE7B,YAAM2B,KAAgB3B,EAAE,YAAY,MAAMD,EAAE,YAAY;AACxD,UAAI4B,MAAiB;AACnB,eAAOA;AAIT,YAAMC,IAAY7B,EAAE,YAAY,IAC1B8B,IAAY7B,EAAE,YAAY,IAC1B8B,IAAeF,EAAU,cAAcC,CAAS;AACtD,aAAIC,MAAiB,IACZA,IAIF/B,EAAE,MAAM,cAAcC,EAAE,KAAK;AAAA,IACtC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,UAAU+B,GAAkC;AAC1C,gBAAK,UAAU,IAAIA,CAAQ,GACpB,MAAM;AACX,WAAK,UAAU,OAAOA,CAAQ;AAAA,IAChC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,SAAS,MAAA,GACd,KAAK,gBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,OAAe;AACjB,WAAO,KAAK,SAAS;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAwB;AAC9B,SAAK,UAAU,QAAQ,CAACA,MAAaA,GAAU;AAAA,EACjD;AACF;AAGA,IAAIC,IAAgD;AAM7C,SAASC,KAAmD;AACjE,SAAKD,MACHA,IAAiB,IAAIhB,EAAA,IAEhBgB;AACT;AAKO,SAASE,KAAmC;AACjD,EAAAF,IAAiB;AACnB;ACvPO,SAASG,GAAkB;AAAA,EAChC,SAAAhB;AAAA,EACA,UAAUiB,IAAkB,CAAA;AAAA,EAC5B,UAAAC,IAAW,EAAE,KAAK,KAAK,QAAQ,GAAA;AAAA,EAC/B,QAAAlC,IAAS,CAAA;AAAA,EACT,UAAUmC;AACZ,GAAoD;AAClD,QAAM,CAACjC,GAAQkC,CAAS,IAAIxN,EAAS,EAAK,GACpC,CAACwL,GAAOC,CAAQ,IAAIzL,EAAS,EAAE,GAC/B,CAAC8J,GAAe6B,CAAgB,IAAI3L,EAAS,CAAC,GAC9C,CAACyN,GAAoBC,CAAqB,IAAI1N,EAAoB,CAAA,CAAE,GAGpE2N,IAAWC;AAAA,IACf,MAAML,KAAoB,IAAItB,EAAA;AAAA,IAC9B,CAACsB,CAAgB;AAAA,EAAA,GAIbM,IAAiBD;AAAA,IACrB,OAAO;AAAA,MACL,GAAGxB;AAAA,MACH,qBAAqB,MAAMoB,EAAU,EAAK;AAAA,IAAA;AAAA,IAE5C,CAACpB,CAAO;AAAA,EAAA;AAIV,EAAA5L,EAAU,MAAM;AACd,QAAIsN,IAAe;AAGnB,UAAMC,IAAcJ,EAAS,UAAU,MAAM;AAC3C,UAAIG,GAAc;AAChB,cAAME,IAAkBL,EAAS,YAAYE,CAAc;AAC3D,QAAAH,EAAsBM,CAAe;AAAA,MACvC;AAAA,IACF,CAAC;AAGD,QAAIX,EAAgB,SAAS;AAC3B,MAAAM,EAAS,iBAAiBN,CAAe;AAAA,SACpC;AAEL,YAAMxD,IAAW8D,EAAS,YAAYE,CAAc;AACpD,MAAAH,EAAsB7D,CAAQ;AAAA,IAChC;AAEA,WAAO,MAAM;AACX,MAAAiE,IAAe,IACfC,EAAA;AAAA,IACF;AAAA,EAEF,GAAG,CAACJ,CAAQ,CAAC;AAGb,QAAMjC,IAAmBkC,EAAQ,OAC3BxC,EAAO,gBAAgB,IAElBuC,EAAS,eAAenC,GAAOqC,CAAc,IAKrD,CAACrC,GAAOmC,GAAUE,GAAgBzC,EAAO,WAAW,CAAC;AAGxD,EAAA5K,EAAU,MAAM;AACd,IAAAmL,EAAiB,CAAC;AAAA,EACpB,GAAG,CAACD,CAAgB,CAAC;AAGrB,QAAMuC,IAAOtN,EAAY,MAAM;;AAC7B,IAAA6M,EAAU,EAAI,GACd/B,EAAS,EAAE,GACXE,EAAiB,CAAC,IAGlBW,IAAAF,EAAQ,WAAR,QAAAE,EAAgB,KAAK;AAAA,MACnB,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,WAAW,KAAK,IAAA;AAAA,MAChB,SAAS,CAAA;AAAA,IAAC;AAAA,EAEd,GAAG,CAACF,EAAQ,MAAM,CAAC,GAGbb,IAAQ5K,EAAY,MAAM;;AAC9B,IAAA6M,EAAU,EAAK,GACf/B,EAAS,EAAE,GACXE,EAAiB,CAAC,IAGlBW,IAAAF,EAAQ,WAAR,QAAAE,EAAgB,KAAK;AAAA,MACnB,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,WAAW,KAAK,IAAA;AAAA,MAChB,SAAS,CAAA;AAAA,IAAC;AAAA,EAEd,GAAG,CAACF,EAAQ,MAAM,CAAC,GAGb8B,IAASvN,EAAY,MAAM;AAC/B,IAAI2K,IACFC,EAAA,IAEA0C,EAAA;AAAA,EAEJ,GAAG,CAAC3C,GAAQ2C,GAAM1C,CAAK,CAAC,GAGlB4C,IAAiBxN;AAAA,IACrB,OAAOwL,MAAsB;AAC3B,YAAMwB,EAAS,eAAexB,GAAW0B,CAAc,GACvDtC,EAAA;AAAA,IACF;AAAA,IACA,CAACoC,GAAUE,GAAgBtC,CAAK;AAAA,EAAA,GAI5B6C,IAAazN,EAAY,MAAM;AACnC,IAAAgL,EAAiB,CAAC0C,MAAS;AACzB,YAAMpE,IAAamB,EAAO,cAAcM,EAAiB,QACnD4C,IAAW,KAAK,IAAI5C,EAAiB,QAAQzB,CAAU,IAAI;AACjE,aAAOoE,IAAOC,IAAWD,IAAO,IAAI;AAAA,IACtC,CAAC;AAAA,EACH,GAAG,CAAC3C,EAAiB,QAAQN,EAAO,UAAU,CAAC,GAGzCmD,IAAiB5N,EAAY,MAAM;AACvC,IAAAgL,EAAiB,CAAC0C,MAAS;AACzB,YAAMpE,IAAamB,EAAO,cAAcM,EAAiB,QACnD4C,IAAW,KAAK,IAAI5C,EAAiB,QAAQzB,CAAU,IAAI;AACjE,aAAOoE,IAAO,IAAIA,IAAO,IAAIC;AAAA,IAC/B,CAAC;AAAA,EACH,GAAG,CAAC5C,EAAiB,QAAQN,EAAO,UAAU,CAAC,GAGzCQ,IAAkBjL,EAAY,YAAY;AAE9C,UAAM6N,IAAe9C,EAAiB,CAAC;AAEvC,IAAI8C,KACF,MAAML,EAAeK,EAAa,EAAE;AAAA,EAExC,GAAG,CAAC9C,GAAkByC,CAAc,CAAC,GAG/BM,IAAmB9N;AAAA,IACvB,CAACkJ,MAAwB;AACvB,MAAA8D,EAAS,iBAAiB9D,CAAQ;AAAA,IACpC;AAAA,IACA,CAAC8D,CAAQ;AAAA,EAAA,GAILe,IAAqB/N;AAAA,IACzB,CAACuL,MAAyB;AACxB,MAAAyB,EAAS,mBAAmBzB,CAAU;AAAA,IACxC;AAAA,IACA,CAACyB,CAAQ;AAAA,EAAA,GAILxG,IAAgBxG;AAAA,IACpB,CAACiI,MAAqB;AACpB,YAAM;AAAA,QACJ,KAAAvG,IAAM;AAAA,QACN,QAAAsM,IAAS;AAAA,QACT,SAAAC,IAAU;AAAA,QACV,SAAAC,IAAU;AAAA,QACV,UAAAC,IAAW;AAAA,MAAA,IACTxB,GAGEyB,IACJnG,EAAE,WAAW+F,KACb/F,EAAE,YAAYgG,KACdhG,EAAE,YAAYiG,KACdjG,EAAE,aAAakG;AAKjB,WAFmBzM,MAAQ,MAAMuG,EAAE,SAAS,UAAUA,EAAE,QAAQvG,MAE9C0M,GAAgB;AAEhC,cAAMC,IAASpG,EAAE;AACjB,YACEoG,EAAO,YAAY,WACnBA,EAAO,YAAY,cACnBA,EAAO;AAEP;AAGF,QAAApG,EAAE,eAAA,GACFsF,EAAA;AAAA,MACF;AAAA,IACF;AAAA,IACA,CAACZ,GAAUY,CAAM;AAAA,EAAA;AAGnB,SAAA1N,EAAU,OACR,OAAO,iBAAiB,WAAW2G,CAAa,GACzC,MAAM,OAAO,oBAAoB,WAAWA,CAAa,IAC/D,CAACA,CAAa,CAAC,GAEX;AAAA,IACL,QAAAmE;AAAA,IACA,MAAA2C;AAAA,IACA,OAAA1C;AAAA,IACA,QAAA2C;AAAA,IACA,OAAA1C;AAAA,IACA,UAAAC;AAAA,IACA,kBAAAC;AAAA,IACA,gBAAAyC;AAAA,IACA,eAAArE;AAAA,IACA,kBAAA6B;AAAA,IACA,YAAAyC;AAAA,IACA,gBAAAG;AAAA,IACA,iBAAA3C;AAAA,IACA,UAAU6B;AAAA,IACV,kBAAAgB;AAAA,IACA,oBAAAC;AAAA,EAAA;AAEJ;ACvPO,MAAMO,KAA2B;AAAA,EACtC;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU,CAAC,QAAQ,WAAW,SAAS,QAAQ;AAAA,IAC/C,SAAS,CAAC7C,MAAY;AACpB,MAAAA,EAAQ,SAAS,MAAM;AAAA,IACzB;AAAA,IACA,aAAa,CAACA,MAAYA,EAAQ,iBAAiB;AAAA,EAAA;AAAA,EAErD;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU,CAAC,UAAU,UAAU,QAAQ,SAAS,QAAQ;AAAA,IACxD,SAAS,CAACA,MAAY;AACpB,MAAAA,EAAQ,SAAS,QAAQ;AAAA,IAC3B;AAAA,IACA,aAAa,CAACA,MAAYA,EAAQ,iBAAiB;AAAA,EAAA;AAAA,EAErD;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU,CAAC,SAAS,WAAW,SAAS,QAAQ;AAAA,IAChD,SAAS,CAACA,MAAY;AACpB,MAAAA,EAAQ,SAAS,OAAO;AAAA,IAC1B;AAAA,IACA,aAAa,CAACA,MAAYA,EAAQ,iBAAiB;AAAA,EAAA;AAAA,EAErD;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,UAAU,CAAC,UAAU,QAAQ,YAAY,UAAU,QAAQ,MAAM;AAAA,IACjE,UAAU;AAAA,IACV,SAAS,CAACA,MAAY;;AACpB,OAAAE,IAAAF,EAAQ,WAAR,QAAAE,EAAgB,KAAK;AAAA,QACnB,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,WAAW,KAAK,IAAA;AAAA,QAChB,SAAS,EAAE,SAAS,OAAA;AAAA,MAAO;AAAA,IAE/B;AAAA,EAAA;AAAA,EAEF;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,UAAU,CAAC,UAAU,SAAS,YAAY,UAAU,QAAQ,MAAM;AAAA,IAClE,UAAU;AAAA,IACV,SAAS,CAACF,MAAY;;AACpB,OAAAE,IAAAF,EAAQ,WAAR,QAAAE,EAAgB,KAAK;AAAA,QACnB,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,WAAW,KAAK,IAAA;AAAA,QAChB,SAAS,EAAE,SAAS,QAAA;AAAA,MAAQ;AAAA,IAEhC;AAAA,EAAA;AAAA,EAEF;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,UAAU,CAAC,YAAY,QAAQ,OAAO,YAAY,YAAY;AAAA,IAC9D,UAAU;AAAA,IACV,SAAS,CAACF,MAAY;;AACpB,OAAAE,IAAAF,EAAQ,WAAR,QAAAE,EAAgB,KAAK;AAAA,QACnB,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,WAAW,KAAK,IAAA;AAAA,QAChB,SAAS,CAAA;AAAA,MAAC;AAAA,IAEd;AAAA,EAAA;AAAA,EAEF;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,UAAU,CAAC,UAAU,QAAQ,OAAO,WAAW,SAAS;AAAA,IACxD,UAAU;AAAA,IACV,SAAS,CAACF,MAAY;;AACpB,OAAAE,IAAAF,EAAQ,WAAR,QAAAE,EAAgB,KAAK;AAAA,QACnB,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,WAAW,KAAK,IAAA;AAAA,QAChB,SAAS,CAAA;AAAA,MAAC;AAAA,IAEd;AAAA,EAAA;AAAA,EAEF;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,UAAU,CAAC,WAAW,UAAU,UAAU,MAAM;AAAA,IAChD,UAAU;AAAA,IACV,SAAS,CAACF,MAAY;;AACpB,YAAMnG,IAAUmG,EAAQ;AACxB,MAAKnG,OAELqG,IAAAF,EAAQ,WAAR,QAAAE,EAAgB,KAAK;AAAA,QACnB,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,WAAW,KAAK,IAAA;AAAA,QAChB,SAAS,EAAE,SAAArG,EAAA;AAAA,MAAQ;AAAA,IAEvB;AAAA,IACA,aAAa,CAACmG,MAAYA,EAAQ,iBAAiB;AAAA,EAAA;AAAA,EAErD;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,UAAU,CAAC,SAAS,UAAU,WAAW,SAAS;AAAA,IAClD,UAAU;AAAA,IACV,SAAS,CAACA,MAAY;;AACpB,OAAAE,IAAAF,EAAQ,WAAR,QAAAE,EAAgB,KAAK;AAAA,QACnB,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,WAAW,KAAK,IAAA;AAAA,QAChB,SAAS,CAAA;AAAA,MAAC;AAAA,IAEd;AAAA,EAAA;AAEJ;AAMO,SAAS4C,KAA8B;AAC5C,SAAOD;AACT;"}