@eclipse-docks/core 0.7.93 → 0.7.95
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/index.js +3 -3
- package/dist/{api-DISr4dl4.js → api-BtDjEaYP.js} +8 -13
- package/dist/{api-DISr4dl4.js.map → api-BtDjEaYP.js.map} +1 -1
- package/dist/core/constants.d.ts +2 -0
- package/dist/core/constants.d.ts.map +1 -1
- package/dist/core/extensionregistry.d.ts +0 -1
- package/dist/core/extensionregistry.d.ts.map +1 -1
- package/dist/externals/webawesome.js +1 -1
- package/dist/index.js +3 -3
- package/dist/parts/index.js +1 -1
- package/dist/parts/tabs.d.ts +8 -0
- package/dist/parts/tabs.d.ts.map +1 -1
- package/dist/{parts-CKBZls6J.js → parts-BUQx-7Vd.js} +104 -32
- package/dist/parts-BUQx-7Vd.js.map +1 -0
- package/dist/{webawesome-CsYKhg4S.js → webawesome-BIXFq9iK.js} +10 -2
- package/dist/webawesome-BIXFq9iK.js.map +1 -0
- package/package.json +1 -1
- package/src/commands/global.ts +1 -6
- package/src/contributions/default-ui-contributions.ts +1 -1
- package/src/core/constants.ts +3 -0
- package/src/core/extensionregistry.ts +14 -34
- package/src/icons/extensions.svg +17 -0
- package/src/icons/icons.txt +5 -0
- package/src/icons/settings.svg +8 -0
- package/src/layouts/standard-layout.ts +3 -3
- package/src/parts/tabs.ts +94 -8
- package/dist/parts-CKBZls6J.js.map +0 -1
- package/dist/webawesome-CsYKhg4S.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"parts-CKBZls6J.js","names":[],"sources":["../src/core/constants.ts","../src/core/settingsservice.ts","../src/core/taskservice.ts","../src/core/esmsh-service.ts","../src/core/extensionregistry.ts","../src/core/keybindings.ts","../src/parts/element.ts","../src/parts/dialog-content.ts","../src/core/dialogservice.ts","../src/core/filesys/opfs.ts","../src/core/filesys/indexeddb.ts","../src/core/marketplaceregistry.ts","../src/core/apploader.ts","../src/dialogs/prompt-dialog.ts","../src/dialogs/info-dialog.ts","../src/dialogs/confirm-dialog.ts","../src/dialogs/navigable-info-dialog.ts","../src/dialogs/filebrowser-dialog.ts","../src/core/icon-utils.ts","../src/parts/toolbar.ts","../src/components/command.ts","../src/parts/contextmenu.ts","../src/parts/container.ts","../src/parts/part.ts","../src/parts/tabs.ts","../src/parts/resizable-grid.ts"],"sourcesContent":["// Toolbars\nexport const TOOLBAR_MAIN = \"app-toolbars-main\"\nexport const TOOLBAR_MAIN_RIGHT = \"app-toolbars-main-right\"\nexport const TOOLBAR_MAIN_CENTER = \"app-toolbars-main-center\"\nexport const TOOLBAR_BOTTOM = \"app-toolbars-bottom\"\nexport const TOOLBAR_BOTTOM_CENTER = \"app-toolbars-bottom-center\"\nexport const TOOLBAR_BOTTOM_END = \"app-toolbars-bottom-end\"\n\nexport const SYSTEM_VIEWS = \"system-views\"\nexport const SYSTEM_LAYOUTS = \"system.layouts\"\n\n// VS Code-style layout containers\nexport const EDITOR_AREA_MAIN = \"editor-area-main\"\nexport const SIDEBAR_MAIN = \"sidebar-main\"\nexport const SIDEBAR_MAIN_BOTTOM = \"sidebar-main-bottom\"\nexport const SIDEBAR_AUXILIARY = \"sidebar-auxiliary\"\nexport const PANEL_BOTTOM = \"panel-bottom\"\n\nexport const COMMAND_SAVE = \"command-save\"\n\nexport const HIDE_DOT_RESOURCE = false\n\n// Mouse button constants\nexport enum MouseButton {\n LEFT = 0,\n MIDDLE = 1,\n RIGHT = 2,\n BACK = 3,\n FORWARD = 4\n}","import {publish} from \"./events\";\nimport {persistenceService} from \"./persistenceservice\";\nimport {rootContext} from \"./di\";\n\nexport const SETTINGS_FILE_PATH = \".eclipse-docks/settings.json\"\n\nexport const DIALOG_SETTINGS_KEY = \"dialogSettings\"\n\nexport interface AppSettings {\n [key: string]: any;\n}\n\nexport const TOPIC_SETTINGS_CHANGED = \"events/settings/changed\"\n\n/**\n * Minimal JSON Schema subset for settings UI. Compatible with JSON Schema (e.g. from Zod via zod-to-json-schema).\n * Top-level properties = categories; nested properties = settings in that category.\n */\nexport interface SettingsJsonSchema {\n type?: 'object' | 'string' | 'number' | 'boolean' | 'array';\n title?: string;\n description?: string;\n default?: unknown;\n enum?: readonly unknown[] | unknown[];\n properties?: Record<string, SettingsJsonSchema>;\n /** Extension: category sort order (only meaningful on top-level property schemas). */\n order?: number;\n}\n\nexport interface SettingsCategoryInfo {\n id: string;\n label: string;\n order: number;\n schema: SettingsJsonSchema;\n}\n\nfunction mergeSchemaProperties(\n target: Record<string, SettingsJsonSchema>,\n source: Record<string, SettingsJsonSchema> | undefined\n): void {\n if (!source) return;\n for (const [key, value] of Object.entries(source)) {\n if (value && typeof value === 'object') {\n const existing = target[key];\n if (existing?.properties && value.properties) {\n mergeSchemaProperties(existing.properties, value.properties);\n } else {\n target[key] = { ...value, properties: value.properties ? { ...value.properties } : undefined };\n }\n }\n }\n}\n\nclass SettingsService {\n\n private appSettings?: AppSettings;\n\n private mergedSchema: SettingsJsonSchema = { type: 'object', properties: {} };\n\n private async checkSettings() {\n if (!this.appSettings) {\n this.appSettings = await persistenceService.getObject(SETTINGS_FILE_PATH)\n if (!this.appSettings) {\n this.appSettings = {}\n await persistenceService.persistObject(SETTINGS_FILE_PATH, this.appSettings)\n }\n publish(TOPIC_SETTINGS_CHANGED, this.appSettings)\n }\n }\n\n /**\n * Register a JSON Schema for settings. Top-level keys of `schema.properties` become categories.\n * Consumers can pass schemas produced by Zod (e.g. zod-to-json-schema) or hand-written JSON Schema.\n */\n public registerSchema(schema: SettingsJsonSchema): void {\n const props = schema.properties ?? (schema.type === 'object' ? {} : undefined);\n if (props) {\n if (!this.mergedSchema.properties) this.mergedSchema.properties = {};\n mergeSchemaProperties(this.mergedSchema.properties, props);\n }\n }\n\n public getCategories(): SettingsCategoryInfo[] {\n const props = this.mergedSchema.properties;\n if (!props) return [];\n return Object.entries(props)\n .filter(([, s]) => s && typeof s === 'object')\n .map(([id, schema]) => ({\n id,\n label: (schema.title as string) ?? id,\n order: typeof schema.order === 'number' ? schema.order : 0,\n schema,\n }))\n .sort((a, b) => a.order - b.order);\n }\n\n public getSchemaForCategory(categoryId: string): SettingsJsonSchema | undefined {\n return this.mergedSchema.properties?.[categoryId];\n }\n\n /**\n * Resolve a dotted key (e.g. \"editor.fontSize\") to the JSON Schema fragment for that path.\n */\n public getSchemaForSettingKey(dottedKey: string): SettingsJsonSchema | undefined {\n const parts = dottedKey.split('.').filter(Boolean);\n if (parts.length === 0) return this.mergedSchema;\n let current: SettingsJsonSchema | undefined = this.mergedSchema;\n for (const part of parts) {\n current = current?.properties?.[part];\n if (!current) return undefined;\n }\n return current;\n }\n\n private traversePath(obj: Record<string, any>, pathParts: string[], createIfMissing: boolean): { parent: Record<string, any>; key: string } | null {\n if (pathParts.length === 0) return null;\n let current: Record<string, any> = obj;\n const lastIndex = pathParts.length - 1;\n for (let i = 0; i < lastIndex; i++) {\n const part = pathParts[i];\n if (current[part] === undefined) {\n if (!createIfMissing) return null;\n current[part] = {};\n }\n if (current[part] === null || typeof current[part] !== 'object') return null;\n current = current[part];\n }\n return { parent: current, key: pathParts[lastIndex] };\n }\n\n public async getAt(path: string): Promise<unknown> {\n await this.checkSettings();\n const parts = path.split('.').filter(Boolean);\n if (parts.length === 0) return this.appSettings;\n const result = this.traversePath(this.appSettings!, parts, false);\n if (!result) return undefined;\n return result.parent[result.key];\n }\n\n public async setAt(path: string, value: unknown): Promise<void> {\n await this.checkSettings();\n const parts = path.split('.').filter(Boolean);\n if (parts.length === 0) return;\n const result = this.traversePath(this.appSettings!, parts, true);\n if (!result) return;\n result.parent[result.key] = value;\n await persistenceService.persistObject(SETTINGS_FILE_PATH, this.appSettings)\n publish(TOPIC_SETTINGS_CHANGED, this.appSettings)\n }\n\n public async get(key: string) {\n await this.checkSettings()\n return this.appSettings![key]\n }\n\n public async set(key: string, value: any) {\n await this.checkSettings()\n this.appSettings![key] = value\n await persistenceService.persistObject(SETTINGS_FILE_PATH, this.appSettings)\n publish(TOPIC_SETTINGS_CHANGED, this.appSettings)\n }\n\n public async getAll() {\n await this.checkSettings()\n return this.appSettings!;\n }\n\n public async setAll(settings: AppSettings) {\n this.appSettings = settings\n await persistenceService.persistObject(SETTINGS_FILE_PATH, this.appSettings)\n publish(TOPIC_SETTINGS_CHANGED, this.appSettings)\n }\n\n public async getDialogSetting(key: string) {\n await this.checkSettings()\n const dialogSettings = this.appSettings![DIALOG_SETTINGS_KEY] || {}\n return dialogSettings[key]\n }\n\n public async setDialogSetting(key: string, value: any) {\n await this.checkSettings()\n const dialogSettings = this.appSettings![DIALOG_SETTINGS_KEY] || {}\n dialogSettings[key] = value\n this.appSettings![DIALOG_SETTINGS_KEY] = dialogSettings\n await persistenceService.persistObject(SETTINGS_FILE_PATH, this.appSettings)\n publish(TOPIC_SETTINGS_CHANGED, this.appSettings)\n }\n}\n\nexport const appSettings = new SettingsService();\nrootContext.put(\"appSettings\", appSettings)\n","import {activeTasksSignal} from \"./appstate\";\nimport {rootContext} from \"./di\";\n\nexport interface ProgressMonitor {\n name: string\n message: string\n currentStep: number\n totalSteps: number\n progress: number // Manual progress percentage (0-100), overrides step-based calculation if >= 0\n}\n\nexport type Task = (progressMonitor: ProgressMonitor) => any\nexport type AsyncTask = (progressMonitor: ProgressMonitor) => Promise<any>\n\nexport class TaskService {\n private tasks: ProgressMonitor[] = []\n private updateCounter = 0\n\n private notifyUpdate() {\n // Always increment counter to ensure signal value changes and triggers re-render\n this.updateCounter++\n activeTasksSignal.set(this.updateCounter)\n }\n\n public run(name: string, task: Task) {\n const progressMonitor = this.createProgressMonitor(name)\n try {\n this.tasks.push(progressMonitor)\n this.notifyUpdate()\n task(progressMonitor)\n } finally {\n this.tasks.splice(this.tasks.indexOf(progressMonitor), 1)\n this.notifyUpdate()\n }\n }\n\n public async runAsync(name: string, task: AsyncTask) {\n const progressMonitor = this.createProgressMonitor(name)\n this.tasks.push(progressMonitor)\n this.notifyUpdate()\n return task(progressMonitor).finally(() => {\n this.tasks.splice(this.tasks.indexOf(progressMonitor), 1)\n this.notifyUpdate()\n })\n }\n\n private createProgressMonitor(name: string): ProgressMonitor {\n const monitor = {\n name: name,\n message: \"\",\n currentStep: 0,\n totalSteps: -1, // -1 indicates indefinite progress\n progress: -1 // -1 means use step-based calculation\n } as ProgressMonitor\n \n // Create a proxy to detect property changes and trigger UI updates\n return new Proxy(monitor, {\n set: (target, prop, value) => {\n (target as any)[prop] = value\n this.notifyUpdate()\n return true\n }\n })\n }\n\n getActiveTasks() {\n return this.tasks\n }\n}\n\nexport const taskService = new TaskService()\nrootContext.put(\"taskService\", taskService)","import { rootContext } from \"./di\";\nimport { createLogger } from \"./logger\";\n\nconst logger = createLogger('EsmShService');\n\nexport interface EsmShSource {\n type: 'npm' | 'github' | 'jsr' | 'pr';\n package?: string;\n owner?: string;\n repo?: string;\n version?: string;\n path?: string;\n commit?: string;\n}\n\nexport interface EsmShOptions {\n deps?: Record<string, string>;\n target?: string;\n dev?: boolean;\n bundle?: boolean;\n external?: string[];\n externalAll?: boolean;\n}\n\nclass EsmShService {\n private static readonly ESM_SH_BASE = 'https://esm.sh';\n private static readonly GITHUB_PREFIX = 'gh/';\n private static readonly JSR_PREFIX = 'jsr/';\n private static readonly PR_PREFIX = 'pr/';\n\n isEsmShUrl(url: string): boolean {\n try {\n const urlObj = new URL(url);\n return urlObj.hostname === 'esm.sh' || urlObj.hostname === 'raw.esm.sh';\n } catch {\n return false;\n }\n }\n\n isSourceIdentifier(source: string): boolean {\n if (this.isEsmShUrl(source)) {\n return false;\n }\n \n if (this.isHttpUrl(source)) {\n return false;\n }\n\n return this.parseSource(source) !== null;\n }\n\n private isHttpUrl(url: string): boolean {\n try {\n const parsed = new URL(url);\n return parsed.protocol === 'http:' || parsed.protocol === 'https:';\n } catch {\n return false;\n }\n }\n\n parseSource(source: string): EsmShSource | null {\n if (!source || typeof source !== 'string') {\n return null;\n }\n\n source = source.trim();\n\n if (this.isHttpUrl(source)) {\n return null;\n }\n\n if (source.startsWith(EsmShService.GITHUB_PREFIX)) {\n return this.parseGitHubSource(source);\n }\n\n if (source.startsWith(EsmShService.JSR_PREFIX)) {\n return this.parseJsrSource(source);\n }\n\n if (source.startsWith(EsmShService.PR_PREFIX)) {\n return this.parsePrSource(source);\n }\n\n return this.parseNpmSource(source);\n }\n\n private parseGitHubSource(source: string): EsmShSource | null {\n const withoutPrefix = source.substring(EsmShService.GITHUB_PREFIX.length);\n const parts = withoutPrefix.split('/');\n \n if (parts.length < 2) {\n return null;\n }\n\n const owner = parts[0];\n const repoWithRef = parts[1];\n \n let repo: string;\n let version: string | undefined;\n let path: string | undefined;\n\n const refMatch = repoWithRef.match(/^(.+?)(@(.+))?$/);\n if (!refMatch) {\n return null;\n }\n\n repo = refMatch[1];\n version = refMatch[3];\n\n if (parts.length > 2) {\n path = parts.slice(2).join('/');\n }\n\n return {\n type: 'github',\n owner,\n repo,\n version,\n path\n };\n }\n\n private parseJsrSource(source: string): EsmShSource | null {\n const withoutPrefix = source.substring(EsmShService.JSR_PREFIX.length);\n \n if (!withoutPrefix.startsWith('@')) {\n return null;\n }\n\n const parts = withoutPrefix.split('/');\n if (parts.length < 2) {\n return null;\n }\n\n const scope = parts[0];\n const packageWithVersion = parts[1];\n \n let packageName: string;\n let version: string | undefined;\n let path: string | undefined;\n\n const versionMatch = packageWithVersion.match(/^(.+?)(@(.+))?$/);\n if (!versionMatch) {\n return null;\n }\n\n packageName = `${scope}/${versionMatch[1]}`;\n version = versionMatch[3];\n\n if (parts.length > 2) {\n path = parts.slice(2).join('/');\n }\n\n return {\n type: 'jsr',\n package: packageName,\n version,\n path\n };\n }\n\n private parsePrSource(source: string): EsmShSource | null {\n const withoutPrefix = source.substring(EsmShService.PR_PREFIX.length);\n const parts = withoutPrefix.split('/');\n \n if (parts.length < 2) {\n return null;\n }\n\n const owner = parts[0];\n const repoWithCommit = parts[1];\n \n let repo: string;\n let commit: string | undefined;\n\n const commitMatch = repoWithCommit.match(/^(.+?)@(.+)$/);\n if (commitMatch) {\n repo = commitMatch[1];\n commit = commitMatch[2];\n } else {\n repo = repoWithCommit;\n }\n\n return {\n type: 'pr',\n owner,\n repo,\n commit\n };\n }\n\n private parseNpmSource(source: string): EsmShSource | null {\n const parts = source.split('/');\n const firstPart = parts[0];\n \n let packageName: string;\n let version: string | undefined;\n let path: string | undefined;\n\n const versionMatch = firstPart.match(/^(.+?)(@(.+))?$/);\n if (!versionMatch) {\n return null;\n }\n\n packageName = versionMatch[1];\n version = versionMatch[3];\n\n if (parts.length > 1) {\n path = parts.slice(1).join('/');\n }\n\n return {\n type: 'npm',\n package: packageName,\n version,\n path\n };\n }\n\n buildEsmShUrl(source: EsmShSource, options?: EsmShOptions): string {\n let url = EsmShService.ESM_SH_BASE;\n\n switch (source.type) {\n case 'npm':\n url += `/${source.package}`;\n if (source.version) {\n url += `@${source.version}`;\n }\n if (source.path) {\n url += `/${source.path}`;\n }\n break;\n\n case 'github':\n url += `/${EsmShService.GITHUB_PREFIX}${source.owner}/${source.repo}`;\n if (source.version) {\n url += `@${source.version}`;\n }\n if (source.path) {\n url += `/${source.path}`;\n }\n break;\n\n case 'jsr':\n url += `/${EsmShService.JSR_PREFIX}${source.package}`;\n if (source.version) {\n url += `@${source.version}`;\n }\n if (source.path) {\n url += `/${source.path}`;\n }\n break;\n\n case 'pr':\n url += `/${EsmShService.PR_PREFIX}${source.owner}/${source.repo}`;\n if (source.commit) {\n url += `@${source.commit}`;\n }\n break;\n }\n\n const queryParams: string[] = [];\n\n if (options?.deps) {\n const depsString = Object.entries(options.deps)\n .map(([pkg, version]) => `${pkg}@${version}`)\n .join(',');\n queryParams.push(`deps=${encodeURIComponent(depsString)}`);\n }\n\n if (options?.target) {\n queryParams.push(`target=${encodeURIComponent(options.target)}`);\n }\n\n if (options?.dev) {\n queryParams.push('dev');\n }\n\n if (options?.bundle === false) {\n queryParams.push('bundle=false');\n } else if (options?.bundle === true) {\n queryParams.push('bundle');\n }\n\n if (queryParams.length > 0) {\n url += `?${queryParams.join('&')}`;\n }\n\n return url;\n }\n\n normalizeToEsmSh(source: string, options?: EsmShOptions): string {\n if (this.isEsmShUrl(source)) {\n return source;\n }\n\n if (this.isHttpUrl(source)) {\n return source;\n }\n\n const parsed = this.parseSource(source);\n if (!parsed) {\n logger.warn(`Could not parse source identifier: ${source}`);\n return source;\n }\n\n return this.buildEsmShUrl(parsed, options);\n }\n\n extractPackageName(source: string): string | null {\n const parsed = this.parseSource(source);\n if (!parsed) {\n return null;\n }\n\n switch (parsed.type) {\n case 'npm':\n return parsed.package || null;\n case 'github':\n return `${parsed.owner}/${parsed.repo}`;\n case 'jsr':\n return parsed.package || null;\n case 'pr':\n return `${parsed.owner}/${parsed.repo}`;\n }\n }\n\n isGitHubUrl(url: string): boolean {\n try {\n const urlObj = new URL(url);\n return urlObj.hostname === 'github.com' || urlObj.hostname === 'www.github.com';\n } catch {\n return url.startsWith('https://github.com/') || url.startsWith('http://github.com/');\n }\n }\n\n convertGitHubUrlToSource(githubUrl: string): string {\n try {\n const urlObj = new URL(githubUrl);\n const pathParts = urlObj.pathname.split('/').filter(p => p);\n \n if (pathParts.length < 2) {\n throw new Error('Invalid GitHub URL format');\n }\n \n const owner = pathParts[0];\n let repo = pathParts[1].replace(/\\.git$/, '');\n let ref: string | undefined;\n let filePath: string | undefined;\n \n if (pathParts.length > 2) {\n if (pathParts[2] === 'blob' || pathParts[2] === 'tree') {\n ref = pathParts[3] || 'main';\n if (pathParts[2] === 'blob' && pathParts.length > 4) {\n filePath = pathParts.slice(4).join('/');\n }\n } else if (pathParts[2] === 'commit') {\n ref = pathParts[3];\n } else {\n filePath = pathParts.slice(2).join('/');\n }\n }\n \n let ghUrl = `${EsmShService.GITHUB_PREFIX}${owner}/${repo}`;\n if (ref) {\n ghUrl += `@${ref}`;\n }\n if (filePath) {\n ghUrl += `/${filePath}`;\n }\n \n return ghUrl;\n } catch {\n const urlMatch = githubUrl.match(/github\\.com\\/([^\\/]+)\\/([^\\/]+)/);\n if (urlMatch) {\n return `${EsmShService.GITHUB_PREFIX}${urlMatch[1]}/${urlMatch[2].replace(/\\.git$/, '')}`;\n }\n return githubUrl;\n }\n }\n\n async fetchGitHubPackageJson(source: EsmShSource): Promise<any> {\n if (source.type !== 'github') {\n throw new Error('Source must be a GitHub source');\n }\n\n const owner = source.owner!;\n const repo = source.repo!;\n const ref = source.version || 'main';\n \n const packageJsonUrl = `https://raw.githubusercontent.com/${owner}/${repo}/${ref}/package.json`;\n \n const response = await fetch(packageJsonUrl);\n if (!response.ok) {\n throw new Error(`Failed to fetch package.json: ${response.statusText}`);\n }\n \n return await response.json();\n }\n}\n\nexport const esmShService = new EsmShService();\nrootContext.put(\"esmShService\", esmShService);","import {appSettings, TOPIC_SETTINGS_CHANGED} from \"./settingsservice\";\nimport {publish, subscribe} from \"./events\";\nimport {toastError, toastInfo} from \"./toast\";\nimport {taskService} from \"./taskservice\";\nimport {rootContext, uiContext} from \"./di\";\nimport logger from \"./logger\";\nimport {esmShService} from \"./esmsh-service\";\n\nexport const TOPIC_EXTENSIONS_CHANGED = \"events/extensionsregistry/extensionsConfigChanged\"\nconst KEY_EXTENSIONS_CONFIG = \"extensions\"\nconst KEY_EXTERNAL_EXTENSIONS = \"extensions.external\"\n\n/**\n * Extension definition for the extension registry.\n * \n * @example\n * ```typescript\n * extensionRegistry.registerExtension({\n * id: \"system.myextension\",\n * name: \"My Extension\",\n * description: \"An example extension\",\n * loader: () => import(\"./my-extension.ts\"),\n * icon: \"puzzle-piece\",\n * dependencies: [\"system.dependency1\", \"system.dependency2\"]\n * })\n * ```\n */\nimport { UILabel } from \"./i18n\";\n\nexport interface Extension {\n /** Unique identifier for the extension (e.g., \"@eclipse-docks/extension-notebook\") */\n id: string;\n \n /** Human-readable name of the extension */\n name: UILabel;\n \n /** Optional description of what the extension does */\n description?: UILabel;\n \n /** Optional URL to load the extension module from */\n url?: string;\n \n /** Function that dynamically imports the extension module */\n loader?: () => any;\n \n /** Optional icon identifier (FontAwesome or custom icon) */\n icon?: string;\n \n /** Whether this extension is marked as experimental */\n experimental?: boolean;\n \n /** Optional extension version */\n version?: string;\n \n /** Optional extension author */\n author?: string;\n \n /** Whether this extension is from an external source (marketplace) */\n external?: boolean;\n \n /**\n * Optional list of extension IDs that must be loaded before this extension.\n * Dependencies are loaded recursively and automatically when this extension is loaded.\n * The system includes circular dependency detection.\n * \n * @example\n * ```typescript\n * dependencies: [\"@eclipse-docks/extension-python-runtime\"]\n * ```\n */\n dependencies?: string[];\n}\n\nexport interface ExtensionSetting {\n id: string;\n enabled: boolean;\n}\n\nexport type ExtensionsConfig = ExtensionSetting[]\n\nclass ExtensionRegistry {\n private extensionsSettings?: ExtensionsConfig;\n private extensions: { [key: string]: Extension } = {}\n private loadedExtensions: Set<string> = new Set()\n private loadingPromises: Map<string, Promise<void>> = new Map()\n\n constructor() {\n subscribe(TOPIC_SETTINGS_CHANGED, () => {\n this.extensionsSettings = undefined\n this.checkExtensionsConfig().then()\n })\n\n // Initialize settings and load metadata for persisted external extensions.\n // Actual extension loading is triggered by the app loader (app.extensions)\n // and explicit calls to enable()/load(), so we avoid eagerly loading any\n // extensions before an app has started.\n this.loadPersistedExternalExtensions().then(() => {\n this.checkExtensionsConfig().then()\n })\n }\n\n private async loadPersistedExternalExtensions(): Promise<void> {\n try {\n const persisted = await appSettings.get(KEY_EXTERNAL_EXTENSIONS)\n if (persisted && Array.isArray(persisted)) {\n persisted.forEach((ext: Extension) => {\n this.extensions[ext.id] = ext\n })\n }\n } catch (error) {\n logger.error(`Failed to load persisted external extensions: ${error}`)\n }\n }\n\n private async savePersistedExternalExtensions(): Promise<void> {\n try {\n const externalExtensions = Object.values(this.extensions).filter(ext => ext.external)\n await appSettings.set(KEY_EXTERNAL_EXTENSIONS, externalExtensions)\n } catch (error) {\n logger.error(`Failed to save persisted external extensions: ${error}`)\n }\n }\n\n private async checkExtensionsConfig() {\n if (!this.extensionsSettings) {\n this.extensionsSettings = await appSettings.get(KEY_EXTENSIONS_CONFIG)\n if (!this.extensionsSettings) {\n await appSettings.set(KEY_EXTENSIONS_CONFIG, [])\n this.extensionsSettings = await appSettings.get(KEY_EXTENSIONS_CONFIG)\n }\n publish(TOPIC_EXTENSIONS_CHANGED, this.extensionsSettings)\n }\n }\n\n\n registerExtension(extension: Extension): void {\n this.extensions[extension.id] = extension;\n logger.debug(`Registered extension: ${extension.id}`);\n\n // Persist external extensions\n if (extension.external) {\n this.savePersistedExternalExtensions().catch(err => {\n logger.error(`Failed to persist external extension: ${err}`)\n })\n }\n \n publish(TOPIC_EXTENSIONS_CHANGED, this.extensionsSettings);\n }\n\n /**\n * Load an extension from a URL and register it.\n * The module at the URL must export a default function that receives uiContext.\n * The extension will register its contributions when loaded.\n * \n * Supports:\n * - Direct URLs (http/https)\n * - esm.sh URLs\n * - Source identifiers (npm packages, GitHub repos, JSR packages, PR packages)\n * Examples: 'react@18', 'gh/user/repo', 'jsr/@std/encoding@1.0.0', 'pr/owner/repo@commit'\n * \n * @param url - URL or source identifier to the extension module\n * @param extensionId - Optional extension ID. If not provided, generates one from the URL.\n * @returns Promise that resolves to the extension ID when the extension is loaded\n */\n async loadExtensionFromUrl(url: string, extensionId?: string): Promise<string> {\n logger.info(`Loading extension from URL: ${url}...`);\n \n try {\n let finalUrl = url;\n let extensionName = `Extension from ${url}`;\n\n if (esmShService.isSourceIdentifier(url)) {\n const packageName = esmShService.extractPackageName(url);\n if (packageName) {\n extensionName = `Extension: ${packageName}`;\n }\n finalUrl = esmShService.normalizeToEsmSh(url);\n logger.debug(`Converted source identifier to esm.sh URL: ${url} -> ${finalUrl}`);\n }\n \n const id = extensionId || `url:${finalUrl}`;\n \n if (this.isEnabled(id)) {\n logger.info(`Extension from URL ${finalUrl} is already enabled`);\n return id;\n }\n \n // Check if extension is already registered\n if (!this.extensions[id]) {\n const extension: Extension = {\n id: id,\n name: extensionName,\n description: `Extension loaded from: ${url}`,\n url: finalUrl\n };\n \n this.registerExtension(extension);\n logger.info(`Registered extension from URL: ${id}`);\n }\n \n this.enable(id, false);\n \n logger.info(`Successfully enabled extension from URL: ${finalUrl}`);\n return id;\n } catch (error) {\n logger.error(`Failed to load extension from URL ${url}: ${error}`);\n throw error;\n }\n }\n\n getExtensions(): Extension[] {\n return Object.values(this.extensions)\n }\n\n /**\n * Load all extensions that are currently marked as enabled in settings.\n * This is intended to be called by the app loader once an app has started,\n * after all extension modules have had a chance to register themselves.\n */\n public async loadEnabledExtensions(): Promise<void> {\n await this.checkExtensionsConfig();\n const settings = this.extensionsSettings ?? [];\n const loadPromises = settings\n // Only attempt to load extensions that are:\n // - marked as enabled, and\n // - already registered in this.extensions (either built-in or persisted external).\n .filter(setting => this.isEnabled(setting.id) && this.extensions[setting.id])\n .map(setting =>\n this.load(setting.id).catch(e => {\n toastError(\"Extension could not be loaded: \" + e.message);\n }),\n );\n\n await Promise.all(loadPromises);\n }\n\n public isEnabled(extensionId: string) {\n this.checkExtensionsConfig()\n return !!this.extensionsSettings?.find((setting) => setting.id === extensionId && setting.enabled)\n }\n\n public isLoaded(extensionId: string) {\n return this.loadedExtensions.has(extensionId)\n }\n\n public enable(extensionId: string, informUser: boolean = false) {\n if (this.isEnabled(extensionId)) {\n return\n }\n logger.debug(`Loading extension: ${extensionId}`)\n this.load(extensionId).then(() => {\n this.updateEnablement(extensionId, true, informUser)\n }).catch(_e => {\n logger.error(`Could not load extension: ${extensionId}: ${_e}`)\n })\n }\n\n /** Like enable() but returns a Promise that resolves when the extension is loaded. Use when the caller must wait for commands/contributions to be registered (e.g. before rendering the app). */\n public async enableAsync(extensionId: string, informUser: boolean = false): Promise<void> {\n if (this.isEnabled(extensionId)) {\n return\n }\n logger.debug(`Loading extension: ${extensionId}`)\n try {\n await this.load(extensionId)\n this.updateEnablement(extensionId, true, informUser)\n } catch (e) {\n logger.error(`Could not load extension: ${extensionId}: ${e}`)\n throw e\n }\n }\n\n /**\n * Loads an extension and all its dependencies.\n * \n * Features:\n * - Automatically loads all dependencies recursively before loading the extension\n * - Ensures each extension is loaded only once (idempotent)\n * - Dependencies are loaded in the order they are declared\n * - If an extension is already being loaded, waits for that load to complete\n * - Detects circular dependencies in the dependency chain\n * \n * @param extensionId - The ID of the extension to load\n * @param loadingChain - Internal parameter to track the dependency chain for circular detection\n * @throws Error if the extension is not found or if a circular dependency is detected\n * \n * @example\n * ```typescript\n * // This will automatically load @eclipse-docks/extension-python-runtime first\n * await extensionRegistry.load('@eclipse-docks/extension-notebook')\n * ```\n */\n public async load(extensionId: string, loadingChain: string[] = []): Promise<void> {\n // Already loaded, return immediately\n if (this.loadedExtensions.has(extensionId)) {\n return\n }\n \n // Currently loading by another call chain, wait for that promise to complete\n const existingPromise = this.loadingPromises.get(extensionId)\n if (existingPromise) {\n return existingPromise\n }\n \n // Check for circular dependency\n if (loadingChain.includes(extensionId)) {\n const chain = [...loadingChain, extensionId].join(' → ')\n throw new Error(`Circular dependency detected: ${chain}`)\n }\n \n const extension = this.extensions[extensionId]\n if (!extension) {\n throw new Error(\"Extension not found: \" + extensionId)\n }\n \n const loadingPromise = (async () => {\n try {\n logger.debug(`Loading extension: ${extensionId}`);\n if (extension.dependencies && extension.dependencies.length > 0) {\n const newChain = [...loadingChain, extensionId]\n for (const depId of extension.dependencies) {\n await this.load(depId, newChain)\n // Enable the dependency if it's not already enabled\n if (!this.isEnabled(depId)) {\n await this.updateEnablementAsync(depId, true, false)\n logger.debug(`Auto-enabled dependency: ${depId}`)\n }\n }\n }\n \n const module = await taskService.runAsync(\"Loading extension: \" + extension.name, async () => {\n if (extension.loader) {\n return extension.loader()\n } else if (extension.url) {\n let finalUrl = extension.url;\n if (esmShService.isSourceIdentifier(extension.url)) {\n finalUrl = esmShService.normalizeToEsmSh(extension.url);\n logger.debug(`Normalized extension URL: ${extension.url} -> ${finalUrl}`);\n }\n return import(/* @vite-ignore */ finalUrl)\n }\n })\n\n // Mark as loaded BEFORE executing the module\n this.loadedExtensions.add(extensionId)\n\n if (module?.default instanceof Function) {\n try {\n module.default(uiContext.getProxy())\n } catch (error) {\n logger.error(`Error executing extension function for ${extensionId}: ${error}`)\n throw error\n }\n }\n \n } catch (error) {\n // If loading failed, remove from loaded set\n this.loadedExtensions.delete(extensionId)\n throw error\n } finally {\n // Always clean up the promise\n this.loadingPromises.delete(extensionId)\n }\n })()\n \n this.loadingPromises.set(extensionId, loadingPromise)\n return loadingPromise\n }\n\n public disable(extensionId: string, informUser: boolean = false) {\n if (!this.isEnabled(extensionId)) {\n return\n }\n this.updateEnablement(extensionId, false, informUser)\n }\n\n private updateEnablement(extensionId: string, enabled: boolean, informUser: boolean) {\n this.checkExtensionsConfig().then(() => {\n const extension = this.extensionsSettings?.find(e => e.id == extensionId)\n if (extension) {\n extension.enabled = enabled\n } else {\n this.extensionsSettings?.push({id: extensionId, enabled: enabled})\n }\n appSettings.set(KEY_EXTENSIONS_CONFIG, this.extensionsSettings).then(() => {\n if (informUser) {\n const extObj = this.extensions[extensionId]\n if (enabled) {\n toastInfo(extObj.name + \" enabled.\")\n } else {\n toastInfo(extObj.name + \" disabled \" + \" - Please restart to take effect\")\n }\n }\n publish(TOPIC_EXTENSIONS_CHANGED, this.extensionsSettings)\n })\n })\n }\n\n private async updateEnablementAsync(extensionId: string, enabled: boolean, informUser: boolean) {\n await this.checkExtensionsConfig()\n const extension = this.extensionsSettings?.find(e => e.id == extensionId)\n if (extension) {\n extension.enabled = enabled\n } else {\n this.extensionsSettings?.push({id: extensionId, enabled: enabled})\n }\n await appSettings.set(KEY_EXTENSIONS_CONFIG, this.extensionsSettings)\n if (informUser) {\n const extObj = this.extensions[extensionId]\n if (enabled) {\n toastInfo(extObj.name + \" enabled.\")\n } else {\n toastInfo(extObj.name + \" disabled \" + \" - Please restart to take effect\")\n }\n }\n publish(TOPIC_EXTENSIONS_CHANGED, this.extensionsSettings)\n }\n}\n\nexport const extensionRegistry = new ExtensionRegistry()\nrootContext.put(\"extensionRegistry\", extensionRegistry)","/**\n * Key Binding Manager for geo!space\n *\n * Handles keyboard shortcuts and binds them to commands.\n * Supports standard modifiers: CTRL, ALT, SHIFT, META (CMD on Mac)\n */\n\nimport logger from \"./logger\";\nimport { subscribe } from \"./events\";\nimport { commandRegistry, TOPIC_COMMAND_REGISTERED } from \"./commandregistry\";\nimport { rootContext } from \"./di\";\n\nimport type { Command } from \"./commandregistry\";\n\nexport type ModifierField = 'ctrl' | 'alt' | 'shift' | 'meta';\n\nexport interface KeyBinding {\n commandId: string;\n key: string;\n ctrl?: boolean;\n alt?: boolean;\n shift?: boolean;\n meta?: boolean;\n}\n\nconst MODIFIER_FIELDS: ModifierField[] = ['alt', 'ctrl', 'meta', 'shift'];\n\nconst MODIFIER_ALIASES: Record<string, ModifierField> = {\n CTRL: 'ctrl', CONTROL: 'ctrl',\n ALT: 'alt', OPTION: 'alt',\n SHIFT: 'shift',\n META: 'meta', CMD: 'meta', COMMAND: 'meta', WIN: 'meta', WINDOWS: 'meta',\n};\n\nconst MODIFIER_DISPLAY: Record<ModifierField, string> = {\n ctrl: 'Ctrl', alt: 'Alt', shift: 'Shift', meta: 'Cmd',\n};\n\nconst KEY_NORMALIZE: Record<string, string> = {\n SPACE: ' ', ESC: 'ESCAPE', RETURN: 'ENTER',\n LEFT: 'ARROWLEFT', RIGHT: 'ARROWRIGHT', UP: 'ARROWUP', DOWN: 'ARROWDOWN',\n DEL: 'DELETE', INS: 'INSERT', PAGEUP: 'PAGEUP', PAGEDOWN: 'PAGEDOWN',\n};\n\nconst KNOWN_MODIFIERS = new Set<string>(Object.keys(MODIFIER_ALIASES));\n\nfunction normalizeKey(key: string): string {\n return KEY_NORMALIZE[key] ?? key;\n}\n\nexport class KeyBindingManager {\n private bindings: Map<string, KeyBinding[]> = new Map();\n private enabled: boolean = true;\n\n constructor() {\n document.addEventListener('keydown', this.handleKeyDown.bind(this), true);\n this.registerExistingCommandBindings();\n subscribe(TOPIC_COMMAND_REGISTERED, (command: Command) => {\n if (command.keyBinding) {\n this.registerKeyBinding(command.id, command.keyBinding);\n }\n });\n }\n\n private registerExistingCommandBindings() {\n const commands = commandRegistry.listCommands();\n Object.values(commands).forEach((command: Command) => {\n if (command.keyBinding) {\n this.registerKeyBinding(command.id, command.keyBinding);\n }\n });\n }\n\n /**\n * Parse a key binding string like \"CTRL+SHIFT+P\" or \"ALT+S\"\n */\n parseKeyBinding(keyBindingString: string): KeyBinding | null {\n if (!keyBindingString || keyBindingString.trim() === '') {\n return null;\n }\n\n const parts = keyBindingString.toUpperCase().split('+').map(p => p.trim());\n if (parts.length === 0) {\n return null;\n }\n\n const key = parts[parts.length - 1];\n const modifiers = parts.slice(0, -1);\n if (parts.length === 1 && KNOWN_MODIFIERS.has(key)) {\n return null;\n }\n\n const binding: Partial<KeyBinding> = { ctrl: false, alt: false, shift: false, meta: false };\n for (const modifier of modifiers) {\n const field = MODIFIER_ALIASES[modifier];\n if (field === undefined) return null;\n binding[field] = true;\n }\n binding.key = normalizeKey(key);\n return binding as KeyBinding;\n }\n\n /**\n * Create a unique key for a binding\n */\n private getBindingKey(binding: KeyBinding): string {\n const parts = [...MODIFIER_FIELDS.filter(f => binding[f]), binding.key.toUpperCase()];\n return parts.join('+');\n }\n\n /**\n * Register a key binding for a command\n */\n registerKeyBinding(commandId: string, keyBindingString: string): boolean {\n const binding = this.parseKeyBinding(keyBindingString);\n \n if (!binding) {\n logger.error(`Invalid key binding: ${keyBindingString}`);\n return false;\n }\n\n binding.commandId = commandId;\n \n const bindingKey = this.getBindingKey(binding);\n \n if (!this.bindings.has(bindingKey)) {\n this.bindings.set(bindingKey, []);\n }\n \n const existing = this.bindings.get(bindingKey)!;\n const sameCommand = existing.find(b => b.commandId === commandId);\n if (sameCommand) {\n logger.error(`Key binding ${keyBindingString} already registered for command ${commandId}`);\n return false;\n }\n const otherCommand = existing.find(b => b.commandId !== commandId);\n if (otherCommand) {\n logger.warn(`Key binding ${keyBindingString} already used by command ${otherCommand.commandId}; refusing for ${commandId}`);\n return false;\n }\n\n existing.push(binding);\n return true;\n }\n\n /**\n * Unregister a key binding\n */\n unregisterKeyBinding(commandId: string, keyBindingString?: string): void {\n if (keyBindingString) {\n const binding = this.parseKeyBinding(keyBindingString);\n if (binding) {\n const bindingKey = this.getBindingKey(binding);\n const bindings = this.bindings.get(bindingKey);\n if (bindings) {\n const filtered = bindings.filter(b => b.commandId !== commandId);\n if (filtered.length === 0) {\n this.bindings.delete(bindingKey);\n } else {\n this.bindings.set(bindingKey, filtered);\n }\n }\n }\n } else {\n // Remove all bindings for this command\n for (const [key, bindings] of this.bindings.entries()) {\n const filtered = bindings.filter(b => b.commandId !== commandId);\n if (filtered.length === 0) {\n this.bindings.delete(key);\n } else {\n this.bindings.set(key, filtered);\n }\n }\n }\n }\n\n /**\n * Get all key bindings for a command\n */\n getKeyBindingsForCommand(commandId: string): string[] {\n const result: string[] = [];\n for (const bindings of this.bindings.values()) {\n for (const binding of bindings) {\n if (binding.commandId === commandId) {\n result.push(this.formatKeyBinding(binding));\n }\n }\n }\n return result.sort();\n }\n\n /**\n * Format a key binding for display\n */\n formatKeyBinding(binding: KeyBinding): string {\n const parts = MODIFIER_FIELDS.filter(f => binding[f]).map(f => MODIFIER_DISPLAY[f]);\n const key = binding.key.length === 1\n ? binding.key.toUpperCase()\n : binding.key.charAt(0).toUpperCase() + binding.key.slice(1).toLowerCase();\n parts.push(key);\n return parts.join('+');\n }\n\n /**\n * Handle keyboard events\n */\n private handleKeyDown(event: KeyboardEvent): void {\n if (!this.enabled) {\n return;\n }\n // event.key can be empty or layout-specific with some IMEs or dead keys\n const eventBinding: KeyBinding = {\n commandId: '',\n key: normalizeKey(event.key.toUpperCase()),\n ctrl: event.ctrlKey,\n alt: event.altKey,\n shift: event.shiftKey,\n meta: event.metaKey\n };\n const bindingKey = this.getBindingKey(eventBinding);\n const bindings = this.bindings.get(bindingKey);\n\n if (bindings && bindings.length > 0) {\n const binding = bindings[0];\n event.preventDefault();\n event.stopPropagation();\n const context = commandRegistry.createExecutionContext({});\n void commandRegistry.execute(binding.commandId, context).then(\n () => {\n logger.debug(`Executed command via key binding: ${binding.commandId}`);\n },\n (error: unknown) => {\n const msg = error instanceof Error ? error.message : String(error);\n logger.error(`Failed to execute command ${binding.commandId}: ${msg}`);\n },\n );\n }\n }\n\n /**\n * Enable or disable key binding handling\n */\n setEnabled(enabled: boolean): void {\n this.enabled = enabled;\n }\n\n /**\n * Check if key binding handling is enabled\n */\n isEnabled(): boolean {\n return this.enabled;\n }\n\n /**\n * Get all registered key bindings\n */\n getAllBindings(): Map<string, KeyBinding[]> {\n const copy = new Map<string, KeyBinding[]>();\n for (const [key, bindings] of this.bindings) {\n copy.set(key, [...bindings]);\n }\n return copy;\n }\n\n /**\n * Clear all key bindings\n */\n clearAll(): void {\n this.bindings.clear();\n }\n}\n\nexport const keyBindingManager = new KeyBindingManager();\nrootContext.put(\"keyBindingManager\", keyBindingManager);\n\n","import {DocksWidget} from \"../widgets/widget\";\nimport {appSettings} from \"../core/settingsservice\";\n\nexport abstract class DocksElement extends DocksWidget {\n /**\n * Unique settings key for this element, used for persisting dialog settings.\n * Automatically initialized on first access via getDialogSetting() or setDialogSetting().\n */\n private settingsKey: string | null = null;\n\n /**\n * Builds a unique DOM tree path for this element.\n * Uses id attribute if available, otherwise builds a path based on tag names and indices.\n * Useful for generating unique settings keys.\n * \n * @returns A string representing the DOM path, or null if path cannot be determined\n */\n private buildDOMTreePath(): string | null {\n const pathParts: string[] = [];\n let current: HTMLElement | null = this;\n \n while (current && current !== document.body && current !== document.documentElement) {\n const id = current.getAttribute(\"id\");\n if (id) {\n pathParts.unshift(`#${id}`);\n break;\n }\n \n const tagName = current.tagName.toLowerCase();\n const parent: HTMLElement | null = current.parentElement;\n \n if (!parent) {\n break;\n }\n \n const siblings = Array.from(parent.children).filter(\n (child: Element) => child.tagName.toLowerCase() === tagName\n ) as HTMLElement[];\n const index = siblings.indexOf(current);\n \n if (index >= 0) {\n pathParts.unshift(`${tagName}:${index}`);\n } else {\n pathParts.unshift(tagName);\n }\n \n current = parent;\n }\n \n return pathParts.length > 0 ? pathParts.join(\" > \") : null;\n }\n\n /**\n * Initializes the settings key for this element using the element's tag name.\n * Called automatically on first access via getDialogSetting() or setDialogSetting().\n */\n private initializeSettingsKey(): void {\n if (!this.settingsKey) {\n const prefix = this.tagName.toLowerCase();\n const id = this.getAttribute(\"id\");\n if (id) {\n this.settingsKey = `${prefix}:${id}`;\n return;\n }\n \n const path = this.buildDOMTreePath();\n if (path) {\n this.settingsKey = `${prefix}:${path}`;\n }\n }\n }\n\n /**\n * Gets a dialog setting value for this element.\n * Automatically initializes the settings key on first access if not already set.\n * \n * @returns The persisted setting value, or undefined if not found\n */\n protected async getDialogSetting(): Promise<any> {\n this.initializeSettingsKey();\n if (!this.settingsKey) {\n return undefined;\n }\n return await appSettings.getDialogSetting(this.settingsKey);\n }\n\n /**\n * Saves a dialog setting value for this element.\n * Automatically initializes the settings key on first access if not already set.\n * \n * @param value - The value to persist\n */\n protected async setDialogSetting(value: any): Promise<void> {\n this.initializeSettingsKey();\n if (!this.settingsKey) {\n return;\n }\n await appSettings.setDialogSetting(this.settingsKey, value);\n }\n}","import { html, TemplateResult, css } from \"lit\";\nimport { unsafeHTML } from \"lit/directives/unsafe-html.js\";\nimport { marked } from \"marked\";\nimport { DocksElement } from \"./element\";\n\nexport abstract class DocksDialogContent extends DocksElement {\n static styles = [\n css`\n .dialog-message {\n margin-bottom: 0.5rem;\n color: var(--wa-color-text-normal);\n }\n `\n ];\n\n dispose(): void | Promise<void> {\n }\n\n getResult(): any {\n return undefined;\n }\n\n protected renderMessage(message: string, markdown: boolean = false): TemplateResult {\n if (markdown) {\n const htmlContent = marked.parse(message, { async: false }) as string;\n return html`<div class=\"dialog-message\" style=\"white-space: normal;\">${unsafeHTML(htmlContent)}</div>`;\n }\n return html`<div class=\"dialog-message\" style=\"white-space: pre-line;\">${message}</div>`;\n }\n}\n\n","import { html, render, TemplateResult } from \"lit\";\nimport { contributionRegistry, Contribution, TOPIC_CONTRIBUTEIONS_CHANGED } from \"./contributionregistry\";\nimport { subscribe } from \"./events\";\nimport { createLogger } from \"./logger\";\nimport { rootContext } from \"./di\";\nimport { DocksDialogContent } from \"../parts/dialog-content\";\n\nconst logger = createLogger('DialogService');\n\nexport const DIALOG_CONTRIBUTION_TARGET = \"dialogs\";\n\nexport interface DialogButton {\n id: string;\n label: string;\n variant?: 'default' | 'primary' | 'success' | 'neutral' | 'warning' | 'danger';\n disabled?: boolean;\n}\n\nexport const OK_BUTTON: DialogButton = {\n id: 'ok',\n label: 'OK',\n variant: 'primary'\n};\n\nexport const CANCEL_BUTTON: DialogButton = {\n id: 'cancel',\n label: 'Cancel',\n variant: 'default'\n};\n\nexport const YES_BUTTON: DialogButton = {\n id: 'yes',\n label: 'Yes',\n variant: 'primary'\n};\n\nexport const NO_BUTTON: DialogButton = {\n id: 'no',\n label: 'No',\n variant: 'default'\n};\n\nexport const CLOSE_BUTTON: DialogButton = {\n id: 'close',\n label: 'Close',\n variant: 'default'\n};\n\nexport const SAVE_BUTTON: DialogButton = {\n id: 'save',\n label: 'Save',\n variant: 'primary'\n};\n\nexport const DELETE_BUTTON: DialogButton = {\n id: 'delete',\n label: 'Delete',\n variant: 'danger'\n};\n\nexport interface DialogContribution extends Contribution {\n id: string;\n buttons?: DialogButton[];\n component: (state?: any) => TemplateResult;\n onButton: (id: string, result: any, state?: any) => boolean | Promise<boolean> | void | Promise<void>;\n}\n\nlet dialogContainer: HTMLElement | null = null;\n\nfunction getDialogContainer(): HTMLElement {\n if (!dialogContainer || !document.body.contains(dialogContainer)) {\n dialogContainer = document.createElement('div');\n dialogContainer.id = 'global-dialog-container';\n document.body.appendChild(dialogContainer);\n }\n return dialogContainer;\n}\n\nclass DialogService {\n private contributions: Map<string, DialogContribution> = new Map();\n private contributionsChangeScheduled = false;\n\n constructor() {\n this.loadContributions();\n\n subscribe(TOPIC_CONTRIBUTEIONS_CHANGED, (event: any) => {\n if (event.target !== DIALOG_CONTRIBUTION_TARGET) return;\n if (this.contributionsChangeScheduled) return;\n this.contributionsChangeScheduled = true;\n queueMicrotask(() => {\n this.contributionsChangeScheduled = false;\n this.loadContributions();\n });\n });\n }\n\n private loadContributions(): void {\n const contributions = contributionRegistry.getContributions<DialogContribution>(DIALOG_CONTRIBUTION_TARGET);\n \n this.contributions.clear();\n \n for (const contribution of contributions) {\n if (!contribution.id) {\n logger.warn('Dialog contribution missing id, skipping');\n continue;\n }\n\n\n if (!contribution.component) {\n logger.warn(`Dialog contribution \"${contribution.id}\" has no component function, skipping`);\n continue;\n }\n\n if (!contribution.onButton) {\n logger.warn(`Dialog contribution \"${contribution.id}\" has no onButton callback, skipping`);\n continue;\n }\n\n this.contributions.set(contribution.id, contribution);\n }\n }\n\n async open(dialogId: string, state?: any): Promise<void> {\n const contribution = this.contributions.get(dialogId);\n \n if (!contribution) {\n logger.error(`Dialog \"${dialogId}\" not found`);\n throw new Error(`Dialog \"${dialogId}\" not found`);\n }\n\n return new Promise((resolve) => {\n const container = getDialogContainer();\n let isOpen = true;\n let dialogContentElement: DocksDialogContent | null = null;\n\n const cleanup = async () => {\n if (!isOpen) return;\n isOpen = false;\n \n if (dialogContentElement) {\n try {\n await dialogContentElement.dispose();\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error(`Error disposing dialog content for \"${dialogId}\": ${errorMessage}`);\n }\n }\n \n try {\n const result = dialogContentElement ? dialogContentElement.getResult() : undefined;\n await contribution.onButton('close', result, stateWithClose);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error(`Error executing close callback for dialog \"${dialogId}\": ${errorMessage}`);\n }\n \n render(html``, container);\n resolve();\n };\n\n const handleButtonClick = async (buttonId: string) => {\n try {\n const result = dialogContentElement ? dialogContentElement.getResult() : undefined;\n const shouldClose = await contribution.onButton(buttonId, result, stateWithClose);\n \n if (shouldClose !== false) {\n cleanup();\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error(`Error executing button callback for dialog \"${dialogId}\": ${errorMessage}`);\n cleanup();\n }\n };\n\n const buttons = contribution.buttons && contribution.buttons.length > 0 \n ? contribution.buttons \n : [OK_BUTTON];\n\n if (state && typeof state === 'object') {\n (state as any).close = cleanup;\n }\n const stateWithClose = { ...state, close: cleanup };\n\n const template = html`\n <wa-dialog label=\"${contribution.label || dialogId}\" open @wa-request-close=${cleanup}>\n <style>\n .dialog-service-content {\n display: flex;\n flex-direction: column;\n gap: 1rem;\n padding: 1rem;\n min-width: 400px;\n }\n \n .dialog-service-footer {\n display: flex;\n gap: 0.5rem;\n justify-content: flex-end;\n margin-top: 1rem;\n padding-top: 1rem;\n border-top: 1px solid var(--wa-color-neutral-20);\n }\n\n :host-context(.wa-light) .dialog-service-footer {\n border-top-color: var(--wa-color-neutral-80);\n }\n </style>\n \n <div class=\"dialog-service-content\" \n @dialog-ok=${() => {\n const okButton = buttons.find(b => b.id === 'ok');\n if (okButton) {\n handleButtonClick(okButton.id);\n }\n }}\n @dialog-cancel=${() => {\n const cancelButton = buttons.find(b => b.id === 'cancel');\n if (cancelButton) {\n handleButtonClick(cancelButton.id);\n } else {\n cleanup();\n }\n }}>\n ${contribution.component(state)}\n \n <div class=\"dialog-service-footer\">\n ${buttons.map(button => html`\n <wa-button \n variant=\"${button.variant || 'default'}\"\n ?disabled=${button.disabled}\n @click=${() => handleButtonClick(button.id)}\n >\n ${button.label}\n </wa-button>\n `)}\n </div>\n </div>\n </wa-dialog>\n `;\n\n render(template, container);\n \n (async () => {\n const allElements = Array.from(container.querySelectorAll('*'));\n for (const element of allElements) {\n if (element instanceof DocksDialogContent) {\n await element.updateComplete;\n dialogContentElement = element;\n break;\n }\n }\n })();\n });\n }\n\n getDialogIds(): string[] {\n return Array.from(this.contributions.keys());\n }\n\n hasDialog(dialogId: string): boolean {\n return this.contributions.has(dialogId);\n }\n}\n\nexport const dialogService = new DialogService();\nrootContext.put(\"dialogService\", dialogService);\n\n","import { publish } from \"../events\";\nimport {\n Directory,\n type GetResourceOptions,\n type Resource,\n TOPIC_WORKSPACE_CHANGED,\n workspaceService,\n} from \"./common\";\n\nconst OPFS_DISPLAY_NAME = '.opfs';\n\nasync function getOPFSRoot(): Promise<FileSystemDirectoryHandle> {\n if (typeof navigator === 'undefined' || !navigator.storage?.getDirectory) {\n throw new Error('OPFS is not available in this environment');\n }\n return await navigator.storage.getDirectory();\n}\n\nexport class OPFSRootDirectory extends Directory {\n constructor(private readonly inner: Directory) {\n super();\n }\n\n getName(): string {\n return OPFS_DISPLAY_NAME;\n }\n\n getParent(): Directory | undefined {\n return this.inner.getParent();\n }\n\n async listChildren(forceRefresh: boolean): Promise<Resource[]> {\n return this.inner.listChildren(forceRefresh);\n }\n\n async getResource(path: string, options?: GetResourceOptions): Promise<Resource | null> {\n return this.inner.getResource(path, options);\n }\n\n touch(): void {\n this.inner.touch();\n }\n\n async delete(name?: string, recursive?: boolean): Promise<void> {\n return this.inner.delete(name, recursive);\n }\n\n async copyTo(targetPath: string): Promise<void> {\n return this.inner.copyTo(targetPath);\n }\n\n async rename(newName: string): Promise<void> {\n return this.inner.rename(newName);\n }\n}\n\n// Register OPFS workspace contribution\nworkspaceService.registerContribution({\n type: 'opfs',\n name: 'opfs',\n\n canHandle(input: any): boolean {\n return input && typeof input === 'object' && input.opfs === true;\n },\n\n async connect(_input: { opfs: true }): Promise<Directory> {\n const root = await getOPFSRoot();\n // We wrap the underlying FileSysDirHandleResource root in an OPFSRootDirectory\n // for a stable display name and clear separation in the workspace tree.\n const fsModule = await import('./fs-access');\n const FileSysDirHandleResource = fsModule.FileSysDirHandleResource;\n const inner = new FileSysDirHandleResource(root);\n return new OPFSRootDirectory(inner);\n },\n\n async restore(data: any): Promise<Directory | undefined> {\n if (data && typeof data === 'object' && data.opfs === true) {\n const root = await getOPFSRoot();\n const fsModule = await import('./fs-access');\n const FileSysDirHandleResource = fsModule.FileSysDirHandleResource;\n const inner = new FileSysDirHandleResource(root);\n return new OPFSRootDirectory(inner);\n }\n return undefined;\n },\n\n async persist(workspace: Directory): Promise<any> {\n if (workspace instanceof OPFSRootDirectory) {\n return { opfs: true };\n }\n return null;\n }\n});\n\n\n","import {\n File,\n Directory,\n FileContentType,\n type FileContentsOptions,\n type GetResourceOptions,\n type Resource,\n TOPIC_WORKSPACE_CHANGED,\n workspaceService,\n} from \"./common\";\nimport { publish } from \"../events\";\n\ntype IDBEntryType = 'file' | 'dir';\n\ninterface IDBEntry {\n type: IDBEntryType;\n content?: Blob;\n mimeType?: string;\n}\n\nconst IDB_WORKSPACE_DB_NAME = 'eclipse-docks-workspace-idb';\nconst IDB_WORKSPACE_STORE_NAME = 'files';\n\nlet idbWorkspacePromise: Promise<IDBDatabase> | null = null;\n\nasync function getWorkspaceIDB(): Promise<IDBDatabase> {\n if (typeof indexedDB === 'undefined') {\n throw new Error('IndexedDB is not available in this environment');\n }\n if (!idbWorkspacePromise) {\n idbWorkspacePromise = new Promise((resolve, reject) => {\n const request = indexedDB.open(IDB_WORKSPACE_DB_NAME, 1);\n request.onerror = () => reject(request.error);\n request.onsuccess = () => resolve(request.result);\n request.onupgradeneeded = (e) => {\n const db = (e.target as IDBOpenDBRequest).result;\n if (!db.objectStoreNames.contains(IDB_WORKSPACE_STORE_NAME)) {\n db.createObjectStore(IDB_WORKSPACE_STORE_NAME);\n }\n };\n });\n }\n return idbWorkspacePromise;\n}\n\nasync function getNextIndexedDBName(): Promise<string> {\n const baseName = 'IndexedDB';\n const folders = await workspaceService.getFolders();\n const existingNames = new Set(\n folders\n .filter(f => f.type === 'indexeddb')\n .map(f => f.name)\n );\n\n if (!existingNames.has(baseName)) {\n return baseName;\n }\n\n let index = 1;\n // Find the smallest n such that \"IndexedDB (n)\" is unused\n // to keep names stable and predictable.\n // This is O(k) in number of existing IndexedDB roots, which is small.\n // We avoid gaps intentionally (e.g. after deleting \"(1)\") to keep UX simple.\n while (existingNames.has(`${baseName} (${index})`)) {\n index += 1;\n }\n return `${baseName} (${index})`;\n}\n\nfunction normalizePath(path: string): string {\n if (!path) return '';\n return path.split('/').filter(Boolean).join('/');\n}\n\nfunction joinPath(base: string, name: string): string {\n const cleanBase = normalizePath(base);\n const cleanName = normalizePath(name);\n if (!cleanBase) return cleanName;\n if (!cleanName) return cleanBase;\n return `${cleanBase}/${cleanName}`;\n}\n\nfunction storageKey(rootId: string, path: string): string {\n const norm = normalizePath(path);\n return norm ? `${rootId}/${norm}` : rootId;\n}\n\nfunction storagePrefix(rootId: string, path: string): string {\n const norm = normalizePath(path);\n return norm ? `${rootId}/${norm}/` : `${rootId}/`;\n}\n\nasync function idbGet(rootId: string, path: string): Promise<IDBEntry | undefined> {\n const db = await getWorkspaceIDB();\n const tx = db.transaction(IDB_WORKSPACE_STORE_NAME, 'readonly');\n const store = tx.objectStore(IDB_WORKSPACE_STORE_NAME);\n const key = path ? storageKey(rootId, path) : rootId;\n return await new Promise((resolve, reject) => {\n const req = store.get(key);\n req.onsuccess = () => resolve(req.result as IDBEntry | undefined);\n req.onerror = () => reject(req.error);\n });\n}\n\nasync function idbPut(rootId: string, path: string, entry: IDBEntry): Promise<void> {\n const db = await getWorkspaceIDB();\n const tx = db.transaction(IDB_WORKSPACE_STORE_NAME, 'readwrite');\n const store = tx.objectStore(IDB_WORKSPACE_STORE_NAME);\n const key = path ? storageKey(rootId, path) : rootId;\n await new Promise<void>((resolve, reject) => {\n const req = store.put(entry, key);\n req.onsuccess = () => resolve();\n req.onerror = () => reject(req.error);\n });\n}\n\nasync function idbDelete(rootId: string, path: string): Promise<void> {\n const db = await getWorkspaceIDB();\n const tx = db.transaction(IDB_WORKSPACE_STORE_NAME, 'readwrite');\n const store = tx.objectStore(IDB_WORKSPACE_STORE_NAME);\n const key = path ? storageKey(rootId, path) : rootId;\n await new Promise<void>((resolve, reject) => {\n const req = store.delete(key);\n req.onsuccess = () => resolve();\n req.onerror = () => reject(req.error);\n });\n}\n\nasync function idbDeleteTree(rootId: string, rootPath: string): Promise<void> {\n const db = await getWorkspaceIDB();\n const tx = db.transaction(IDB_WORKSPACE_STORE_NAME, 'readwrite');\n const store = tx.objectStore(IDB_WORKSPACE_STORE_NAME);\n const prefix = storageKey(rootId, rootPath);\n const prefixWithSlash = prefix + '/';\n const cursorReq = store.openCursor();\n\n await new Promise<void>((resolve, reject) => {\n cursorReq.onerror = () => reject(cursorReq.error);\n cursorReq.onsuccess = (ev) => {\n const cursor = (ev.target as IDBRequest<IDBCursorWithValue | null>).result;\n if (!cursor) {\n resolve();\n return;\n }\n const key = String(cursor.key);\n if (key === prefix || key.startsWith(prefixWithSlash)) {\n cursor.delete();\n }\n cursor.continue();\n };\n });\n}\n\nasync function idbDeleteRoot(rootId: string): Promise<void> {\n await idbDeleteTree(rootId, '');\n}\n\nasync function idbRenameTree(rootId: string, oldPath: string, newPath: string): Promise<void> {\n const db = await getWorkspaceIDB();\n const tx = db.transaction(IDB_WORKSPACE_STORE_NAME, 'readwrite');\n const store = tx.objectStore(IDB_WORKSPACE_STORE_NAME);\n const oldPrefix = storageKey(rootId, oldPath);\n const newPrefix = storageKey(rootId, newPath);\n const cursorReq = store.openCursor();\n\n const operations: Array<() => void> = [];\n\n await new Promise<void>((resolve, reject) => {\n cursorReq.onerror = () => reject(cursorReq.error);\n cursorReq.onsuccess = (ev) => {\n const cursor = (ev.target as IDBRequest<IDBCursorWithValue | null>).result;\n if (!cursor) {\n resolve();\n return;\n }\n const key = String(cursor.key);\n if (key === oldPrefix || key.startsWith(oldPrefix + '/')) {\n const suffix = key.slice(oldPrefix.length);\n const newKey = newPrefix + suffix;\n const value = cursor.value as IDBEntry;\n operations.push(() => {\n cursor.delete();\n store.put(value, newKey);\n });\n }\n cursor.continue();\n };\n });\n\n for (const op of operations) {\n op();\n }\n}\n\nasync function idbListChildrenOfDir(rootId: string, dirPath: string): Promise<Array<{ name: string; entry: IDBEntry; type: IDBEntryType }>> {\n const db = await getWorkspaceIDB();\n const tx = db.transaction(IDB_WORKSPACE_STORE_NAME, 'readonly');\n const store = tx.objectStore(IDB_WORKSPACE_STORE_NAME);\n const prefix = storagePrefix(rootId, dirPath);\n const cursorReq = store.openCursor();\n\n const dirNames = new Set<string>();\n const fileEntries = new Map<string, IDBEntry>();\n\n await new Promise<void>((resolve, reject) => {\n cursorReq.onerror = () => reject(cursorReq.error);\n cursorReq.onsuccess = (ev) => {\n const cursor = (ev.target as IDBRequest<IDBCursorWithValue | null>).result;\n if (!cursor) {\n resolve();\n return;\n }\n const key = String(cursor.key);\n const entry = cursor.value as IDBEntry;\n\n if (!key.startsWith(prefix)) {\n cursor.continue();\n return;\n }\n\n const rest = key.slice(prefix.length);\n if (!rest) {\n cursor.continue();\n return;\n }\n\n const idx = rest.indexOf('/');\n const childName = idx === -1 ? rest : rest.slice(0, idx);\n\n if (idx === -1) {\n if (entry.type === 'dir') {\n dirNames.add(childName);\n } else {\n fileEntries.set(childName, entry);\n }\n } else {\n dirNames.add(childName);\n }\n\n cursor.continue();\n };\n });\n\n const result: Array<{ name: string; entry: IDBEntry; type: IDBEntryType }> = [];\n for (const name of dirNames) {\n result.push({ name, entry: { type: 'dir' }, type: 'dir' });\n }\n for (const [name, entry] of fileEntries) {\n if (!dirNames.has(name)) {\n result.push({ name, entry, type: 'file' });\n }\n }\n return result;\n}\n\nfunction getRootIdFromParent(parent: Directory): string {\n return parent instanceof IDBDirectoryResource ? parent.getRootId() : '';\n}\n\nexport class IDBFileResource extends File {\n private readonly path: string;\n private readonly parent: Directory;\n\n constructor(path: string, parent: Directory) {\n super();\n this.path = normalizePath(path);\n this.parent = parent;\n }\n\n getName(): string {\n const parts = this.path.split('/');\n return parts[parts.length - 1] || '';\n }\n\n getParent(): Directory {\n return this.parent;\n }\n\n private getRootId(): string {\n return getRootIdFromParent(this.parent);\n }\n\n async delete(): Promise<void> {\n await idbDelete(this.getRootId(), this.path);\n publish(TOPIC_WORKSPACE_CHANGED, workspaceService.getWorkspaceSync() ?? this.getWorkspace());\n }\n\n async getContents(options?: FileContentsOptions): Promise<any> {\n const entry = await idbGet(this.getRootId(), this.path);\n let raw = (entry as any)?.content as Blob | string | undefined;\n\n if (typeof raw === 'string') {\n const migratedBlob = new Blob([raw], { type: entry?.mimeType || 'text/plain' });\n raw = migratedBlob;\n if (entry) {\n entry.content = migratedBlob;\n await idbPut(this.getRootId(), this.path, entry);\n }\n }\n\n if (!options || options.contentType === FileContentType.TEXT) {\n if (!raw) {\n return '';\n }\n return await raw.text();\n }\n\n let blob: Blob;\n if (raw) {\n blob = raw;\n } else {\n blob = new Blob([], { type: entry?.mimeType });\n }\n\n if (options.blob) {\n return blob;\n }\n\n if (options.uri) {\n return URL.createObjectURL(blob);\n }\n\n return blob.stream();\n }\n\n async saveContents(contents: any, _options?: FileContentsOptions): Promise<void> {\n let blob: Blob;\n let mimeType: string | undefined;\n\n if (contents instanceof Blob) {\n blob = contents;\n mimeType = contents.type || undefined;\n } else if (typeof contents === 'string') {\n mimeType = 'text/plain';\n blob = new Blob([contents], { type: mimeType });\n } else if (contents instanceof ReadableStream) {\n const response = new Response(contents);\n blob = await response.blob();\n mimeType = response.headers.get('content-type') ?? undefined;\n } else {\n const text = String(contents ?? '');\n mimeType = 'text/plain';\n blob = new Blob([text], { type: mimeType });\n }\n\n await idbPut(this.getRootId(), this.path, { type: 'file', content: blob, mimeType });\n publish(TOPIC_WORKSPACE_CHANGED, workspaceService.getWorkspaceSync() ?? this.getWorkspace());\n }\n\n async size(): Promise<number | null> {\n const entry = await idbGet(this.getRootId(), this.path);\n const content = entry?.content;\n if (!content) return null;\n return content.size;\n }\n\n async copyTo(targetPath: string): Promise<void> {\n const contents = await this.getContents({ blob: true });\n const targetFile = await this.getWorkspace().getResource(targetPath, { create: true }) as File;\n if (!targetFile) {\n throw new Error(`Failed to create target file: ${targetPath}`);\n }\n await targetFile.saveContents(contents);\n }\n\n async rename(newName: string): Promise<void> {\n if (this.getName() === newName) {\n return;\n }\n const parentDir = this.getParent();\n const parentPath = parentDir instanceof IDBDirectoryResource ? parentDir.getPath() : '';\n const newPath = joinPath(parentPath, newName);\n\n const rootId = this.getRootId();\n const entry = await idbGet(rootId, this.path);\n if (!entry) {\n throw new Error('File not found in IndexedDB');\n }\n\n await idbDelete(rootId, this.path);\n await idbPut(rootId, newPath, entry);\n\n publish(TOPIC_WORKSPACE_CHANGED, workspaceService.getWorkspaceSync() ?? this.getWorkspace());\n }\n}\n\nexport class IDBDirectoryResource extends Directory {\n private readonly path: string;\n private readonly parent?: Directory;\n\n constructor(path: string, parent?: Directory) {\n super();\n this.path = normalizePath(path);\n this.parent = parent;\n }\n\n getPath(): string {\n return this.path;\n }\n\n getName(): string {\n if (!this.path) {\n return '';\n }\n const parts = this.path.split('/');\n return parts[parts.length - 1];\n }\n\n getParent(): Directory | undefined {\n return this.parent;\n }\n\n getRoot(): IDBDirectoryResource {\n const p = this.getParent();\n if (!p) return this;\n return (p as IDBDirectoryResource).getRoot();\n }\n\n getRootId(): string {\n const r = this.getRoot();\n return r instanceof IDBRootDirectory ? r.getRootId() : '';\n }\n\n async listChildren(_forceRefresh: boolean): Promise<Resource[]> {\n const childrenInfo = await idbListChildrenOfDir(this.getRootId(), this.path);\n const result: Resource[] = [];\n for (const child of childrenInfo) {\n const childPath = joinPath(this.path, child.name);\n if (child.type === 'dir') {\n result.push(new IDBDirectoryResource(childPath, this));\n } else {\n result.push(new IDBFileResource(childPath, this));\n }\n }\n return result;\n }\n\n async getResource(path: string, options?: GetResourceOptions): Promise<Resource | null> {\n if (!path) {\n throw new Error('No path provided');\n }\n\n const isDirectoryIntent = path.endsWith('/');\n const segments = path.split('/').filter(s => s.trim());\n let currentDir: IDBDirectoryResource = this;\n let workspaceChanged = false;\n\n for (let i = 0; i < segments.length; i++) {\n const segment = segments[i];\n const isLast = i === segments.length - 1;\n const currentPath = currentDir.getPath();\n const candidatePath = joinPath(currentPath, segment);\n const rootId = this.getRootId();\n\n const entry = await idbGet(rootId, candidatePath);\n\n if (!entry) {\n if (!options?.create) {\n return null;\n }\n\n if (isLast && !isDirectoryIntent) {\n await idbPut(rootId, candidatePath, { type: 'file', content: new Blob([]) });\n workspaceChanged = true;\n publish(TOPIC_WORKSPACE_CHANGED, workspaceService.getWorkspaceSync() ?? this.getWorkspace());\n return new IDBFileResource(candidatePath, currentDir);\n }\n\n await idbPut(rootId, candidatePath, { type: 'dir' });\n workspaceChanged = true;\n currentDir = new IDBDirectoryResource(candidatePath, currentDir);\n continue;\n }\n\n if (isLast) {\n if (isDirectoryIntent) {\n if (entry.type !== 'dir') {\n return null;\n }\n return new IDBDirectoryResource(candidatePath, currentDir);\n }\n if (entry.type === 'dir') {\n return new IDBDirectoryResource(candidatePath, currentDir);\n }\n return new IDBFileResource(candidatePath, currentDir);\n }\n\n if (entry.type !== 'dir') {\n return null;\n }\n\n currentDir = new IDBDirectoryResource(candidatePath, currentDir);\n }\n\n if (workspaceChanged) {\n publish(TOPIC_WORKSPACE_CHANGED, workspaceService.getWorkspaceSync() ?? this.getWorkspace());\n }\n\n return currentDir;\n }\n\n touch(): void {\n publish(TOPIC_WORKSPACE_CHANGED, workspaceService.getWorkspaceSync() ?? this.getWorkspace());\n }\n\n async delete(name?: string, _recursive: boolean = true): Promise<void> {\n if (!name) {\n const parent = this.getParent();\n if (parent instanceof IDBDirectoryResource) {\n await parent.delete(this.getName());\n return;\n }\n return;\n }\n\n const targetPath = joinPath(this.path, name);\n await idbDeleteTree(this.getRootId(), targetPath);\n publish(TOPIC_WORKSPACE_CHANGED, workspaceService.getWorkspaceSync() ?? this.getWorkspace());\n }\n\n async copyTo(targetPath: string): Promise<void> {\n for (const resource of await this.listChildren(false)) {\n const childTarget = [targetPath, resource.getName()].join('/');\n await resource.copyTo(childTarget);\n }\n }\n\n async rename(newName: string): Promise<void> {\n if (this.getName() === newName) {\n return;\n }\n const parentDir = this.getParent();\n if (!(parentDir instanceof IDBDirectoryResource)) {\n throw new Error('Cannot rename IndexedDB root directory');\n }\n const oldPath = this.getPath();\n const newPath = joinPath(parentDir.getPath(), newName);\n await idbRenameTree(this.getRootId(), oldPath, newPath);\n publish(TOPIC_WORKSPACE_CHANGED, workspaceService.getWorkspaceSync() ?? this.getWorkspace());\n }\n}\n\nexport class IDBRootDirectory extends IDBDirectoryResource {\n private readonly displayName: string;\n private readonly rootId: string;\n\n constructor(displayName: string, rootId: string) {\n super('');\n this.displayName = displayName || 'IndexedDB';\n this.rootId = rootId;\n }\n\n getRootId(): string {\n return this.rootId;\n }\n\n getName(): string {\n return this.displayName;\n }\n\n getParent(): Directory | undefined {\n return undefined;\n }\n\n async rename(_newName: string): Promise<void> {\n const name = String(_newName ?? '').trim();\n if (!name || name === this.displayName) {\n return;\n }\n // Update the in-memory display name and persist the change via workspaceService.\n (this as any).displayName = name;\n await workspaceService.updateFolderName(this, name);\n }\n}\n\nfunction generateRootId(): string {\n return typeof crypto !== 'undefined' && crypto.randomUUID\n ? crypto.randomUUID()\n : 'default-' + Math.random().toString(36).slice(2) + Date.now().toString(36);\n}\n\n// Register IndexedDB workspace contribution\nworkspaceService.registerContribution({\n type: 'indexeddb',\n name: 'idb',\n\n canHandle(input: any): boolean {\n return input && typeof input === 'object' && input.indexeddb === true;\n },\n\n async connect(input: { indexeddb: true; name?: string }): Promise<Directory> {\n await getWorkspaceIDB();\n const explicitName = input.name && String(input.name).trim();\n const name = explicitName && explicitName.length > 0\n ? explicitName\n : await getNextIndexedDBName();\n const rootId = generateRootId();\n return new IDBRootDirectory(name, rootId);\n },\n\n async restore(data: any): Promise<Directory | undefined> {\n if (data && typeof data === 'object' && data.indexeddb === true && data.rootId) {\n await getWorkspaceIDB();\n const name = (data.name && String(data.name).trim()) || 'IndexedDB';\n return new IDBRootDirectory(name, String(data.rootId));\n }\n return undefined;\n },\n\n async persist(workspace: Directory): Promise<any> {\n if (workspace instanceof IDBRootDirectory) {\n return { indexeddb: true, name: workspace.getName(), rootId: workspace.getRootId() };\n }\n return null;\n }\n});\n\n/**\n * Deletes all persisted IndexedDB workspace data for the provided root.\n * Returns true when deletion was performed, false when the directory is not an IndexedDB root.\n */\nexport async function deleteIndexedDbWorkspaceData(directory: Directory): Promise<boolean> {\n if (!(directory instanceof IDBRootDirectory)) {\n return false;\n }\n await idbDeleteRoot(directory.getRootId());\n return true;\n}\n\n\n","import {appSettings} from \"./settingsservice\";\nimport {publish} from \"./events\";\nimport {createLogger} from \"./logger\";\nimport {extensionRegistry, Extension} from \"./extensionregistry\";\nimport {rootContext} from \"./di\";\n\nconst logger = createLogger('MarketplaceRegistry');\n\nexport const TOPIC_MARKETPLACE_CHANGED = \"events/marketplaceregistry/changed\";\n\nexport interface MarketplaceCatalog {\n name?: string;\n description?: string;\n extensions?: Extension[];\n}\n\nconst KEY_CATALOG_URLS = \"marketplace.catalogUrls\";\n\nclass MarketplaceRegistry {\n private catalogUrls: string[] = [];\n private loadingPromises: Map<string, Promise<MarketplaceCatalog>> = new Map();\n\n constructor() {\n // Load catalog URLs and refresh catalogs\n this.loadCatalogUrls().then(() => {\n this.refreshCatalogs().catch(err => {\n logger.error(`Failed to refresh catalogs on init: ${err.message}`);\n });\n });\n }\n\n private async loadCatalogUrls(): Promise<void> {\n try {\n const urls = await appSettings.get(KEY_CATALOG_URLS);\n this.catalogUrls = Array.isArray(urls) ? urls : [];\n } catch (error) {\n logger.error(`Failed to load catalog URLs: ${error}`);\n this.catalogUrls = [];\n }\n }\n\n private async saveCatalogUrls(): Promise<void> {\n await appSettings.set(KEY_CATALOG_URLS, this.catalogUrls);\n publish(TOPIC_MARKETPLACE_CHANGED, {type: 'catalogs', urls: this.catalogUrls});\n }\n\n async addCatalogUrl(url: string): Promise<void> {\n if (!this.isValidUrl(url)) {\n throw new Error(`Invalid catalog URL: ${url}`);\n }\n\n if (this.catalogUrls.includes(url)) {\n logger.debug(`Catalog URL already exists: ${url}`);\n return;\n }\n\n this.catalogUrls.push(url);\n await this.saveCatalogUrls();\n logger.debug(`Added catalog URL: ${url}`);\n\n try {\n await this.refreshCatalogs();\n } catch (error) {\n logger.warn(`Failed to refresh catalogs immediately after adding: ${error}`);\n }\n }\n\n async addCatalogUrls(urls: string[]): Promise<void> {\n let added = 0;\n for (const url of urls) {\n if (!this.isValidUrl(url)) {\n logger.warn(`Skipping invalid catalog URL: ${url}`);\n continue;\n }\n if (this.catalogUrls.includes(url)) continue;\n this.catalogUrls.push(url);\n logger.debug(`Added catalog URL: ${url}`);\n added++;\n }\n if (added === 0) return;\n await this.saveCatalogUrls();\n try {\n await this.refreshCatalogs();\n } catch (error) {\n logger.warn(`Failed to refresh catalogs after adding URLs: ${error}`);\n }\n }\n\n async removeCatalogUrl(url: string): Promise<void> {\n const index = this.catalogUrls.indexOf(url);\n if (index === -1) {\n return;\n }\n\n this.catalogUrls.splice(index, 1);\n await this.saveCatalogUrls();\n logger.info(`Removed catalog URL: ${url}`);\n }\n\n getCatalogUrls(): string[] {\n return [...this.catalogUrls];\n }\n\n private isValidUrl(url: string): boolean {\n try {\n const parsed = new URL(url);\n return parsed.protocol === 'http:' || parsed.protocol === 'https:';\n } catch {\n return false;\n }\n }\n\n private async fetchCatalog(url: string): Promise<MarketplaceCatalog> {\n const existingPromise = this.loadingPromises.get(url);\n if (existingPromise) {\n return existingPromise;\n }\n\n const fetchPromise = (async () => {\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n },\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n const data = await response.json() as MarketplaceCatalog;\n\n if (!data.extensions || !Array.isArray(data.extensions)) {\n throw new Error('Invalid catalog format: extensions array is required');\n }\n\n const catalog: MarketplaceCatalog = {\n name: data.name,\n description: data.description,\n extensions: data.extensions || [],\n };\n\n return catalog;\n } catch (error) {\n logger.error(`Failed to fetch catalog from ${url}: ${error}`);\n throw error;\n } finally {\n this.loadingPromises.delete(url);\n }\n })();\n\n this.loadingPromises.set(url, fetchPromise);\n return fetchPromise;\n }\n\n async refreshCatalogs(): Promise<void> {\n const promises = this.catalogUrls.map(url =>\n this.fetchCatalog(url).catch(error => {\n logger.warn(`Failed to refresh catalog ${url}: ${error.message}`);\n return null;\n })\n );\n\n const catalogs = await Promise.allSettled(promises);\n let registeredCount = 0;\n\n catalogs.forEach((result) => {\n if (result.status === 'fulfilled' && result.value) {\n const catalog = result.value;\n if (catalog.extensions) {\n catalog.extensions.forEach(marketplaceExt => {\n if (!extensionRegistry.getExtensions().find(e => e.id === marketplaceExt.id)) {\n const extension: Extension = {\n ...marketplaceExt,\n external: true\n };\n extensionRegistry.registerExtension(extension);\n registeredCount++;\n }\n });\n }\n }\n });\n\n logger.debug(`Refreshed ${this.catalogUrls.length} catalogs, ${registeredCount} extensions registered`);\n if (registeredCount > 0) {\n logger.info(`Marketplace: ${registeredCount} new extension(s) available`);\n }\n publish(TOPIC_MARKETPLACE_CHANGED, {type: 'refreshed'});\n }\n\n getMarketplaceExtension(extensionId: string): Extension | undefined {\n // Check if extension is registered in extensionRegistry and is external\n const extension = extensionRegistry.getExtensions().find(e => e.id === extensionId);\n if (extension && extension.external) {\n return extension;\n }\n return undefined;\n }\n\n isMarketplaceExtension(extensionId: string): boolean {\n const extension = extensionRegistry.getExtensions().find(e => e.id === extensionId);\n return extension !== undefined && extension.external === true;\n }\n}\n\nexport const marketplaceRegistry = new MarketplaceRegistry();\nrootContext.put(\"marketplaceRegistry\", marketplaceRegistry);\n\n","/**\n * App Loader Service\n * \n * Provides a clean separation between the framework and applications built on it.\n * This allows the framework (k-* components and core services) to be published\n * as a reusable npm package, while applications like `my-app` can be loaded\n * dynamically.\n * \n * Architecture:\n * - Framework: Core services, k-* components (publishable as npm package)\n * - Application: App-specific code, gs-* components, contributions\n * - App Loader: Bridge between framework and application\n */\n\nimport { render, TemplateResult, html } from \"lit\";\nimport { rootContext } from \"./di\";\nimport { createLogger } from \"./logger\";\nimport { extensionRegistry, Extension } from \"./extensionregistry\";\nimport { contributionRegistry, Contribution, LayoutContribution, TOPIC_CONTRIBUTEIONS_CHANGED } from \"./contributionregistry\";\nimport { SYSTEM_LAYOUTS } from \"./constants\";\nimport { appSettings } from \"./settingsservice\";\nimport { marketplaceRegistry } from \"./marketplaceregistry\";\nimport { contributionTargetMappingRegistry, type ContributionNameRemap } from \"./contribution-mapping\";\nimport { publish } from \"./events\";\n\n\nconst logger = createLogger('AppLoader');\n\n/** Layout reference: layout id string, or id + props to parameterize the layout (e.g. show-bottom-panel). */\nexport type LayoutDescriptor = string | { id: string; props?: Record<string, string | boolean> };\n\nfunction getLayoutIdFromApp(app: AppDefinition | undefined): string {\n if (!app) return 'standard';\n const l = app.layout ?? app.layoutId;\n return typeof l === 'object' ? l.id : (l ?? 'standard');\n}\n\nfunction propsToAttributes(props: Record<string, string | boolean>): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(props)) {\n out[k] = typeof v === 'boolean' ? (v ? 'true' : 'false') : v;\n }\n return out;\n}\n\n/**\n * Extracts error message from an error object.\n */\nfunction getErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * Extracts the first path segment from the current page URL.\n * This allows loading apps by path, e.g., /my-app loads the my-app app.\n */\nfunction extractAppIdFromPath(): string | undefined {\n const pathname = window.location.pathname;\n const pathSegments = pathname.split('/').filter(Boolean);\n \n if (pathSegments.length === 0) {\n return undefined;\n }\n \n const firstSegment = pathSegments[0];\n \n if (!firstSegment || firstSegment === 'index.html' || firstSegment.endsWith('.html')) {\n return undefined;\n }\n \n return firstSegment;\n}\n\n/**\n * Application contributions interface.\n * Declaratively defines all contributions for an application.\n */\nexport interface AppContributions {\n /** UI contributions (tabs, toolbars, commands, etc.) */\n ui?: Contribution[];\n \n /** App-specific extensions to register */\n extensions?: Extension[];\n}\n\n/**\n * Represents a single release entry in the release history.\n * Compatible with GitHub release format but with optional html_url.\n */\nexport interface ReleaseEntry {\n /** Release tag name (e.g., \"v1.0.0\") */\n tag_name: string;\n \n /** Human-readable release name */\n name: string;\n \n /** Release notes/description (markdown supported) */\n body: string;\n \n /** ISO 8601 timestamp when the release was published */\n published_at: string;\n \n /** Optional URL to the release page */\n html_url?: string;\n \n /** Whether this is a pre-release */\n prerelease?: boolean;\n \n /** Whether this release is a draft */\n draft?: boolean;\n}\n\n/**\n * Release history can be provided as:\n * - A static array of releases\n * - A function that returns releases asynchronously\n * This allows apps to either provide pre-loaded releases or fetch them dynamically.\n */\nexport type ReleaseHistory = ReleaseEntry[];\n\n/** Descriptor for rendering a single custom element as the app root (no lit required). */\nexport interface RenderDescriptor {\n tag: string;\n attributes?: Record<string, string>;\n}\n\n/**\n * Application definition interface.\n * Applications implement this interface to integrate with the framework.\n */\nexport interface AppDefinition {\n /** Application name (from package.json). Unique key; set by hostConfig resolution when omitted. */\n name?: string;\n\n /** Application version. Set by hostConfig resolution from package.json when omitted. */\n version?: string;\n\n /** Application description. Set by hostConfig resolution from package.json when omitted. */\n description?: string;\n\n /** Optional URL path segment for routing (e.g. \"my-app\"). When absent, name is used for lookup. */\n path?: string;\n \n /**\n * Custom application metadata (optional).\n * Apps can define any custom metadata here for their own use.\n * The framework may read certain metadata keys (e.g., `metadata.github` for release checking).\n */\n metadata?: Record<string, any>;\n \n /**\n * Core framework extensions required by the application.\n * The app loader will enable these extensions when loading the app\n * and disable them when unloading.\n */\n extensions?: string[];\n \n /**\n * Application contributions (tabs, toolbars, commands, app extensions).\n * The app loader will register these contributions automatically.\n */\n contributions?: AppContributions;\n \n /**\n * Application initialization function.\n * Called after extensions are enabled and contributions are registered.\n * Use this for custom initialization logic that can't be expressed declaratively.\n */\n initialize?: () => void | Promise<void>;\n \n /**\n * Optional release history for the application.\n * Can be a static array of releases or a callback function that returns releases (synchronously or asynchronously).\n * If not provided, the version-info command will attempt to fetch releases from GitHub\n * (if metadata.github is configured).\n */\n releaseHistory?: ReleaseHistory | (() => ReleaseHistory | Promise<ReleaseHistory>);\n\n /**\n * Layout: id (string) or { id, props } to parameterize the layout.\n * App root is the chosen layout's component. Props are merged as attributes when rendering (e.g. show-bottom-panel).\n * Defaults to 'standard' when omitted.\n */\n layout?: LayoutDescriptor;\n\n /** @deprecated Use layout (string or { id, props }) instead. */\n layoutId?: string;\n\n /**\n * Optional cleanup function.\n * Called when the app is being unloaded, before extensions are disabled.\n */\n dispose?: () => void | Promise<void>;\n\n /** Resolved dependency versions (e.g. from build plugin). Shown in About / version info. */\n dependencies?: Record<string, string>;\n\n /** Marketplace catalog URLs for this app. Registered when the app is registered. */\n marketplaceCatalogUrls?: string[];\n\n /**\n * Optional contribution remaps for this application.\n * Allows apps to declaratively remap contributions to different targets.\n */\n remaps?: ContributionNameRemap[];\n}\n\n/**\n * Options for registering an application with the apploader.\n */\nexport interface RegisterAppOptions {\n /** Default app name when URL routing (?appId= or path) does not select an app. If not specified, the first registered app is loaded. */\n defaultAppName?: string;\n \n /** \n * Whether to automatically start the apploader after registration.\n * If true, the apploader will start immediately after the app is registered.\n * Defaults to false.\n */\n autoStart?: boolean;\n \n /** \n * DOM element to render the app into.\n * Defaults to document.body.\n */\n container?: HTMLElement;\n\n /**\n * When true, fill name, version, description, dependencies, marketplaceCatalogUrls from __RESOLVED_PACKAGE_INFO__ only when not already set on the app.\n */\n hostConfig?: boolean;\n}\n\n/**\n * App Loader Service\n * \n * Manages application lifecycle:\n * 1. Register app definitions\n * 2. Initialize apps\n * 3. Render apps to DOM\n * 4. Manage app lifecycle\n */\nclass AppLoaderService {\n private apps: Map<string, AppDefinition> = new Map();\n private currentApp?: AppDefinition;\n private started: boolean = false;\n private defaultAppName?: string;\n private container: HTMLElement = document.body;\n private systemRequiredExtensions: Set<string> = new Set();\n private static readonly PREFERRED_APP_KEY = 'preferredAppName';\n private static readonly PREFERRED_LAYOUT_KEY = 'preferredLayoutId';\n private preferredLayoutId?: string;\n \n /**\n * Register an application with the framework.\n * Optionally starts the apploader automatically after registration.\n * \n * @param app - Application definition\n * @param options - Optional configuration for registration and auto-starting\n */\n registerApp(app: AppDefinition, options?: RegisterAppOptions): void {\n if (options?.hostConfig === true && typeof __RESOLVED_PACKAGE_INFO__ !== 'undefined') {\n const resolved = __RESOLVED_PACKAGE_INFO__;\n if (app.name === undefined) app.name = resolved.name;\n if (app.version === undefined) app.version = resolved.version;\n if (app.description === undefined) app.description = resolved.description;\n if (app.dependencies === undefined) app.dependencies = resolved.dependencies;\n if (app.marketplaceCatalogUrls === undefined) app.marketplaceCatalogUrls = resolved.marketplaceCatalogUrls;\n }\n app.name = app.name ?? 'app';\n app.version = app.version ?? '0.0.0';\n\n if (this.apps.has(app.name)) {\n logger.warn(`App '${app.name}' is already registered. Overwriting.`);\n }\n if (app.marketplaceCatalogUrls?.length) {\n marketplaceRegistry.addCatalogUrls(app.marketplaceCatalogUrls).catch(() => {});\n }\n\n this.apps.set(app.name, app);\n\n if (options?.defaultAppName) {\n this.defaultAppName = options.defaultAppName;\n }\n \n if (options?.container) {\n this.container = options.container;\n }\n \n if (options?.autoStart && !this.started) {\n this.start();\n }\n }\n\n registerSystemRequiredExtension(extensionId: string) {\n this.systemRequiredExtensions.add(extensionId);\n }\n\n /**\n * Start the application loader.\n * Resolves which registered app to load from URL hints (?appId=, path) and settings, then loads it.\n * This method is idempotent - calling it multiple times only starts once.\n */\n async start(): Promise<void> {\n if (this.started) {\n logger.debug('AppLoader already started');\n return;\n }\n \n this.started = true;\n\n const urlParams = new URLSearchParams(window.location.search);\n const appIdFromUrl = urlParams.get('appId');\n const appIdFromPath = extractAppIdFromPath();\n\n if (appIdFromPath) {\n logger.info(`Extracted app ID from current page path: ${appIdFromPath}`);\n }\n\n const appToLoad = await this.selectAppToLoad({\n appIdFromUrl,\n appIdFromPath\n });\n \n if (!appToLoad) {\n throw new Error('No apps registered');\n }\n \n await this.loadApp(appToLoad, this.container);\n }\n\n /**\n * Resolve a path/URL segment to an app name (map key). Matches app.path, app.name, or name ending with /segment.\n */\n private findAppNameBySegment(segment: string): string | undefined {\n if (this.apps.has(segment)) return segment;\n for (const app of this.apps.values()) {\n if (app.path === segment || (app.name && app.name.endsWith('/' + segment))) return app.name ?? undefined;\n }\n return undefined;\n }\n\n /**\n * Load and initialize an application.\n * @param appName - Application name (must be already registered)\n * @param container - Optional DOM element to render into (if provided, auto-renders after loading)\n */\n private dispatchLoadProgress(message: string): void {\n window.dispatchEvent(new CustomEvent('app-load-progress', { detail: { message } }));\n }\n\n async loadApp(appName: string, container?: HTMLElement): Promise<void> {\n const app = this.apps.get(appName);\n if (!app) {\n throw new Error(`App '${appName}' not found. Make sure it's registered.`);\n }\n\n this.dispatchLoadProgress('Starting…');\n\n // Dispose current app if exists\n if (this.currentApp) {\n logger.info(`Disposing current app: ${this.currentApp.name}`);\n \n // Call app's dispose method\n if (this.currentApp.dispose) {\n await this.currentApp.dispose();\n }\n \n // Disable current app's extensions (but not system-required ones)\n if (this.currentApp.extensions && this.currentApp.extensions.length > 0) {\n logger.info(`Disabling ${this.currentApp.extensions.length} extensions...`);\n this.currentApp.extensions.forEach(extId => {\n extensionRegistry.disable(extId);\n });\n }\n }\n \n // Apply app-level contribution remaps before registering contributions\n contributionTargetMappingRegistry.applyAppNameRemaps(app.remaps);\n if (app.remaps?.length) {\n const remappedTargets = new Set<string>();\n for (const r of app.remaps) {\n for (const t of r.targets) remappedTargets.add(t);\n }\n for (const target of remappedTargets) {\n const contributions = contributionRegistry.getContributions(target);\n publish(TOPIC_CONTRIBUTEIONS_CHANGED, { target, contributions });\n }\n }\n\n // Register app contributions\n if (app.contributions) {\n logger.info('Registering app contributions...');\n \n // Register UI contributions (tabs, toolbars, commands, etc.)\n if (app.contributions.ui) {\n app.contributions.ui.forEach(contribution => {\n const target = contribution.target;\n if (target) {\n contributionRegistry.registerContribution(target, contribution);\n }\n });\n logger.info(`Registered ${app.contributions.ui.length} UI contributions`);\n }\n \n // Register app-specific extensions\n if (app.contributions.extensions) {\n app.contributions.extensions.forEach(extension => {\n extensionRegistry.registerExtension(extension);\n });\n logger.info(`Registered ${app.contributions.extensions.length} app extensions`);\n }\n }\n \n const extensionsSet = new Set<string>(app.extensions || []);\n this.systemRequiredExtensions.forEach(extId => extensionsSet.add(extId));\n app.extensions = Array.from(extensionsSet);\n\n // At this point, all core/built-in extension modules and app contributions\n // have been registered. It is now safe for the extension registry to\n // load any extensions that are marked as enabled in settings (including\n // persisted external extensions).\n this.dispatchLoadProgress('Loading extensions…');\n await extensionRegistry.loadEnabledExtensions();\n\n // Enable and load app extensions so commands/contributions are registered before UI is shown\n if (app.extensions.length > 0) {\n this.dispatchLoadProgress('Enabling extensions…');\n await Promise.all(\n app.extensions.map((extId) =>\n extensionRegistry.enableAsync(extId).catch((e) => {\n logger.error(`Failed to load extension ${extId}: ${getErrorMessage(e)}`);\n })\n )\n );\n }\n\n // Initialize new app\n if (app.initialize) {\n this.dispatchLoadProgress('Initializing…');\n logger.info(`Initializing ${app.name}...`);\n await app.initialize();\n }\n\n this.currentApp = app;\n logger.info(`App ${app.name} loaded successfully`);\n this.preferredLayoutId = await this.getPreferredLayoutId();\n this.updateDocumentMetadata(app);\n if (container) {\n this.dispatchLoadProgress('Rendering layout…');\n this.renderApp(container);\n }\n\n // Dispatch event for components to react to app changes\n window.dispatchEvent(new CustomEvent('app-loaded', { detail: { appName: app.name } }));\n }\n \n /**\n * Updates document title and favicon from app metadata\n */\n private updateDocumentMetadata(app: AppDefinition): void {\n document.title = app.name ?? '';\n \n // Set favicon if provided in metadata\n if (app.metadata?.favicon) {\n const faviconPath = app.metadata.favicon;\n let link = document.querySelector(\"link[rel*='icon']\") as HTMLLinkElement;\n if (!link) {\n link = document.createElement('link');\n link.rel = 'icon';\n document.head.appendChild(link);\n }\n link.type = 'image/svg+xml';\n link.href = faviconPath;\n }\n }\n \n /**\n * Render the current application to the DOM.\n * Resolves the layout by layoutId (default 'standard'), renders its component, then calls layout.onShow if defined.\n *\n * @param container - DOM element to render into\n */\n renderApp(container: HTMLElement): void {\n if (!this.currentApp) {\n throw new Error('No app loaded. Call loadApp() first.');\n }\n\n const layoutId = this.preferredLayoutId ?? getLayoutIdFromApp(this.currentApp);\n const layouts = contributionRegistry.getContributions<LayoutContribution>(SYSTEM_LAYOUTS);\n let layout = layouts.find((c) => c.id === layoutId);\n if (!layout) {\n logger.warn(`Layout '${layoutId}' not found, falling back to 'standard'`);\n layout = layouts.find((c) => c.id === 'standard');\n }\n if (!layout) {\n throw new Error(`No layout found for layoutId '${layoutId}' and no 'standard' layout registered.`);\n }\n\n const r = layout.component;\n let effectiveAttributes: Record<string, string> = {};\n if (r && typeof r === 'object' && 'tag' in r && r.attributes) {\n effectiveAttributes = { ...r.attributes };\n }\n const appLayout = this.currentApp?.layout;\n if (typeof appLayout === 'object' && appLayout.id === layoutId && appLayout.props) {\n Object.assign(effectiveAttributes, propsToAttributes(appLayout.props));\n }\n\n container.innerHTML = '';\n if (typeof r === 'string') {\n const el = document.createElement(r);\n for (const [key, value] of Object.entries(effectiveAttributes)) {\n el.setAttribute(key, value);\n }\n container.appendChild(el);\n } else if (r && typeof r === 'object' && 'tag' in r) {\n const el = document.createElement(r.tag);\n for (const [key, value] of Object.entries(effectiveAttributes)) {\n el.setAttribute(key, value);\n }\n container.appendChild(el);\n } else if (typeof r === 'function') {\n render(r(), container);\n } else {\n throw new Error(`Layout '${layout.id}' has invalid component.`);\n }\n\n if (layout.onShow) {\n requestAnimationFrame(() => {\n void Promise.resolve(layout!.onShow!()).catch((err) =>\n logger.error(`Layout onShow failed for '${layout!.id}': ${getErrorMessage(err)}`)\n );\n });\n }\n }\n \n /**\n * Get the currently loaded application.\n */\n getCurrentApp(): AppDefinition | undefined {\n return this.currentApp;\n }\n \n /**\n * Get all registered applications.\n */\n getRegisteredApps(): AppDefinition[] {\n return Array.from(this.apps.values());\n }\n \n /**\n * Get the preferred app ID from settings.\n */\n async getPreferredAppId(): Promise<string | undefined> {\n try {\n return await appSettings.get(AppLoaderService.PREFERRED_APP_KEY);\n } catch (error) {\n logger.debug(`Failed to get preferred app ID from settings: ${getErrorMessage(error)}`);\n return undefined;\n }\n }\n \n /**\n * Set the preferred app ID and persist it to settings.\n */\n async setPreferredAppId(appId: string): Promise<void> {\n if (!this.apps.has(appId)) {\n throw new Error(`App '${appId}' not found. Make sure it's registered.`);\n }\n try {\n await appSettings.set(AppLoaderService.PREFERRED_APP_KEY, appId);\n this.defaultAppName = appId;\n logger.info(`Set preferred app to: ${appId}`);\n } catch (error) {\n logger.error(`Failed to persist preferred app: ${getErrorMessage(error)}`);\n throw error;\n }\n }\n\n getRegisteredLayouts(): LayoutContribution[] {\n return contributionRegistry.getContributions<LayoutContribution>(SYSTEM_LAYOUTS);\n }\n\n getCurrentLayoutId(): string {\n return this.preferredLayoutId ?? getLayoutIdFromApp(this.currentApp);\n }\n\n async getPreferredLayoutId(): Promise<string | undefined> {\n try {\n return await appSettings.get(AppLoaderService.PREFERRED_LAYOUT_KEY);\n } catch (error) {\n logger.debug(`Failed to get preferred layout ID: ${getErrorMessage(error)}`);\n return undefined;\n }\n }\n\n async setPreferredLayoutId(layoutId: string): Promise<void> {\n const layouts = this.getRegisteredLayouts();\n if (!layouts.some((l) => l.id === layoutId)) {\n throw new Error(`Layout '${layoutId}' not found.`);\n }\n try {\n await appSettings.set(AppLoaderService.PREFERRED_LAYOUT_KEY, layoutId);\n this.preferredLayoutId = layoutId;\n logger.info(`Set preferred layout to: ${layoutId}`);\n if (this.currentApp && this.container) {\n this.renderApp(this.container);\n }\n window.dispatchEvent(new CustomEvent('layout-changed', { detail: { layoutId } }));\n } catch (error) {\n logger.error(`Failed to persist preferred layout: ${getErrorMessage(error)}`);\n throw error;\n }\n }\n \n /**\n * Select which app to load based on priority:\n * 1. appId URL parameter (?appId=...)\n * 2. App from current page URL path (/my-app)\n * 3. Preferred app from settings\n * 4. Default app\n * 5. First registered app\n */\n private async selectAppToLoad(options: {\n appIdFromUrl: string | null;\n appIdFromPath: string | undefined;\n }): Promise<string | undefined> {\n const { appIdFromUrl, appIdFromPath } = options;\n\n if (appIdFromUrl) {\n const name = this.findAppNameBySegment(appIdFromUrl) ?? appIdFromUrl;\n if (this.apps.has(name)) {\n logger.info(`Loading app specified by URL parameter 'appId': ${name}`);\n return name;\n }\n logger.warn(`App '${appIdFromUrl}' from URL parameter not found`);\n }\n\n if (appIdFromPath) {\n const name = this.findAppNameBySegment(appIdFromPath);\n if (name) {\n logger.info(`Loading app from URL path: ${appIdFromPath}`);\n return name;\n }\n logger.debug(`App for path '${appIdFromPath}' not found, continuing search`);\n }\n\n const preferred = await this.getPreferredAppId();\n if (preferred && this.apps.has(preferred)) {\n logger.info(`Loading preferred app from settings: ${preferred}`);\n return preferred;\n }\n\n if (this.defaultAppName && this.apps.has(this.defaultAppName)) {\n return this.defaultAppName;\n }\n if (this.defaultAppName) {\n logger.warn(`Default app '${this.defaultAppName}' not found`);\n }\n\n const registeredApps = this.getRegisteredApps();\n if (registeredApps.length > 0) {\n const app = registeredApps[0];\n return app.name;\n }\n\n return undefined;\n }\n}\n\nexport const appLoaderService = new AppLoaderService();\nrootContext.put(\"appLoaderService\", appLoaderService);\n\n","import { html, css, PropertyValues } from \"lit\";\nimport { customElement, state, property } from \"lit/decorators.js\";\nimport { DocksDialogContent } from \"../parts/dialog-content\";\nimport { contributionRegistry } from \"../core/contributionregistry\";\nimport { DIALOG_CONTRIBUTION_TARGET, OK_BUTTON, CANCEL_BUTTON, DialogContribution, dialogService } from \"../core/dialogservice\";\n\n@customElement('docks-prompt-dialog-content')\nexport class DocksPromptDialogContent extends DocksDialogContent {\n @property({ type: String })\n message: string = '';\n\n @property({ type: String, attribute: 'default-value' })\n defaultValue: string = '';\n\n @property({ type: Boolean })\n markdown: boolean = false;\n\n @state()\n private inputValue: string = '';\n\n static styles = [\n ...DocksDialogContent.styles,\n css`\n wa-input {\n width: 100%;\n }\n `\n ];\n\n async firstUpdated(changedProperties: PropertyValues) {\n super.firstUpdated(changedProperties);\n this.inputValue = this.defaultValue;\n\n await this.updateComplete;\n const input = this.shadowRoot?.querySelector('wa-input');\n if (input) {\n const inputEl = (input as any).shadowRoot?.querySelector('input');\n if (inputEl) {\n inputEl.focus();\n inputEl.select();\n }\n }\n }\n\n getResult(): string | null {\n return this.inputValue;\n }\n\n private handleInput(e: Event) {\n this.inputValue = (e.target as any).value;\n }\n\n private handleKeyDown(e: KeyboardEvent) {\n if (e.key === 'Enter') {\n e.preventDefault();\n this.dispatchEvent(new CustomEvent('dialog-ok', { bubbles: true, composed: true }));\n } else if (e.key === 'Escape') {\n e.preventDefault();\n this.dispatchEvent(new CustomEvent('dialog-cancel', { bubbles: true, composed: true }));\n }\n }\n\n render() {\n return html`\n ${this.renderMessage(this.message, this.markdown)}\n <wa-input\n value=\"${this.inputValue}\"\n @input=${this.handleInput}\n @keydown=${this.handleKeyDown}\n autofocus\n ></wa-input>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'docks-prompt-dialog-content': DocksPromptDialogContent;\n }\n}\n\ncontributionRegistry.registerContribution(DIALOG_CONTRIBUTION_TARGET, {\n id: 'prompt',\n label: 'Input',\n buttons: [OK_BUTTON, CANCEL_BUTTON],\n component: (state?: any) => {\n if (!state) {\n return html`<div>Error: No prompt dialog state</div>`;\n }\n \n return html`\n <docks-prompt-dialog-content \n .message=\"${state.message}\"\n .defaultValue=\"${state.defaultValue}\"\n .markdown=\"${state.markdown}\"\n ></docks-prompt-dialog-content>\n `;\n },\n onButton: async (id: string, result: any, state?: any) => {\n if (!state) {\n return true;\n }\n \n if (id === 'ok') {\n state.resolve(result || '');\n } else {\n state.resolve(null);\n }\n \n return true;\n }\n});\n\nexport async function promptDialog(message: string, defaultValue: string = '', markdown: boolean = false): Promise<string | null> {\n return new Promise((resolve) => {\n dialogService.open('prompt', {\n message,\n defaultValue,\n markdown,\n resolve\n });\n });\n}","import { html } from \"lit\";\nimport { customElement, property } from \"lit/decorators.js\";\nimport { DocksDialogContent } from \"../parts/dialog-content\";\nimport { contributionRegistry } from \"../core/contributionregistry\";\nimport { DIALOG_CONTRIBUTION_TARGET, OK_BUTTON, DialogContribution, dialogService } from \"../core/dialogservice\";\n\n@customElement('docks-info-dialog-content')\nexport class DocksInfoDialogContent extends DocksDialogContent {\n @property({ type: String })\n message: string = '';\n\n @property({ type: Boolean })\n markdown: boolean = false;\n\n render() {\n return html`\n ${this.renderMessage(this.message, this.markdown)}\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'docks-info-dialog-content': DocksInfoDialogContent;\n }\n}\n\ncontributionRegistry.registerContribution(DIALOG_CONTRIBUTION_TARGET, {\n id: 'info',\n label: 'Information',\n buttons: [OK_BUTTON],\n component: (state?: any) => {\n if (!state) {\n return html`<div>Error: No info dialog state</div>`;\n }\n \n return html`\n <docks-info-dialog-content \n .message=\"${state.message}\"\n .markdown=\"${state.markdown}\"\n ></docks-info-dialog-content>\n `;\n },\n onButton: async (id: string, result: any, state?: any) => {\n if (!state) {\n return true;\n }\n \n if (state.resolve) {\n state.resolve();\n }\n \n return true;\n }\n});\n\nexport async function infoDialog(title: string, message: string, markdown: boolean = false): Promise<void> {\n return new Promise((resolve) => {\n dialogService.open('info', {\n title,\n message,\n markdown,\n resolve\n });\n });\n}\n\n","import { html } from \"lit\";\nimport { customElement, property } from \"lit/decorators.js\";\nimport { DocksDialogContent } from \"../parts/dialog-content\";\nimport { contributionRegistry } from \"../core/contributionregistry\";\nimport { DIALOG_CONTRIBUTION_TARGET, OK_BUTTON, CANCEL_BUTTON, DialogContribution, dialogService } from \"../core/dialogservice\";\n\n@customElement('docks-confirm-dialog-content')\nexport class DocksConfirmDialogContent extends DocksDialogContent {\n @property({ type: String })\n message: string = '';\n\n @property({ type: Boolean })\n markdown: boolean = false;\n\n getResult(): boolean {\n return false;\n }\n\n render() {\n return html`\n ${this.renderMessage(this.message, this.markdown)}\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'docks-confirm-dialog-content': DocksConfirmDialogContent;\n }\n}\n\ncontributionRegistry.registerContribution(DIALOG_CONTRIBUTION_TARGET, {\n id: 'confirm',\n label: 'Confirm',\n buttons: [OK_BUTTON, CANCEL_BUTTON],\n component: (state?: any) => {\n if (!state) {\n return html`<div>Error: No confirm dialog state</div>`;\n }\n \n return html`\n <docks-confirm-dialog-content \n .message=\"${state.message}\"\n .markdown=\"${state.markdown}\"\n ></docks-confirm-dialog-content>\n `;\n },\n onButton: async (id: string, result: any, state?: any) => {\n if (!state) {\n return true;\n }\n \n if (id === 'ok') {\n state.resolve(true);\n } else {\n state.resolve(false);\n }\n \n return true;\n }\n});\n\nexport async function confirmDialog(message: string, markdown: boolean = false): Promise<boolean> {\n return new Promise((resolve) => {\n dialogService.open('confirm', {\n message,\n markdown,\n resolve\n });\n });\n}\n\n","import { html, css, PropertyValues } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\nimport { DocksDialogContent } from \"../parts/dialog-content\";\nimport { contributionRegistry } from \"../core/contributionregistry\";\nimport { DIALOG_CONTRIBUTION_TARGET, CLOSE_BUTTON, DialogContribution, dialogService } from \"../core/dialogservice\";\n\nexport interface NavigableDialogAction {\n label: string;\n variant?: 'default' | 'primary' | 'success' | 'neutral' | 'warning' | 'danger';\n disabled?: boolean;\n callback: () => void;\n}\n\n@customElement('docks-navigable-info-dialog-content')\nexport class DocksNavigableInfoDialogContent extends DocksDialogContent {\n @property({ type: String })\n title: string = '';\n\n @property({ type: String })\n message: string = '';\n\n @property({ type: Boolean })\n markdown: boolean = false;\n\n @state()\n actions: NavigableDialogAction[] = [];\n\n @state()\n private currentTitle: string = '';\n\n @state()\n private currentMessage: string = '';\n\n resolveCallback?: () => void;\n private dialogElement: HTMLElement | null = null;\n\n async firstUpdated(changedProperties: PropertyValues) {\n super.firstUpdated(changedProperties);\n this.currentTitle = this.title;\n this.currentMessage = this.message;\n \n await this.updateComplete;\n const dialog = this.closest('wa-dialog');\n if (dialog) {\n this.dialogElement = dialog as HTMLElement;\n this.updateDialogLabel();\n }\n \n const contentContainer = this.closest('.dialog-service-content');\n if (contentContainer) {\n const footer = contentContainer.parentElement?.querySelector('.dialog-service-footer');\n if (footer) {\n (footer as HTMLElement).style.display = 'none';\n }\n }\n }\n\n updated(changedProperties: PropertyValues) {\n super.updated(changedProperties);\n if (changedProperties.has('title')) {\n this.currentTitle = this.title;\n this.updateDialogLabel();\n }\n if (changedProperties.has('message')) {\n this.currentMessage = this.message;\n }\n }\n\n private updateDialogLabel() {\n if (this.dialogElement) {\n this.dialogElement.setAttribute('label', this.currentTitle);\n }\n }\n\n updateDialog(newTitle: string, newMessage: string, newActions: NavigableDialogAction[]) {\n this.currentTitle = newTitle;\n this.currentMessage = newMessage;\n this.actions = [...newActions];\n this.updateDialogLabel();\n this.requestUpdate();\n }\n\n private handleActionClick(action: NavigableDialogAction) {\n action.callback();\n }\n\n private handleClose() {\n const dialog = this.closest('wa-dialog');\n if (dialog && this.resolveCallback) {\n this.resolveCallback();\n }\n }\n\n static styles = [\n ...DocksDialogContent.styles,\n css`\n :host {\n display: block;\n }\n\n :host-context(.dialog-service-content) {\n padding: 0;\n }\n \n .dialog-content {\n display: flex;\n flex-direction: column;\n gap: 1rem;\n min-width: 400px;\n max-width: 600px;\n height: 500px;\n padding: 1rem;\n }\n \n .dialog-scroller {\n flex: 1;\n overflow-y: auto;\n }\n \n .dialog-actions {\n display: flex;\n gap: 0.5rem;\n justify-content: space-between;\n margin-top: 0.5rem;\n }\n \n .dialog-actions-left,\n .dialog-actions-right {\n display: flex;\n gap: 0.5rem;\n }\n `\n ];\n\n render() {\n const leftActions = this.actions.filter(a => a.label !== 'Close');\n const rightActions = this.actions.filter(a => a.label === 'Close');\n\n return html`\n <div class=\"dialog-content\">\n <wa-scroller class=\"dialog-scroller\">\n ${this.renderMessage(this.currentMessage, this.markdown)}\n </wa-scroller>\n \n <div class=\"dialog-actions\">\n <div class=\"dialog-actions-left\">\n ${leftActions.map(action => html`\n <wa-button \n variant=\"${action.variant || 'default'}\"\n ?disabled=${action.disabled}\n @click=${() => this.handleActionClick(action)}\n >\n ${action.label}\n </wa-button>\n `)}\n </div>\n <div class=\"dialog-actions-right\">\n ${rightActions.map(action => html`\n <wa-button \n variant=\"${action.variant || 'primary'}\"\n @click=${() => {\n this.handleActionClick(action);\n this.handleClose();\n }}\n >\n ${action.label}\n </wa-button>\n `)}\n </div>\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'docks-navigable-info-dialog-content': DocksNavigableInfoDialogContent;\n }\n}\n\ncontributionRegistry.registerContribution(DIALOG_CONTRIBUTION_TARGET, {\n id: 'navigable-info',\n label: 'Information',\n buttons: [CLOSE_BUTTON],\n component: (state?: any) => {\n if (!state) {\n return html`<div>Error: No navigable info dialog state</div>`;\n }\n \n const componentHtml = html`\n <docks-navigable-info-dialog-content \n .title=\"${state.title}\"\n .message=\"${state.message}\"\n .markdown=\"${state.markdown}\"\n ></docks-navigable-info-dialog-content>\n `;\n \n (async () => {\n const element = document.querySelector('docks-navigable-info-dialog-content') as DocksNavigableInfoDialogContent;\n if (element) {\n await element.updateComplete;\n element.actions = state.actions || [];\n element.resolveCallback = state.resolve;\n if (state.updateDialogRef) {\n state.updateDialogRef.current = (newTitle: string, newMessage: string, newActions: NavigableDialogAction[]) => {\n element.updateDialog(newTitle, newMessage, newActions);\n };\n }\n }\n })();\n \n return componentHtml;\n },\n onButton: async (id: string, result: any, state?: any) => {\n if (!state) {\n return false;\n }\n \n if (id === 'close' && state.resolve) {\n state.resolve();\n return true;\n }\n \n return false;\n }\n});\n\nexport async function navigableInfoDialog(\n title: string,\n message: string,\n actions: NavigableDialogAction[],\n markdown: boolean = false\n): Promise<void> {\n return new Promise((resolve) => {\n const updateDialogRef: { current?: (title: string, message: string, actions: NavigableDialogAction[]) => void } = {};\n \n dialogService.open('navigable-info', {\n title,\n message,\n actions,\n markdown,\n resolve,\n updateDialogRef\n });\n\n const updateDialog = (newTitle: string, newMessage: string, newActions: NavigableDialogAction[]) => {\n if (updateDialogRef.current) {\n updateDialogRef.current(newTitle, newMessage, newActions);\n }\n };\n\n (actions as any).updateDialog = updateDialog;\n });\n}\n\n","import { html, css } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\nimport { DocksDialogContent } from \"../parts/dialog-content\";\nimport type { PropertyValues } from \"lit\";\nimport { contributionRegistry } from \"../core/contributionregistry\";\nimport {\n DIALOG_CONTRIBUTION_TARGET,\n OK_BUTTON,\n CANCEL_BUTTON,\n type DialogContribution,\n dialogService,\n} from \"../core/dialogservice\";\nimport { Directory, File, type Resource, workspaceService } from \"../core/filesys\";\n\nexport type FilebrowserDialogMode = \"file\" | \"directory\" | \"either\";\n\n@customElement(\"docks-filebrowser-dialog\")\nexport class DocksFilebrowserDialog extends DocksDialogContent {\n @property({ type: String })\n mode: FilebrowserDialogMode = \"either\";\n\n @state()\n private selectedPath: string | null = null;\n\n @state()\n private rootNodes: TreeNode[] = [];\n\n @state()\n private loading = false;\n\n @state()\n private loadError: string | null = null;\n\n static styles = [\n ...DocksDialogContent.styles,\n css`\n :host {\n min-width: 0;\n overflow-x: hidden;\n display: block;\n }\n\n .dialog-body {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n min-width: 0;\n min-height: 320px;\n max-height: 600px;\n overflow-x: hidden;\n }\n\n .browser-container {\n flex: 1;\n min-height: 240px;\n min-width: 0;\n overflow: hidden;\n overflow-x: hidden;\n }\n\n .browser-container wa-tree {\n min-width: 0;\n overflow-x: hidden;\n }\n\n .tree-label {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n }\n\n .selection-info {\n font-size: 0.85em;\n opacity: 0.8;\n }\n `,\n ];\n\n protected async doInitUI() {\n await this.loadWorkspaceTree();\n }\n\n firstUpdated(changed: PropertyValues) {\n super.firstUpdated?.(changed);\n const dialog = this.closest(\"wa-dialog\");\n if (dialog) dialog.setAttribute(\"label\", this.dialogTitle);\n }\n\n updated(changed: PropertyValues) {\n super.updated?.(changed);\n if (changed.has(\"mode\")) {\n const dialog = this.closest(\"wa-dialog\");\n if (dialog) dialog.setAttribute(\"label\", this.dialogTitle);\n }\n }\n\n private get dialogTitle(): string {\n if (this.mode === \"file\") return \"Choose a file\";\n if (this.mode === \"directory\") return \"Choose a directory\";\n return \"Choose a file or directory\";\n }\n\n getResult(): string | null {\n return this.selectedPath != null ? \"/\" + this.selectedPath : null;\n }\n\n private async loadWorkspaceTree() {\n this.loading = true;\n this.loadError = null;\n try {\n const workspaceDir = await workspaceService.getWorkspace();\n if (!workspaceDir) {\n this.rootNodes = [];\n return;\n }\n const children = await workspaceDir.listChildren(false);\n const nodes: TreeNode[] = [];\n for (const child of children) {\n nodes.push(await this.resourceToTreeNode(child, false));\n }\n nodes.sort((a, b) => a.label.localeCompare(b.label));\n this.rootNodes = nodes;\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n this.loadError = msg;\n this.rootNodes = [];\n } finally {\n this.loading = false;\n }\n }\n\n private async resourceToTreeNode(resource: Resource, loadChildren = true): Promise<TreeNode> {\n const isFile = resource instanceof File;\n const node: TreeNode = {\n resource,\n label: resource.getName(),\n leaf: isFile,\n children: [],\n };\n\n if (resource instanceof Directory && loadChildren) {\n for (const child of await resource.listChildren(false)) {\n node.children.push(await this.resourceToTreeNode(child, false));\n }\n node.children.sort((a, b) => a.label.localeCompare(b.label));\n }\n\n return node;\n }\n\n private handleSelectionChange(e: CustomEvent) {\n const selection = (e.detail && (e.detail as any).selection) || [];\n if (!selection || selection.length === 0) {\n this.selectedPath = null;\n this.requestUpdate();\n return;\n }\n\n const node = selection[0]?.model as TreeNode | undefined;\n const resource = node?.resource;\n if (!resource) {\n this.selectedPath = null;\n this.requestUpdate();\n return;\n }\n\n const isDir = resource instanceof Directory;\n const isFile = resource instanceof File;\n if (this.mode === \"file\" && !isFile) {\n this.selectedPath = null;\n this.requestUpdate();\n return;\n }\n if (this.mode === \"directory\" && isFile) {\n const parent = (resource as File).getParent?.() as Directory | undefined;\n this.selectedPath = parent ? parent.getWorkspacePath() : null;\n this.requestUpdate();\n return;\n }\n if (this.mode === \"directory\" && !isDir) {\n this.selectedPath = null;\n this.requestUpdate();\n return;\n }\n const path = (resource as any).getWorkspacePath?.();\n this.selectedPath = typeof path === \"string\" ? path : null;\n this.requestUpdate();\n }\n\n private renderTreeNode(node: TreeNode): unknown {\n return html`\n <wa-tree-item .model=${node} ?leaf=${node.leaf}>\n ${node.label}\n ${node.children.map((child) => this.renderTreeNode(child))}\n </wa-tree-item>\n `;\n }\n\n render() {\n return html`\n <div class=\"dialog-body\">\n ${this.loadError ? this.renderMessage(this.loadError, false) : null}\n\n <div class=\"browser-container\">\n ${this.loading\n ? html`<div>Loading workspace…</div>`\n : this.rootNodes.length > 0\n ? html`\n <wa-tree @wa-selection-change=${(e: Event) => this.handleSelectionChange(e as CustomEvent)}>\n ${this.rootNodes.map((node) => this.renderTreeNode(node))}\n </wa-tree>\n `\n : html`<div>No workspace folders.</div>`}\n </div>\n\n <div class=\"selection-info\">\n ${this.selectedPath ? `Selected path: ${this.selectedPath}` : \"No path selected yet.\"}\n </div>\n </div>\n `;\n }\n}\n\ninterface TreeNode {\n resource: Resource;\n label: string;\n leaf: boolean;\n children: TreeNode[];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"docks-filebrowser-dialog\": DocksFilebrowserDialog;\n }\n}\n\nexport interface FilebrowserDialogState {\n resolve: (path: string | null) => void;\n mode?: FilebrowserDialogMode;\n}\n\ncontributionRegistry.registerContribution<DialogContribution>(DIALOG_CONTRIBUTION_TARGET, {\n id: \"filebrowser-dialog\",\n label: \"Select Path\",\n buttons: [OK_BUTTON, CANCEL_BUTTON],\n component: (state?: FilebrowserDialogState) =>\n html`<docks-filebrowser-dialog .mode=${state?.mode ?? \"either\"}></docks-filebrowser-dialog>`,\n onButton: async (id: string, result: any, state?: FilebrowserDialogState) => {\n if (!state) return true;\n if (id === \"ok\") {\n state.resolve(result || null);\n } else {\n state.resolve(null);\n }\n return true;\n },\n});\n\nexport function filebrowserDialog(mode: FilebrowserDialogMode = \"either\"): Promise<string | null> {\n return new Promise((resolve) => {\n dialogService.open(\"filebrowser-dialog\", { resolve, mode });\n });\n}\n\n","import { html, nothing } from 'lit';\nimport type { TemplateResult } from 'lit';\n\nexport interface ParsedIconSpec {\n name: string;\n library?: string;\n}\n\nexport interface IconOptions {\n label?: string;\n slot?: string;\n}\n\n/**\n * Parses an icon spec string into `{ library, name }` for use with `wa-icon`.\n *\n * Icon specs support an optional icon library prefix followed by the icon name,\n * separated by whitespace, e.g. `\"docks mark-github\"`.\n *\n * - When the spec contains **no whitespace**, it is treated as the icon name only\n * and `library` is omitted so the default Web Awesome / Font Awesome library is used.\n * - When the spec contains **whitespace**, the **last segment** is treated as\n * the icon name and every prior segment (joined by a single space) becomes `library`.\n *\n * Prefer {@link icon} for rendering; use parseIconSpec only when you need the parsed parts.\n */\nexport function parseIconSpec(spec: string): ParsedIconSpec {\n const trimmed = (spec ?? '').trim();\n if (!trimmed) return { name: '' };\n const parts = trimmed.split(/\\s+/);\n if (parts.length <= 1) return { name: trimmed };\n const name = parts.pop()!;\n const library = parts.join(' ');\n return { name, library };\n}\n\n/**\n * Returns a Lit template that renders a `wa-icon` for the given spec.\n * Use this for all icon rendering so specs (e.g. contribution `icon` fields) stay consistent.\n * Handles undefined/null/empty spec internally; call sites may pass values directly.\n */\nexport function icon(spec: string | undefined | null, options?: IconOptions): TemplateResult {\n const { name: iconName, library } = parseIconSpec(spec ?? '');\n return html`<wa-icon library=${library ?? nothing} name=${iconName} label=${options?.label ?? nothing} slot=${options?.slot ?? nothing}></wa-icon>`;\n}\n","import {css, html, nothing} from 'lit'\nimport {customElement, property, state} from 'lit/decorators.js'\nimport {DocksElement} from \"./element\";\nimport {styleMap} from 'lit/directives/style-map.js';\nimport {\n CommandContribution,\n Contribution,\n ContributionChangeEvent,\n contributionRegistry,\n HTMLContribution,\n TOPIC_CONTRIBUTEIONS_CHANGED\n} from \"../core/contributionregistry\";\nimport {Signal} from '@lit-labs/signals';\nimport {unsafeHTML} from \"lit/directives/unsafe-html.js\";\nimport {subscribe} from \"../core/events\";\nimport { icon } from \"../core/icon-utils\";\n\nconst RESIZE_DEBOUNCE_MS = 150;\n\ntype ToolbarSlotName = 'start' | undefined | 'end';\n\nfunction renderButtonGroup(\n slotName: ToolbarSlotName,\n orientation: 'horizontal' | 'vertical',\n contributions: Contribution[],\n isToolbarItem: (c: Contribution) => boolean,\n contributionCreator: (c: Contribution) => unknown\n) {\n const slot = slotName ?? 'default';\n const label = `Toolbar ${slot}`;\n const items = contributions.filter(c => c.slot === slotName && isToolbarItem(c));\n const slotHtml = slotName === 'start'\n ? html`<slot name=\"start\"></slot>`\n : slotName === 'end'\n ? html`<slot name=\"end\"></slot>`\n : html`<slot></slot>`;\n return html`\n <wa-button-group orientation=${orientation} label=${label}>\n ${slotHtml}\n ${items.map(contributionCreator)}\n </wa-button-group>\n `;\n}\n\n@customElement('docks-toolbar')\nexport class DocksToolbar extends DocksElement {\n @property()\n private position: \"start\" | \"center\" | \"end\" = \"start\";\n\n @property({reflect: true})\n orientation: \"horizontal\" | \"vertical\" = \"horizontal\";\n\n @property({reflect: true})\n align: \"start\" | \"center\" | \"end\" = \"start\";\n\n @property({reflect: true})\n size: \"small\" | \"medium\" | \"large\" = \"small\";\n\n @property({attribute: false})\n scopeTokens: string[] = [];\n\n @property({attribute: false})\n public partToolbarContent?: any = undefined;\n\n @property({attribute: false})\n public partToolbarRenderer?: () => any = undefined;\n\n @state()\n private contributions: Contribution[] = [];\n\n @state()\n private compact = false;\n\n private resizeObserver: ResizeObserver | null = null;\n private resizeDebounceTimer: ReturnType<typeof setTimeout> | null = null;\n private overflowCheckScheduled = false;\n\n private updateCompactFromSpace() {\n const toolbarItems = this.shadowRoot?.querySelector('.toolbar-items') as HTMLElement | null;\n if (!toolbarItems) return;\n const trimmed = toolbarItems.scrollWidth > toolbarItems.clientWidth;\n if (this.compact !== trimmed) {\n this.compact = trimmed;\n this.requestUpdate();\n }\n }\n\n private scheduleOverflowCheck() {\n if (this.overflowCheckScheduled) return;\n this.overflowCheckScheduled = true;\n requestAnimationFrame(() => {\n this.overflowCheckScheduled = false;\n this.updateCompactFromSpace();\n });\n }\n\n private onResize = () => {\n if (this.resizeDebounceTimer !== null) clearTimeout(this.resizeDebounceTimer);\n this.resizeDebounceTimer = setTimeout(() => {\n this.resizeDebounceTimer = null;\n this.updateCompactFromSpace();\n }, RESIZE_DEBOUNCE_MS);\n };\n\n connectedCallback() {\n super.connectedCallback();\n this.resizeObserver = new ResizeObserver(this.onResize);\n this.resizeObserver.observe(this);\n }\n\n disconnectedCallback() {\n this.resizeObserver?.disconnect();\n this.resizeObserver = null;\n if (this.resizeDebounceTimer !== null) {\n clearTimeout(this.resizeDebounceTimer);\n this.resizeDebounceTimer = null;\n }\n super.disconnectedCallback();\n }\n\n updated(changedProperties: Map<string, unknown>) {\n super.updated?.(changedProperties);\n if (!this.compact) this.scheduleOverflowCheck();\n if (changedProperties.has('scopeTokens')) {\n this.refreshContributions();\n }\n }\n\n attributeChangedCallback(name: string, old: string | null, value: string | null) {\n super.attributeChangedCallback(name, old, value);\n if (name === 'id' && old !== value) {\n this.refreshContributions();\n }\n }\n\n protected doBeforeUI() {\n this.refreshContributions();\n \n subscribe(TOPIC_CONTRIBUTEIONS_CHANGED, (event: ContributionChangeEvent) => {\n const id = this.getAttribute(\"id\");\n if (!id) return;\n \n const shouldReload = this.matchesTarget(id, event.target);\n if (shouldReload) {\n this.refreshContributions();\n this.requestUpdate()\n }\n })\n }\n\n private refreshContributions() {\n const id = this.getAttribute(\"id\");\n if (!id) {\n this.contributions = [];\n return;\n }\n this.loadContributions(id);\n }\n\n\n private matchesTarget(id: string, target: string): boolean {\n if (target === id) return true;\n \n if (!id.includes(':')) return false;\n \n const [prefix] = id.split(':');\n if (target === `${prefix}:*`) return true;\n \n const targetParts = target.split(':');\n if (targetParts.length === 2) {\n const categoryToken = targetParts[1];\n if (this.scopeTokens.includes(categoryToken)) {\n return id.startsWith(`${prefix}:`);\n }\n }\n \n return false;\n }\n\n private loadContributions(id: string) {\n const specific = contributionRegistry.getContributions(id);\n \n if (!id.includes(':')) {\n this.contributions = specific;\n return;\n }\n \n const [prefix] = id.split(':');\n const wildcardId = `${prefix}:*`;\n const wildcard = contributionRegistry.getContributions(wildcardId);\n \n const categoryMatches: Contribution[] = [];\n\n for (const category of this.scopeTokens) {\n const categoryId = `${prefix}:${category}`;\n const matches = contributionRegistry.getContributions(categoryId);\n categoryMatches.push(...matches);\n }\n \n this.contributions = [...wildcard, ...categoryMatches, ...specific];\n }\n\n private isToolbarItem(contribution: Contribution): boolean {\n return \"command\" in contribution || \"component\" in contribution;\n }\n\n contributionCreator(contribution: Contribution) {\n if (\"command\" in contribution) {\n const commandContribution = contribution as CommandContribution;\n const showLabel = !this.compact && !!commandContribution.showLabel;\n return html`\n <wa-button @click=${() => void this.executeCommand(commandContribution.command, commandContribution.params || {})}\n title=${commandContribution.label}\n ?disabled=\"${(commandContribution.disabled as Signal.Computed<boolean>)?.get()}\"\n appearance=\"plain\" size=${this.size}>\n ${icon(commandContribution.icon, { label: commandContribution.label })}\n ${showLabel ? commandContribution.label : ''}\n </wa-button>\n `;\n }\n if (\"component\" in contribution) {\n const contents = (contribution as HTMLContribution).component\n if (contents instanceof Function) {\n return contents()\n }\n return unsafeHTML(contents)\n }\n return html`<span>unknown contribution type: ${typeof contribution}</span>`\n }\n\n render() {\n const partContent = this.partToolbarRenderer ? this.partToolbarRenderer() :\n (this.partToolbarContent ? this.partToolbarContent : '');\n const flexDir = this.orientation === \"vertical\" ? \"column\" : \"row\";\n const alignMap = { start: \"flex-start\", center: \"center\", end: \"flex-end\" } as const;\n const bindCreator = this.contributionCreator.bind(this);\n const bindIsItem = this.isToolbarItem.bind(this);\n return html`\n <div class=\"toolbar-items\" style=${styleMap({\n \"flex-direction\": flexDir,\n \"align-items\": alignMap[this.align],\n \"justify-content\": this.position\n })}>\n ${renderButtonGroup('start', this.orientation, this.contributions, bindIsItem, bindCreator)}\n ${partContent}\n ${renderButtonGroup(undefined, this.orientation, this.contributions, bindIsItem, bindCreator)}\n ${renderButtonGroup('end', this.orientation, this.contributions, bindIsItem, bindCreator)}\n </div>\n `;\n }\n\n static styles = css`\n :host {\n display: flex;\n flex-direction: row;\n --wa-form-control-padding-inline: var(--wa-space-2xs);\n }\n\n :host([orientation=\"vertical\"]) {\n flex-direction: column;\n }\n\n .toolbar-items {\n display: flex;\n flex: 1;\n gap: var(--wa-space-2xs);\n }\n `\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'docks-toolbar': DocksToolbar\n }\n}\n","import { css, html, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { DocksWidget } from '../widgets/widget'\nimport { icon } from '../core/icon-utils'\nimport { keyBindingManager } from '../core/keybindings'\nimport { contributionRegistry, Contribution, CommandContribution, HTMLContribution, ContributionChangeEvent, TOPIC_CONTRIBUTEIONS_CHANGED } from '../core/contributionregistry'\nimport { subscribe } from '../core/events'\nimport { Signal } from '@lit-labs/signals'\nimport { unsafeHTML } from 'lit/directives/unsafe-html.js'\n\n@customElement('docks-command')\nexport class DocksCommand extends DocksWidget {\n @property()\n cmd: string = ''\n\n @property({ type: Object, attribute: false })\n action?: (event?: Event) => void\n\n @property()\n title: string = ''\n\n @property()\n label?: boolean = false\n\n @property()\n icon?: string\n\n @property({ type: Boolean })\n disabled: boolean = false\n\n @property()\n appearance: 'default' | 'plain' | 'outline' | 'accent' | 'filled-outlined' | 'filled' | 'outlined' = 'plain'\n\n @property()\n variant: 'neutral' | 'brand' | 'success' | 'warning' | 'danger' = 'neutral'\n\n @property()\n size: 'small' | 'medium' | 'large' = 'small'\n\n @property({ type: Object, attribute: false })\n params: Record<string, any> = {}\n\n @property()\n dropdown?: string\n\n @property()\n placement: 'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'left-start' | 'left-end' | 'right' | 'right-start' | 'right-end' = 'bottom-start'\n\n @state()\n private dropdownContributions: Contribution[] = []\n\n private handleClick(event?: Event) {\n if (this.disabled) return\n\n if (event) {\n event.stopPropagation()\n }\n\n if (this.action) {\n this.action(event)\n return\n }\n\n if (this.cmd) {\n const dropdown = this.closest('wa-dropdown') as any;\n if (dropdown && dropdown.open !== undefined) {\n dropdown.open = false;\n }\n void this.executeCommand(this.cmd, this.params);\n }\n }\n\n private handleSelect(event: CustomEvent) {\n // Close dropdown immediately when any item is selected\n // This ensures the dropdown is hidden before the command executes\n const dropdown = event.target as any;\n if (dropdown && dropdown.open !== undefined) {\n dropdown.open = false;\n }\n }\n\n private isInDropdown(): boolean {\n return !!this.closest('wa-dropdown, wa-dropdown-menu')\n }\n\n private getKeybinding(): string | null {\n if (!this.cmd || this.action) return null\n const keybindings = keyBindingManager.getKeyBindingsForCommand(this.cmd)\n return keybindings.length > 0 ? keybindings[0] : null\n }\n\n protected doBeforeUI() {\n if (this.dropdown) {\n this.loadDropdownContributions()\n \n subscribe(TOPIC_CONTRIBUTEIONS_CHANGED, (event: ContributionChangeEvent) => {\n if (this.dropdown && event.target === this.dropdown) {\n this.dropdownContributions = event.contributions;\n this.requestUpdate();\n }\n })\n }\n }\n\n private loadDropdownContributions() {\n if (!this.dropdown) return\n this.dropdownContributions = contributionRegistry.getContributions(this.dropdown)\n this.requestUpdate()\n }\n\n private renderContribution(contribution: Contribution) {\n if ('command' in contribution) {\n const commandContribution = contribution as CommandContribution\n const disabled = (commandContribution.disabled as Signal.Computed<boolean>)?.get()\n return html`\n <docks-command \n cmd=\"${commandContribution.command}\"\n icon=\"${commandContribution.icon || ''}\"\n .params=${commandContribution.params || {}}\n ?disabled=\"${disabled}\">\n ${commandContribution.label}\n </docks-command>\n `\n }\n \n if ('component' in contribution) {\n const htmlContribution = contribution as HTMLContribution\n const contents = htmlContribution.component\n if (contents instanceof Function) {\n return contents()\n }\n return unsafeHTML(contents)\n }\n \n return nothing\n }\n\n render() {\n const keybinding = this.getKeybinding()\n\n if (this.isInDropdown()) {\n return html`\n <wa-dropdown-item \n ?disabled=${this.disabled}\n @click=${(e: Event) => this.handleClick(e)}>\n ${icon(this.icon, { label: this.title, slot: 'icon' })}\n <slot></slot>\n ${keybinding ? html`<span class=\"keybinding\">${keybinding}</span>` : ''}\n </wa-dropdown-item>\n `\n }\n\n if (this.dropdown) {\n return html`\n <wa-dropdown \n placement=${this.placement}\n @wa-select=${(e: CustomEvent) => this.handleSelect(e)}>\n <wa-button \n slot=\"trigger\"\n appearance=${this.appearance}\n variant=${this.variant}\n size=${this.size}\n ?disabled=${this.disabled}\n with-caret\n title=${keybinding ? `${this.title} (${keybinding})` : this.title}>\n ${icon(this.icon, { label: this.title, slot: 'start' })}\n <slot></slot>\n ${this.label ? this.title : nothing}\n </wa-button>\n \n ${this.title ? html`\n <h6 style=\"padding: var(--wa-space-xs) var(--wa-space-s); margin: 0; color: var(--wa-color-neutral-50); font-size: 0.75rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em;\">\n ${this.title}\n </h6>\n ` : nothing}\n \n ${this.dropdownContributions.map(c => this.renderContribution(c))}\n \n ${this.cmd ? html`\n <wa-divider></wa-divider>\n <docks-command \n cmd=\"${this.cmd}\"\n icon=\"${this.icon || ''}\"\n .params=${this.params}\n ?disabled=${this.disabled}>\n <slot></slot>\n ${this.title}\n </docks-command>\n ` : nothing}\n </wa-dropdown>\n `\n }\n\n return html`\n <wa-button\n appearance=${this.appearance}\n variant=${this.variant}\n size=${this.size}\n ?disabled=${this.disabled}\n title=${keybinding ? `${this.title} (${keybinding})` : this.title}\n @click=${(e: Event) => this.handleClick(e)}>\n ${icon(this.icon, { label: this.title, slot: 'start' })}\n <slot></slot>\n </wa-button>\n `\n }\n\n static styles = css`\n :host {\n display: inline-block;\n }\n\n .keybinding {\n margin-left: auto;\n padding: 2px 6px;\n background: var(--wa-color-neutral-15);\n border: 1px solid var(--wa-color-neutral-25);\n border-radius: 3px;\n font-size: 10px;\n font-family: monospace;\n opacity: 0.7;\n }\n\n :host-context(.wa-light) .keybinding {\n background: var(--wa-color-neutral-85);\n border: 1px solid var(--wa-color-neutral-75);\n }\n `\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'docks-command': DocksCommand\n }\n}\n\n","import {css, html, nothing} from 'lit'\nimport {customElement, property, state} from 'lit/decorators.js'\nimport {DocksElement} from \"./element\";\nimport {\n CommandContribution,\n Contribution,\n ContributionChangeEvent,\n contributionRegistry,\n HTMLContribution,\n TOPIC_CONTRIBUTEIONS_CHANGED\n} from \"../core/contributionregistry\";\nimport {Signal} from '@lit-labs/signals';\nimport {unsafeHTML} from \"lit/directives/unsafe-html.js\";\nimport {subscribe} from \"../core/events\";\nimport {createRef, ref} from \"lit/directives/ref.js\";\nimport '../components/command';\n\n@customElement('docks-contextmenu')\nexport class DocksContextMenu extends DocksElement {\n @property({attribute: false})\n scopeTokens: string[] = [];\n\n @property({attribute: false})\n public partContextMenuRenderer?: () => any = undefined;\n\n @state()\n private contributions: Contribution[] = [];\n\n @state()\n private isOpen: boolean = false;\n\n @state()\n private position: { x: number, y: number } = { x: 0, y: 0 };\n\n private anchorRef = createRef<HTMLElement>();\n private dropdownRef = createRef<HTMLElement>();\n\n private boundHandleDocumentPointerDown = this.handleDocumentPointerDown.bind(this);\n\n /**\n * \"Click outside to close\" runs in capture phase before the target's click.\n * We use composedPath() so hits inside the menu still count as inside:\n * - Clicks on items (e.g. command / wa-dropdown-item) or their icon/label\n * are inside shadow roots; contains(target) can miss those.\n * - composedPath() is the path from target to root crossing shadow boundaries,\n * so if the dropdown is in the path, the click was inside the menu and we\n * do not close (so the item's click can run). We only close when the click\n * is truly outside (dropdown not in path). Submenus: same idea, skip close\n * when any node in the path has part=\"submenu\".\n */\n private handleDocumentPointerDown(e: PointerEvent) {\n if (!this.isOpen) return;\n const path = e.composedPath() as Element[];\n if (\n this.dropdownRef.value &&\n path.includes(this.dropdownRef.value)\n ) return;\n if (path.some((el) => el.getAttribute?.('part') === 'submenu')) return;\n this.onClose();\n }\n\n protected doBeforeUI() {\n this.refreshContributions();\n \n subscribe(TOPIC_CONTRIBUTEIONS_CHANGED, (event: ContributionChangeEvent) => {\n const id = this.getAttribute(\"id\");\n if (!id) return;\n \n const shouldReload = this.matchesTarget(id, event.target);\n if (shouldReload) {\n this.refreshContributions();\n this.requestUpdate();\n }\n });\n }\n\n protected updated(changedProperties: Map<string, unknown>) {\n super.updated?.(changedProperties);\n if (changedProperties.has('scopeTokens')) {\n this.refreshContributions();\n }\n }\n\n attributeChangedCallback(name: string, old: string | null, value: string | null) {\n super.attributeChangedCallback(name, old, value);\n if (name === 'id' && old !== value) {\n this.refreshContributions();\n }\n }\n\n private refreshContributions() {\n const id = this.getAttribute(\"id\");\n if (!id) {\n this.contributions = [];\n return;\n }\n this.loadContributions(id);\n }\n\n\n private matchesTarget(id: string, target: string): boolean {\n if (target === id) return true;\n \n if (!id.includes(':')) return false;\n \n const [prefix] = id.split(':');\n if (target === `${prefix}:*`) return true;\n \n const targetParts = target.split(':');\n if (targetParts.length === 2) {\n const categoryToken = targetParts[1];\n if (this.scopeTokens.includes(categoryToken)) {\n return id.startsWith(`${prefix}:`);\n }\n }\n \n return false;\n }\n\n private loadContributions(id: string) {\n const specific = contributionRegistry.getContributions(id);\n \n if (!id.includes(':')) {\n this.contributions = specific;\n return;\n }\n \n const [prefix] = id.split(':');\n const wildcardId = `${prefix}:*`;\n const wildcard = contributionRegistry.getContributions(wildcardId);\n \n const categoryMatches: Contribution[] = [];\n\n for (const category of this.scopeTokens) {\n const categoryId = `${prefix}:${category}`;\n const matches = contributionRegistry.getContributions(categoryId);\n categoryMatches.push(...matches);\n }\n \n this.contributions = [...wildcard, ...categoryMatches, ...specific];\n }\n\n /** Returns true when registry contributions or part-supplied menu content exist. */\n private hasMenuBody(): boolean {\n this.refreshContributions();\n if (this.contributions.length > 0) return true;\n const partContent = this.partContextMenuRenderer ? this.partContextMenuRenderer() : nothing;\n return partContent !== nothing;\n }\n\n /**\n * Gets the element at the given point, traversing shadow DOM boundaries recursively.\n * This is necessary because elementFromPoint() doesn't penetrate shadow roots.\n */\n private getElementFromPoint(x: number, y: number): Element | null {\n let element: Element | null = document.elementFromPoint(x, y);\n if (!element) return null;\n\n // Recursively traverse shadow DOM boundaries\n while (element) {\n const shadowRoot = (element as any).shadowRoot as ShadowRoot | undefined;\n if (shadowRoot) {\n const shadowElement: Element | null = shadowRoot.elementFromPoint(x, y);\n if (shadowElement && shadowElement !== element) {\n element = shadowElement;\n continue;\n }\n }\n break;\n }\n\n return element;\n }\n\n /**\n * Triggers a click on the element under the cursor to update selection before showing context menu.\n */\n private triggerClickUnderCursor(mouseEvent: MouseEvent): void {\n const elementUnderCursor = this.getElementFromPoint(mouseEvent.clientX, mouseEvent.clientY);\n if (elementUnderCursor) {\n const clickEvent = new MouseEvent('click', {\n bubbles: true,\n cancelable: true,\n view: window,\n clientX: mouseEvent.clientX,\n clientY: mouseEvent.clientY,\n screenX: mouseEvent.screenX,\n screenY: mouseEvent.screenY,\n button: 0,\n buttons: 0,\n detail: 1,\n which: 1\n });\n elementUnderCursor.dispatchEvent(clickEvent);\n }\n }\n\n /** Opens the menu at `position`. Returns false when there is nothing to show (no thin empty panel). */\n public show(position: { x: number, y: number }, mouseEvent?: MouseEvent): boolean {\n if (!this.hasMenuBody()) return false;\n if (mouseEvent) {\n this.triggerClickUnderCursor(mouseEvent);\n }\n this.position = position;\n this.isOpen = true;\n this.updateComplete.then(() => {\n document.addEventListener('pointerdown', this.boundHandleDocumentPointerDown, { capture: true });\n });\n return true;\n }\n\n private onClose() {\n this.isOpen = false;\n document.removeEventListener('pointerdown', this.boundHandleDocumentPointerDown, { capture: true });\n }\n\n private renderContribution(contribution: Contribution) {\n if (\"command\" in contribution) {\n const commandContribution = contribution as CommandContribution;\n const disabled = (commandContribution.disabled as Signal.Computed<boolean>)?.get();\n return html`\n <docks-command\n cmd=\"${commandContribution.command}\"\n icon=\"${commandContribution.icon ?? ''}\"\n .params=${commandContribution.params ?? {}}\n ?disabled=\"${disabled}\">\n ${commandContribution.label}\n </docks-command>\n `;\n } else if (\"component\" in contribution) {\n const contents = (contribution as HTMLContribution).component;\n if (contents instanceof Function) {\n return contents();\n }\n return unsafeHTML(contents);\n }\n return nothing;\n }\n\n render() {\n if (!this.isOpen) return nothing;\n\n const partContent = this.partContextMenuRenderer ? this.partContextMenuRenderer() : nothing;\n\n return html`\n <wa-dropdown\n ${ref(this.dropdownRef)}\n ?open=${this.isOpen}\n @wa-after-hide=${this.onClose}>\n \n <div \n slot=\"trigger\"\n ${ref(this.anchorRef)}\n style=\"position: fixed; \n left: ${this.position.x}px; \n top: ${this.position.y}px; \n width: 1px; \n height: 1px; \n pointer-events: none;\">\n </div>\n \n ${partContent}\n ${this.contributions.map(c => this.renderContribution(c))}\n </wa-dropdown>\n `;\n }\n\n static styles = css`\n :host {\n position: fixed;\n top: 0;\n left: 0;\n width: 0;\n height: 0;\n pointer-events: none;\n z-index: 10000;\n }\n\n wa-dropdown {\n pointer-events: auto;\n min-width: 200px;\n }\n \n wa-dropdown::part(menu) {\n min-width: 200px;\n }\n `;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'docks-contextmenu': DocksContextMenu\n }\n}\n\n","import {DocksElement} from \"./element\";\n\nexport abstract class DocksContainer extends DocksElement {\n}","import { DocksContainer } from \"./container\";\nimport { property } from \"lit/decorators.js\";\nimport { css, CSSResultGroup, html, PropertyValues, TemplateResult, nothing } from \"lit\";\nimport { partDirtySignal, activePartSignal, activeEditorSignal } from \"../core/appstate\";\nimport { CommandStack } from \"../core/commandregistry\";\nimport { TabContribution } from \"../core/contributionregistry\";\nimport type { DocksTabs } from \"./tabs\";\nimport { ifDefined } from \"lit/directives/if-defined.js\";\nimport { DocksContextMenu } from \"./contextmenu\";\n\nexport abstract class DocksPart extends DocksContainer {\n protected scrollMode: 'scroller' | 'native' = 'scroller';\n\n @property()\n private dirty: boolean = false\n\n @property({ attribute: false })\n public tabContribution?: TabContribution;\n \n @property({ type: Boolean, attribute: false })\n public isEditor: boolean = false;\n\n protected commandStack?: CommandStack;\n\n public getCommandStack(): CommandStack | undefined {\n return this.commandStack;\n }\n\n /**\n * Override this method to provide toolbar content for this part.\n * This is a lightweight alternative to registering toolbar contributions\n * for actions that are scoped to this part instance.\n * \n * IMPORTANT: Event handlers MUST use arrow functions to preserve the component's 'this' context.\n * The toolbar template is rendered in a different component (docks-toolbar), so direct method \n * references lose their binding.\n * \n * ✅ Correct:\n * @click=${() => this.myMethod()}\n * @click=${(e) => this.handleClick(e)}\n * \n * ❌ Wrong (this will be bound to the toolbar, not your component):\n * @click=${this.myMethod}\n * \n * Example:\n * ```typescript\n * protected renderToolbar() {\n * return html`\n * <wa-button @click=${() => this.save()} title=\"Save\">\n * <wa-icon name=\"save\"></wa-icon>\n * </wa-button>\n * `;\n * }\n * ```\n * \n * @returns TemplateResult with toolbar items, or nothing if no toolbar needed\n */\n protected renderToolbar(): TemplateResult | typeof nothing {\n return nothing;\n }\n\n /**\n * Activates the tab that contains this part by walking up the DOM to the first\n * docks-tabs ancestor and activating the tab panel that contains this part.\n * Crosses Shadow DOM boundaries (e.g. wa-tab-group) via getRootNode().host.\n * No-op if this part is not inside a docks-tabs / wa-tab-panel.\n */\n protected activateContainingTab(): void {\n let el: Element | null = this;\n let panelName: string | null = null;\n let tabsEl: Element | null = null;\n while (el) {\n const tag = el.tagName?.toLowerCase();\n if (tag === 'wa-tab-panel') {\n panelName = el.getAttribute('name');\n }\n if (tag === 'docks-tabs') {\n tabsEl = el;\n break;\n }\n const parent: Element | null = el.parentElement;\n if (parent) {\n el = parent;\n } else {\n const root = el.getRootNode();\n el = root instanceof ShadowRoot ? (root.host as Element) : null;\n }\n }\n if (tabsEl && panelName != null && panelName !== '') {\n (tabsEl as DocksTabs).activate(panelName);\n }\n }\n\n /**\n * Override this method to provide context menu content for this part.\n * This is a lightweight alternative to registering context menu contributions\n * for actions that are scoped to this part instance.\n * \n * IMPORTANT: Event handlers MUST use arrow functions to preserve the component's 'this' context.\n * The context menu is rendered in a different component (contextmenu), so direct method \n * references lose their binding.\n * \n * ✅ Correct:\n * @click=${() => this.myMethod()}\n * @click=${(e) => this.handleClick(e)}\n * \n * ❌ Wrong (this will be bound to the context menu, not your component):\n * @click=${this.myMethod}\n * \n * Example:\n * ```typescript\n * protected renderContextMenu() {\n * return html`\n * <wa-dropdown-item @click=${() => this.open()}>\n * <wa-icon name=\"folder-open\"></wa-icon>\n * Open\n * </wa-dropdown-item>\n * <wa-divider></wa-divider>\n * <wa-dropdown-item @click=${() => this.delete()}>\n * <wa-icon name=\"trash\"></wa-icon>\n * Delete\n * </wa-dropdown-item>\n * `;\n * }\n * ```\n * \n * @returns TemplateResult with context menu items, or nothing if no context menu needed\n */\n protected renderContextMenu(): TemplateResult | typeof nothing {\n return nothing;\n }\n\n protected renderContent(): TemplateResult | typeof nothing {\n return nothing;\n }\n\n private getToolbarTarget(): string | undefined {\n const contributionKey = this.tabContribution?.editorId ?? this.id ?? this.tabContribution?.name;\n return contributionKey ? `toolbar:${contributionKey}` : undefined;\n }\n\n private getContextMenuTarget(): string | undefined {\n const contributionKey = this.tabContribution?.editorId ?? this.id ?? this.tabContribution?.name;\n return contributionKey ? `contextmenu:${contributionKey}` : undefined;\n }\n\n private onContentContextMenu = (event: MouseEvent): void => {\n const contextMenu = this.renderRoot.querySelector('docks-contextmenu') as DocksContextMenu | null;\n if (!contextMenu) return;\n if (contextMenu.show({ x: event.clientX, y: event.clientY }, event)) {\n event.preventDefault();\n }\n };\n\n private syncIsEditorCapability(): void {\n const next = this.save !== DocksPart.prototype.save;\n if (next === this.isEditor) return;\n this.isEditor = next;\n }\n\n private maybeActivateForCoupledEditors(): void {\n const coupled = this.tabContribution?.coupledEditors;\n if (!coupled?.length) return;\n const active = activeEditorSignal.get();\n if (!(active instanceof DocksPart)) return;\n const editorId = active.tabContribution?.editorId;\n if (!editorId || !coupled.includes(editorId)) return;\n this.activateContainingTab();\n }\n\n protected render() {\n const toolbarTarget = this.getToolbarTarget();\n const contextMenuTarget = this.getContextMenuTarget();\n const toolbarEnabled = this.tabContribution?.toolbar !== false;\n const contextMenuEnabled = this.tabContribution?.contextMenu !== false;\n const scrollMode = this.scrollMode;\n const scopeTokens = this.isEditor ? ['system.editors', '.system.editors'] : [];\n const content = this.renderContent();\n const contentNode = scrollMode === 'scroller'\n ? html`\n <wa-scroller class=\"part-content-scroll\" orientation=\"vertical\">\n <div class=\"part-content-inner\">${content}</div>\n </wa-scroller>\n `\n : html`<div class=\"part-content-inner\">${content}</div>`;\n return html`\n <div class=\"part-shell\">\n ${toolbarEnabled ? html`\n <docks-toolbar\n class=\"part-toolbar\"\n id=${ifDefined(toolbarTarget)}\n .scopeTokens=${scopeTokens}\n .partToolbarRenderer=${() => this.renderToolbar()}>\n </docks-toolbar>\n ` : nothing}\n <div class=\"part-content ${scrollMode === 'native' ? 'native-scroll' : ''}\" @contextmenu=${contextMenuEnabled ? this.onContentContextMenu : undefined}>\n ${contentNode}\n </div>\n ${contextMenuEnabled ? html`\n <docks-contextmenu\n id=${ifDefined(contextMenuTarget)}\n .scopeTokens=${scopeTokens}\n .partContextMenuRenderer=${() => this.renderContextMenu()}>\n </docks-contextmenu>\n ` : nothing}\n </div>\n `;\n }\n\n protected updated(_changedProperties: PropertyValues) {\n super.updated(_changedProperties);\n this.syncIsEditorCapability();\n if (_changedProperties.has(\"tabContribution\")) {\n this.maybeActivateForCoupledEditors();\n }\n\n if (_changedProperties.has(\"dirty\")) {\n const dirty = _changedProperties.get(\"dirty\")\n if (dirty !== undefined) {\n this.dispatchEvent(new CustomEvent(\"dirty\", {detail: this.dirty, bubbles: true}))\n }\n }\n }\n\n protected doClose() {\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n // Don't automatically close when disconnected - the element might just be moving\n // Call close() explicitly when actually closing the part\n }\n\n public close() {\n this.doClose()\n }\n\n connectedCallback() {\n super.connectedCallback();\n this.syncIsEditorCapability();\n queueMicrotask(() => this.syncIsEditorCapability());\n this.watch(activeEditorSignal, () => this.maybeActivateForCoupledEditors());\n }\n\n save() {\n }\n\n public isDirty() {\n return this.dirty\n }\n\n public markDirty(dirty: boolean) {\n this.dirty = dirty\n partDirtySignal.set(null as unknown as DocksPart)\n partDirtySignal.set(this)\n activePartSignal.set(null as unknown as DocksPart)\n activePartSignal.set(this)\n }\n\n private static readonly baseStyles = css`\n :host {\n display: block;\n }\n\n .part-shell {\n display: grid;\n grid-template-rows: auto minmax(0, 1fr);\n height: 100%;\n width: 100%;\n position: relative;\n overflow: hidden;\n }\n\n .part-content {\n min-height: 0;\n overflow: hidden;\n position: relative;\n }\n\n .part-content.native-scroll {\n overflow: auto;\n }\n\n .part-content-scroll {\n width: 100%;\n height: 100%;\n }\n\n .part-content-inner {\n height: 100%;\n min-height: 100%;\n }\n\n .part-toolbar {\n min-height: 0;\n }\n `;\n\n static finalizeStyles(styles?: CSSResultGroup) {\n const own = super.finalizeStyles(styles);\n return [DocksPart.baseStyles, ...own];\n }\n}","import {customElement, property, state} from \"lit/decorators.js\";\nimport {css, html, nothing} from \"lit\";\nimport {DocksContainer} from \"./container\";\nimport {contributionRegistry, ContributionChangeEvent, TabContribution, TOPIC_CONTRIBUTEIONS_CHANGED} from \"../core/contributionregistry\";\nimport {when} from \"lit/directives/when.js\";\nimport {repeat} from \"lit/directives/repeat.js\";\nimport {createRef, ref} from \"lit/directives/ref.js\";\nimport { icon } from \"../core/icon-utils\";\nimport {subscribe} from \"../core/events\";\nimport { DocksPart } from \"./part\";\nimport {MouseButton, EDITOR_AREA_MAIN} from \"../core/constants\";\nimport {activePartSignal, activeEditorSignal, partDirtySignal} from \"../core/appstate\";\nimport {watchSignal} from \"../core/signals\";\nimport {confirmDialog} from \"../dialogs\";\nimport {appLoaderService} from \"../core/apploader\";\n\n/**\n * DocksTabs - A dynamic tab container component\n * \n * Architecture:\n * - Fixed layout (VS Code style) - each tab is registered to a specific container\n * - Tabs are created/destroyed as needed (no instance reuse)\n * - Support for both static (views) and dynamic (editors) tabs\n * \n * Lifecycle:\n * 1. doInitUI(): Load contributions, activate first tab\n * 2. render(): Create tab UI from contributions\n * 3. open/closeTab(): Dynamic tab operations\n */\n@customElement('docks-tabs')\nexport class DocksTabs extends DocksContainer {\n @property({reflect: true})\n placement: \"top\" | \"bottom\" | \"start\" | \"end\" = \"top\";\n\n /** Tab contributions for this container */\n @state()\n private contributions: TabContribution[] = [];\n\n /** Reference to the underlying wa-tab-group element */\n private tabGroup = createRef()\n\n /** Cached container ID (this element's 'id' attribute) */\n private containerId: string | null = null;\n\n private tabGroupListenersAttached = false;\n\n private dirtySignalCleanup?: () => void;\n\n // ============= Lifecycle Methods =============\n\n protected doBeforeUI() {\n this.containerId = this.getAttribute(\"id\");\n if (!this.containerId) {\n throw new Error(\"docks-tabs requires an 'id' attribute to function\");\n }\n this.loadAndResolveContributions();\n }\n\n protected doInitUI() {\n this.updateComplete.then(() => this.ensureTabGroupListenersAndActivate());\n \n subscribe(TOPIC_CONTRIBUTEIONS_CHANGED, (event: ContributionChangeEvent) => {\n if (!this.containerId || event.target !== this.containerId) return;\n \n this.loadAndResolveContributions();\n this.requestUpdate();\n \n this.updateComplete.then(() => {\n this.activateNextAvailableTab();\n });\n });\n }\n\n updated(changedProperties: Map<string, any>) {\n super.updated(changedProperties);\n if (this.contributions.length > 0 && this.tabGroup.value) {\n this.updateComplete.then(() => this.ensureTabGroupListenersAndActivate());\n }\n if (changedProperties.has('contributions')) {\n if (this.contributions.length === 0) this.tabGroupListenersAttached = false;\n this.contributions.forEach(contribution => {\n const tabPanel = this.getTabPanel(contribution.name);\n if (!tabPanel) return;\n\n const part = this.getPartFromPanel(tabPanel);\n if (part) {\n part.tabContribution = contribution;\n }\n });\n }\n }\n\n // ============= Public API Methods =============\n \n has(key: string): boolean {\n if (!this.tabGroup.value) return false;\n return !!this.getTabPanel(key);\n }\n\n activate(key: string): void {\n if (!this.tabGroup.value) return;\n this.tabGroup.value.setAttribute(\"active\", key);\n const tabPanel = this.getTabPanel(key);\n if (tabPanel) this.syncActiveSignalsFromPanel(tabPanel);\n }\n\n public getActiveEditor(): string | null {\n if (!this.tabGroup.value) return null;\n return this.tabGroup.value.getAttribute(\"active\");\n }\n\n open(contribution: TabContribution): void {\n const existing = this.contributions.find(c => c.name === contribution.name);\n if (existing) {\n this.activate(contribution.name);\n return;\n }\n \n this.contributions.push(contribution);\n this.requestUpdate();\n \n this.updateComplete.then(() => {\n requestAnimationFrame(() => {\n const tabPanel = this.getTabPanel(contribution.name);\n if (!tabPanel) return;\n const part = this.getPartFromPanel(tabPanel);\n if (part) {\n part.tabContribution = contribution;\n }\n this.activate(contribution.name);\n });\n });\n }\n\n handleTabAuxClick(event: MouseEvent, contribution: TabContribution): void {\n if (event.button === MouseButton.MIDDLE && contribution.closable) {\n this.closeTab(event, contribution.name);\n }\n }\n\n async closeTab(event: Event, tabName: string): Promise<void> {\n event.stopPropagation();\n \n if (this.isDirty(tabName) && !await confirmDialog(\"Unsaved changes will be lost: Do you really want to close?\")) {\n return;\n }\n \n const tabPanel = this.getTabPanel(tabName);\n if (!tabPanel) return;\n \n const contribution = this.contributions.find(c => c.name === tabName);\n if (!contribution) return;\n \n this.cleanupTabInstance(tabPanel);\n this.clearActiveSignalsIfPartInPanel(tabPanel);\n\n const index = this.contributions.indexOf(contribution);\n if (index > -1) {\n this.contributions.splice(index, 1);\n }\n\n this.requestUpdate();\n \n this.updateComplete.then(() => {\n this.activateNextAvailableTab();\n });\n }\n\n markDirty(name: string, dirty: boolean): void {\n const tab = this.getTab(name);\n if (!tab) return;\n tab.classList.toggle(\"part-dirty\", dirty);\n }\n \n isDirty(name: string): boolean {\n const tab = this.getTab(name);\n return !!tab && tab.classList.contains(\"part-dirty\");\n }\n\n // ============= Private Helper Methods =============\n \n /**\n * Loads tab contributions from the registry.\n */\n private loadAndResolveContributions(): void {\n if (!this.containerId) return;\n this.contributions = contributionRegistry.getContributions(this.containerId) as TabContribution[];\n this.requestUpdate();\n }\n\n /**\n * Cleans up a tab instance when the tab is closed.\n * \n * Cleanup Process:\n * 1. Disconnect ResizeObserver if one exists\n * 2. Call component's close() method if available (disposes resources)\n * 3. DOM element is removed by caller (closeTab method)\n */\n private cleanupTabInstance(tabPanel: HTMLElement): void {\n // Explicitly close the component inside the tab before removing\n // This allows components to dispose resources (e.g., Monaco editor models, event listeners)\n const part = this.getPartFromPanel(tabPanel);\n if (part && 'close' in part && typeof part.close === 'function') {\n part.close();\n }\n }\n\n private ensureTabGroupListenersAndActivate(): void {\n if (!this.tabGroup.value) {\n return;\n }\n if (this.tabGroupListenersAttached) {\n return;\n }\n this.tabGroupListenersAttached = true;\n const el = this.tabGroup.value;\n\n // @ts-ignore\n el.addEventListener(\"wa-tab-show\", (event: CustomEvent) => {\n const tabPanel = this.getTabPanel(event.detail.name);\n if (tabPanel) {\n this.syncActiveSignalsFromPanel(tabPanel);\n }\n });\n\n el.addEventListener('click', (event: Event) => {\n const target = event.target as HTMLElement;\n const tab = target.closest('wa-tab');\n if (tab) {\n const panelName = tab.getAttribute('panel');\n if (panelName) {\n const tabPanel = this.getTabPanel(panelName);\n if (tabPanel) this.syncActiveSignalsFromPanel(tabPanel);\n }\n return;\n }\n const tabPanel = target.closest('wa-tab-panel') as HTMLElement | null;\n if (tabPanel) this.syncActiveSignalsFromPanel(tabPanel);\n });\n\n\n this.dirtySignalCleanup?.();\n this.dirtySignalCleanup = watchSignal(partDirtySignal, (part: DocksPart | null) => {\n if (!part) return;\n const panel = part.closest('wa-tab-panel') as HTMLElement | null;\n if (!panel) return;\n const name = panel.getAttribute('name');\n if (!name) return;\n this.markDirty(name, part.isDirty());\n });\n\n this.activateNextAvailableTab();\n }\n\n disconnectedCallback() {\n this.dirtySignalCleanup?.();\n this.dirtySignalCleanup = undefined;\n super.disconnectedCallback();\n }\n\n private activateNextAvailableTab(): void {\n if (!this.tabGroup.value) return;\n \n const allRemainingTabs = this.tabGroup.value.querySelectorAll(\"wa-tab\");\n if (allRemainingTabs.length > 0) {\n const newActive = allRemainingTabs.item(0).getAttribute(\"panel\");\n if (newActive) {\n this.tabGroup.value.setAttribute(\"active\", newActive);\n }\n } else {\n this.tabGroup.value.removeAttribute(\"active\");\n }\n }\n\n private getTabPanel(name: string): HTMLElement | null {\n if (!this.tabGroup.value) return null;\n return this.tabGroup.value.querySelector(`wa-tab-panel[name='${name}']`) as HTMLElement | null;\n }\n\n private getTab(name: string): HTMLElement | null {\n if (!this.tabGroup.value) return null;\n return this.tabGroup.value.querySelector(`wa-tab[panel='${name}']`) as HTMLElement | null;\n }\n\n private syncActiveSignalsFromPanel(tabPanel: HTMLElement): void {\n const part = this.getPartFromPanel(tabPanel);\n if (!(part instanceof DocksPart)) return;\n\n // Always update the active part to reflect current focus\n activePartSignal.set(null as unknown as DocksPart);\n activePartSignal.set(part);\n\n // Only update the active editor when an editor in the main editor area changes.\n // Do NOT clear the existing active editor when non-editor parts gain focus so\n // commands depending on the active editor keep working while other views are active.\n if (this.containerId === EDITOR_AREA_MAIN && part.isEditor) {\n activeEditorSignal.set(null as unknown as DocksPart);\n activeEditorSignal.set(part);\n }\n }\n\n private clearActiveSignalsIfPartInPanel(tabPanel: HTMLElement): void {\n const parts = Array.from(tabPanel.querySelectorAll('*')).filter(\n (el): el is DocksPart => el instanceof DocksPart\n );\n for (const part of parts) {\n if (activePartSignal.get() === part) activePartSignal.set(null as unknown as DocksPart);\n if (activeEditorSignal.get() === part) activeEditorSignal.set(null as unknown as DocksPart);\n }\n }\n\n private getPartFromPanel(tabPanel: HTMLElement): DocksPart | null {\n const first = tabPanel.firstElementChild;\n return first instanceof DocksPart ? first : null;\n }\n\n // ============= Render Method =============\n\n private static readonly MAX_TAB_LABEL = 16;\n\n private truncateTabLabel(label: string): string {\n if (!label || label.length <= DocksTabs.MAX_TAB_LABEL) return label;\n const ellipsis = '…';\n const take = DocksTabs.MAX_TAB_LABEL - ellipsis.length;\n const startLen = Math.floor(take / 2);\n return label.slice(0, startLen) + ellipsis + label.slice(-(take - startLen));\n }\n\n private renderEmptyState() {\n const currentApp = appLoaderService.getCurrentApp();\n return html`\n <div class=\"empty-state\">\n ${when(\n currentApp,\n () => html`\n <div class=\"empty-content\">\n <h2 class=\"empty-title\">${currentApp!.name}</h2>\n ${when(\n currentApp!.description,\n () => html`<p class=\"empty-description\">${currentApp!.description}</p>`\n )}\n </div>\n `,\n () => html`<wa-icon name=\"folder-open\" class=\"empty-icon\"></wa-icon>`\n )}\n </div>\n `;\n }\n\n render() {\n if (this.contributions.length === 0) {\n return this.renderEmptyState();\n }\n return html`\n <wa-tab-group ${ref(this.tabGroup)} placement=${this.placement}>\n ${repeat(\n this.contributions,\n (c) => c.name,\n (c) => {\n const fullLabel = c.label ?? c.name;\n const shortLabel = this.truncateTabLabel(fullLabel);\n return html`\n <wa-tab panel=\"${c.name}\"\n title=\"${fullLabel}\"\n @auxclick=\"${(e: MouseEvent) => this.handleTabAuxClick(e, c)}\">\n ${icon(c.icon, { label: fullLabel })}\n ${shortLabel}\n ${when(c.closable, () => html`\n <wa-icon name=\"xmark\" label=\"Close\" @click=\"${(e: Event) => this.closeTab(e, c.name)}\"></wa-icon>\n `)}\n </wa-tab>\n <wa-tab-panel name=\"${c.name}\">\n ${c.component ? c.component(c.name) : nothing}\n </wa-tab-panel>\n `;\n }\n )}\n </wa-tab-group>\n `;\n }\n\n static styles = css`\n :host {\n height: 100%;\n width: 100%;\n }\n\n wa-tab-group {\n height: 100%;\n width: 100%;\n }\n\n wa-tab-group::part(base) {\n display: grid;\n grid-template-rows: auto minmax(0, 1fr);\n height: 100%;\n width: 100%;\n }\n\n wa-tab-panel[active] {\n display: grid;\n grid-template-rows: minmax(0, 1fr);\n height: 100%;\n width: 100%;\n overflow: hidden;\n position: relative;\n }\n\n wa-tab-panel > * {\n width: 100%;\n height: 100%;\n min-height: 0;\n }\n\n wa-tab::part(base) {\n padding: 3px 0.5rem;\n }\n\n wa-tab-panel {\n --padding: 0px;\n }\n\n .part-dirty::part(base) {\n font-style: italic;\n color: var(--wa-color-danger-fill-loud)\n }\n\n .empty-state {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n grid-row: 2;\n }\n\n .empty-content {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n padding: 2rem;\n gap: 0.75rem;\n opacity: 0.3;\n }\n\n .empty-title {\n margin: 0;\n font-size: 1.5rem;\n font-weight: 500;\n color: var(--wa-color-text-quiet);\n }\n\n .empty-description {\n margin: 0;\n font-size: 1rem;\n color: var(--wa-color-text-quiet);\n max-width: 500px;\n }\n\n .empty-icon {\n font-size: 6rem;\n opacity: 0.2;\n color: var(--wa-color-text-quiet);\n }\n `\n}\n","/**\n * DocksResizableGrid - A simple resizable grid layout component\n * \n * Uses CSS Grid with explicit column/row templates and manual resize handles.\n * Much simpler and more predictable than flex-based layouts.\n * \n * Features:\n * - Horizontal or vertical orientation\n * - Custom size distribution via 'sizes' attribute\n * - Interactive resize handles between children\n * - Min size constraints (5% of container)\n * \n * Example usage:\n * <docks-resizable-grid orientation=\"horizontal\" sizes=\"20%, 60%, 20%\">\n * <div>Left</div>\n * <div>Center</div>\n * <div>Right</div>\n * </docks-resizable-grid>\n */\nimport {customElement, property, state} from \"lit/decorators.js\";\nimport {html, nothing} from \"lit\";\nimport {DocksElement} from \"./element\";\n\n@customElement('docks-resizable-grid')\nexport class DocksResizableGrid extends DocksElement {\n private static readonly HANDLE_VISUAL_SIZE_PX = 1;\n private static readonly HANDLE_HITBOX_PADDING_PX = 4;\n\n @property()\n orientation: 'horizontal' | 'vertical' = 'horizontal';\n\n @property()\n sizes?: string; // e.g., \"20%, 60%, 20%\"\n\n @state()\n private gridSizes: string[] = [];\n\n @state()\n private gridChildren: HTMLElement[] = [];\n\n private resizing: {\n handleIndex: number;\n startPos: number;\n startSizes: number[];\n currentSizes?: number[];\n } | null = null;\n \n private resizeOverlay: HTMLDivElement | null = null;\n private childrenLoaded = false;\n private childStylesApplied = false;\n private mutationObserver?: MutationObserver;\n private settingsLoaded = false;\n\n createRenderRoot() {\n // intentionally disabling shadow DOM for the resizable grid\n return this;\n }\n\n // ============= Lifecycle Methods =============\n\n protected doBeforeUI() {\n // Only set up observer if children not yet loaded\n if (!this.childrenLoaded) {\n // Use MutationObserver to detect when children are added\n this.mutationObserver = new MutationObserver(() => {\n if (!this.childrenLoaded) {\n this.loadChildren();\n }\n });\n \n this.mutationObserver.observe(this, { childList: true, subtree: false });\n \n // Also try to load immediately\n this.loadChildren();\n }\n }\n\n private async loadChildren() {\n const potentialChildren = Array.from(this.children).filter(\n child => child.tagName !== 'STYLE' && \n child.tagName !== 'SCRIPT' && \n !child.classList.contains('resize-handle')\n ) as HTMLElement[];\n\n if (potentialChildren.length === 0) {\n return;\n }\n\n // Mark as loaded and disconnect observer\n this.childrenLoaded = true;\n if (this.mutationObserver) {\n this.mutationObserver.disconnect();\n this.mutationObserver = undefined;\n }\n\n // Store children references\n this.gridChildren = potentialChildren;\n\n // Load persisted sizes once if available\n if (!this.settingsLoaded) {\n this.settingsLoaded = true;\n const persisted = await this.getDialogSetting();\n if (persisted && Array.isArray(persisted.sizes) && persisted.sizes.length === this.gridChildren.length) {\n this.gridSizes = persisted.sizes;\n this.requestUpdate();\n return;\n }\n }\n\n // Use sizes attribute or equal distribution (only if not restored from settings)\n if (this.sizes) {\n this.gridSizes = this.sizes.split(',').map(s => s.trim());\n } else {\n const equalSize = `${100 / this.gridChildren.length}%`;\n this.gridSizes = this.gridChildren.map(() => equalSize);\n }\n\n this.requestUpdate();\n }\n\n private async saveSizes() {\n if (this.gridSizes.length === 0) {\n return;\n }\n\n await this.setDialogSetting({\n sizes: this.gridSizes,\n orientation: this.orientation\n });\n }\n\n updated(changedProperties: Map<string, any>) {\n super.updated(changedProperties);\n \n // Only apply child styles once when children are first loaded\n // This prevents interfering with nested resizable grids during resize operations\n if (changedProperties.has('gridChildren') && !this.childStylesApplied && this.gridChildren.length > 0) {\n this.childStylesApplied = true;\n \n /**\n * Direct style manipulation is intentionally used here.\n * \n * Reasoning:\n * - Grid positioning (gridColumn/gridRow) must be computed dynamically based on\n * the number of children and orientation at runtime\n * - Shadow DOM is disabled (see createRenderRoot), so we cannot use ::slotted()\n * or scoped CSS selectors to style children\n * - CSS classes alone cannot express the dynamic grid positioning logic\n * (e.g., child at index 0 → column 1, index 1 → column 3, etc.)\n * - This is a layout container whose primary job is to programmatically position\n * its children within a CSS grid system\n */\n this.gridChildren.forEach((child, index) => {\n child.style.overflow = 'hidden';\n child.style.height = '100%';\n child.style.width = '100%';\n child.style.gridColumn = this.orientation === 'horizontal' ? `${index * 2 + 1}` : '1';\n child.style.gridRow = this.orientation === 'vertical' ? `${index * 2 + 1}` : '1';\n child.style.display = 'flex';\n child.style.flexDirection = 'column';\n });\n }\n }\n\n // ============= Resize Handling Methods =============\n\n private startResize(e: MouseEvent, handleIndex: number) {\n e.preventDefault();\n \n if (handleIndex >= this.gridChildren.length - 1) return;\n\n const startPos = this.orientation === 'horizontal' ? e.clientX : e.clientY;\n \n // Convert all sizes to pixels at the start of resize\n const containerSize = this.orientation === 'horizontal' \n ? this.offsetWidth \n : this.offsetHeight;\n \n const startSizes = this.gridSizes.map(size => {\n if (size.endsWith('%')) {\n return (parseFloat(size) / 100) * containerSize;\n } else if (size.endsWith('px')) {\n return parseFloat(size);\n } else {\n return parseFloat(size);\n }\n });\n\n this.resizing = {\n handleIndex,\n startPos,\n startSizes\n };\n\n // Create overlay to prevent iframes from capturing mouse events\n this.resizeOverlay = document.createElement('div');\n this.resizeOverlay.style.position = 'fixed';\n this.resizeOverlay.style.top = '0';\n this.resizeOverlay.style.left = '0';\n this.resizeOverlay.style.width = '100%';\n this.resizeOverlay.style.height = '100%';\n this.resizeOverlay.style.zIndex = '9999';\n this.resizeOverlay.style.cursor = this.orientation === 'horizontal' ? 'col-resize' : 'row-resize';\n document.body.appendChild(this.resizeOverlay);\n\n document.addEventListener('mousemove', this.handleResize);\n document.addEventListener('mouseup', this.stopResize);\n \n document.body.style.cursor = this.orientation === 'horizontal' ? 'col-resize' : 'row-resize';\n document.body.style.userSelect = 'none';\n }\n\n private handleResize = (e: MouseEvent) => {\n if (!this.resizing) return;\n\n const currentPos = this.orientation === 'horizontal' ? e.clientX : e.clientY;\n const delta = currentPos - this.resizing.startPos;\n\n const newSizes = [...this.resizing.startSizes];\n newSizes[this.resizing.handleIndex] += delta;\n newSizes[this.resizing.handleIndex + 1] -= delta;\n\n // Apply min constraints (5% of container)\n const containerSize = this.orientation === 'horizontal' \n ? this.offsetWidth \n : this.offsetHeight;\n const minSize = containerSize * 0.05;\n\n if (newSizes[this.resizing.handleIndex] >= minSize && \n newSizes[this.resizing.handleIndex + 1] >= minSize) {\n this.resizing.currentSizes = newSizes;\n \n // Update visual preview directly without triggering requestUpdate()\n const gridTemplate = newSizes.map((size, index) => {\n const percent = (size / containerSize) * 100;\n const sizeStr = `${percent.toFixed(2)}%`;\n if (index === newSizes.length - 1) {\n return sizeStr;\n }\n return `${sizeStr} ${DocksResizableGrid.HANDLE_VISUAL_SIZE_PX}px`;\n }).join(' ');\n \n if (this.orientation === 'horizontal') {\n this.style.gridTemplateColumns = gridTemplate;\n } else {\n this.style.gridTemplateRows = gridTemplate;\n }\n }\n }\n\n private stopResize = async () => {\n if (this.resizing?.currentSizes) {\n const containerSize = this.orientation === 'horizontal' \n ? this.offsetWidth \n : this.offsetHeight;\n \n this.gridSizes = this.resizing.currentSizes.map(size => {\n const percent = (size / containerSize) * 100;\n return `${percent.toFixed(2)}%`;\n });\n \n await this.saveSizes();\n this.requestUpdate();\n }\n \n // Remove overlay\n if (this.resizeOverlay) {\n document.body.removeChild(this.resizeOverlay);\n this.resizeOverlay = null;\n }\n \n this.resizing = null;\n document.removeEventListener('mousemove', this.handleResize);\n document.removeEventListener('mouseup', this.stopResize);\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n }\n\n // ============= Render Methods =============\n\n render() {\n if (this.gridChildren.length === 0 || this.gridSizes.length === 0) {\n // Show children with default styling while grid is initializing\n return nothing;\n }\n\n // Build grid template with resize handles\n // For 3 children: \"size1 4px size2 4px size3\"\n const gridTemplate = this.gridSizes.flatMap((size, index) => {\n if (index === this.gridSizes.length - 1) {\n return [size];\n }\n return [size, `${DocksResizableGrid.HANDLE_VISUAL_SIZE_PX}px`];\n }).join(' ');\n\n // Apply grid layout to the custom element itself\n this.style.display = 'grid';\n if (this.orientation === 'horizontal') {\n this.style.gridTemplateColumns = gridTemplate;\n this.style.gridTemplateRows = '100%';\n } else {\n this.style.gridTemplateColumns = '100%';\n this.style.gridTemplateRows = gridTemplate;\n }\n this.style.overflow = 'hidden';\n\n // Render resize handles\n // Child styling is applied in updated() when gridChildren/gridSizes change\n return html`\n <style>\n .resize-handle {\n position: relative;\n z-index: 10;\n background-color: var(--wa-color-neutral-border-quiet);\n transition: background-color var(--wa-transition-fast);\n }\n\n .resize-handle::before {\n content: '';\n position: absolute;\n inset: 0;\n }\n\n .resize-handle.horizontal::before {\n right: -${DocksResizableGrid.HANDLE_HITBOX_PADDING_PX}px;\n left: -${DocksResizableGrid.HANDLE_HITBOX_PADDING_PX}px;\n }\n\n .resize-handle.vertical::before {\n top: -${DocksResizableGrid.HANDLE_HITBOX_PADDING_PX}px;\n bottom: -${DocksResizableGrid.HANDLE_HITBOX_PADDING_PX}px;\n }\n \n .resize-handle:hover {\n background-color: var(--wa-color-brand-fill-normal);\n }\n </style>\n \n ${this.gridChildren.map((_, index) => {\n if (index < this.gridChildren.length - 1) {\n const gridCol = this.orientation === 'horizontal' ? `${index * 2 + 2}` : '1';\n const gridRow = this.orientation === 'vertical' ? `${index * 2 + 2}` : '1';\n return html`\n <div \n class=\"resize-handle ${this.orientation === 'horizontal' ? 'horizontal' : 'vertical'}\"\n style=\"\n cursor: ${this.orientation === 'horizontal' ? 'col-resize' : 'row-resize'};\n grid-column: ${gridCol};\n grid-row: ${gridRow};\n \"\n @mousedown=${(e: MouseEvent) => this.startResize(e, index)}\n ></div>\n `;\n }\n return nothing;\n })}\n `;\n }\n\n // ============= Cleanup Methods =============\n\n disconnectedCallback() {\n super.disconnectedCallback();\n if (this.resizing) {\n this.stopResize();\n }\n if (this.mutationObserver) {\n this.mutationObserver.disconnect();\n this.mutationObserver = undefined;\n }\n }\n\n connectedCallback() {\n super.connectedCallback();\n this.style.height = '100%';\n this.style.width = '100%';\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'docks-resizable-grid': DocksResizableGrid\n }\n}\n\n"],"mappings":"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"}
|