@eclipse-docks/core 0.7.83 → 0.7.84
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 +1 -1
- package/dist/{api-C8Vh88fr.js → api-DISr4dl4.js} +16 -4
- package/dist/api-DISr4dl4.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/layouts/standard-layout.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/commands/version-info.ts +8 -3
- package/src/layouts/standard-layout.ts +8 -0
- package/dist/api-C8Vh88fr.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-DISr4dl4.js","names":[],"sources":["../src/core/i18n.ts","../src/core/editorregistry.ts","../src/core/tree-utils.ts","../src/components/filebrowser.ts","../src/components/tasks.ts","../src/components/document-title.ts","../src/components/part-name.ts","../src/components/extensions.ts","../src/components/log-terminal.ts","../src/components/fastviews.ts","../src/components/language-selector.ts","../src/components/layout-switcher.ts","../src/core/ui-ids.ts","../src/contributions/default-ui-contributions.ts","../src/layouts/standard-layout.ts","../src/contributions/default-layout-contributions.ts","../src/commands/files.ts","../src/commands/version-info.ts","../src/commands/global.ts","../src/core/js-runtime.ts","../src/commands/js.ts","../src/commands/open-view-as-editor.ts","../src/commands/shared.ts","../src/commands/cat.ts","../src/commands/exists.ts","../src/commands/filebrowser-contributions.ts","../src/commands/head.ts","../src/commands/ls.ts","../src/commands/mkdir.ts","../src/commands/mv.ts","../src/commands/rm.ts","../src/commands/tail.ts","../src/commands/touch.ts","../src/commands/unzip.ts","../src/commands/wc.ts","../src/commands/wget.ts","../src/core/index.ts","../src/core/config.ts"],"sourcesContent":["import { signal, Signal } from '@lit-labs/signals';\nimport { appSettings, TOPIC_SETTINGS_CHANGED } from \"./settingsservice\";\nimport { subscribe } from \"./events\";\n\n/**\n * Why this custom i18n layer exists (instead of directly using @lit/localize):\n *\n * - Architecture fit: this system localizes not only Lit templates, but also\n * runtime metadata (for example extension names/descriptions) that can be\n * consumed outside component render paths.\n * - Plugin ergonomics: each feature can ship co-located locale JSON files and\n * load them lazily via import.meta.glob.\n * - Low process overhead: simple JSON dictionaries are easy to maintain and\n * work well with AI-assisted translation workflows without XLIFF tooling.\n *\n * Trade-offs versus Lit Localize:\n *\n * - We do not get Lit Localize's extraction/build pipeline and XLIFF workflow\n * out of the box.\n * - We own validation/consistency guarantees (key parity, placeholder parity,\n * locale completeness) and must enforce them in our own checks.\n * - Message interpolation is intentionally simple ({param} replacement), which\n * is less expressive than template-aware localization APIs.\n */\nexport const SETTINGS_KEY_LANGUAGE = 'language';\n\nexport const DEFAULT_LANGUAGE = 'en';\n\nfunction replaceParameters(text: string, params?: Record<string, string>): string {\n if (!params) return text;\n return text.replace(/\\{(\\w+)\\}/g, (match, paramKey) =>\n params[paramKey] !== undefined ? params[paramKey] : match\n );\n}\n\nconst supportedLocales = new Set<string>([DEFAULT_LANGUAGE]);\nexport const supportedLocalesSignal: Signal.State<Set<string>> = signal(supportedLocales);\n\nlet languageFromSettings: string | null = null;\n\nfunction addSupportedLocales(locales: string[]): void {\n let changed = false;\n for (const loc of locales) {\n const normalized = loc.toLowerCase().replace('-', '_');\n if (!supportedLocales.has(normalized)) {\n supportedLocales.add(normalized);\n changed = true;\n }\n }\n if (changed) {\n supportedLocalesSignal.set(new Set(supportedLocales));\n if (languageFromSettings === null) {\n const preferred = getPreferredBrowserLanguage();\n if (preferred !== currentLanguageSignal.get()) currentLanguageSignal.set(preferred);\n }\n }\n}\n\nfunction getPreferredBrowserLanguage(): string {\n const list = navigator.languages?.length ? navigator.languages : [navigator.language || DEFAULT_LANGUAGE];\n const supported = supportedLocalesSignal.get();\n for (const raw of list) {\n const primary = raw.split('-')[0].toLowerCase();\n if (supported.has(primary)) return primary;\n }\n return DEFAULT_LANGUAGE;\n}\n\nexport const currentLanguageSignal: Signal.State<string> = signal(getPreferredBrowserLanguage());\n\nasync function updateLanguageFromSettings(): Promise<void> {\n const settingsLanguage = await appSettings.get(SETTINGS_KEY_LANGUAGE);\n languageFromSettings = settingsLanguage ?? null;\n currentLanguageSignal.set(settingsLanguage || getPreferredBrowserLanguage());\n}\n\nsubscribe(TOPIC_SETTINGS_CHANGED, (settings: any) => {\n languageFromSettings = settings?.[SETTINGS_KEY_LANGUAGE] ?? null;\n currentLanguageSignal.set(settings?.[SETTINGS_KEY_LANGUAGE] || getPreferredBrowserLanguage());\n});\n\nupdateLanguageFromSettings();\n\nexport interface LazyLabel {\n toString(): string;\n valueOf(): string;\n [Symbol.toPrimitive](hint?: string): string;\n toJSON?(): string;\n}\n\nexport type UILabel = string | LazyLabel;\n\nexport function createLazyLabel(getter: () => string): LazyLabel {\n return {\n toString: () => getter(),\n valueOf: () => getter(),\n [Symbol.toPrimitive]: () => getter(),\n toJSON: () => getter(),\n };\n}\n\ntype Messages = Record<string, string>;\n\ntype I18nHandle<TKeys extends string> = {\n [K in TKeys]: string & ((params?: Record<string, string>) => string);\n};\n\nexport async function i18n<F extends Record<string, () => Promise<any>>>(files: F, reactive = false) {\n const byLocale: Record<string, Messages> = {};\n\n await Promise.all(\n Object.entries(files).map(async ([path, loader]) => {\n const mod = await loader();\n const messages: Messages = (mod && 'default' in mod ? (mod as any).default : mod) as Messages;\n const match = path.match(/\\.([a-zA-Z-_]+)\\.json$/);\n const rawLocale = match?.[1] ?? DEFAULT_LANGUAGE;\n const normalizedLocale = rawLocale.toLowerCase().replace('-', '_');\n byLocale[normalizedLocale] = messages;\n }),\n );\n\n addSupportedLocales(Object.keys(byLocale));\n\n type AllKeys = keyof (typeof byLocale)[keyof typeof byLocale] & string;\n type Handle = I18nHandle<AllKeys>;\n\n const getMessage = (key: string): string => {\n const current = currentLanguageSignal.get();\n const normalized = current.toLowerCase().replace('-', '_');\n const [lang, region] = normalized.split('_');\n const candidates: string[] = region ? [`${lang}_${region}`, lang] : [lang];\n candidates.push(DEFAULT_LANGUAGE);\n for (const loc of candidates) {\n const dict = byLocale[loc];\n if (dict && key in dict) return dict[key]!;\n }\n return key;\n };\n\n const target = Object.assign({} as Handle, { then: undefined, catch: undefined, finally: undefined });\n\n const handler: ProxyHandler<Handle> = {\n get(t, key: string) {\n if (key in t) return (t as Record<string, unknown>)[key];\n const base = getMessage(key);\n const fn = ((params?: Record<string, string>) =>\n replaceParameters(getMessage(key), params)) as unknown as Handle[typeof key];\n (fn as any).toString = () => (reactive ? getMessage(key) : base);\n (fn as any).valueOf = () => (reactive ? getMessage(key) : base);\n (fn as any)[Symbol.toPrimitive] = () => (reactive ? getMessage(key) : base);\n if (reactive) (fn as any).toJSON = () => getMessage(key);\n return fn;\n },\n };\n\n return new Proxy(target, handler);\n}\n","import { EDITOR_AREA_MAIN } from \"./constants\";\nimport { subscribe } from \"./events\";\nimport { File, TOPIC_WORKSPACE_CONNECTED } from \"./filesys\";\nimport { DocksTabs } from \"../parts/tabs\";\nimport { TabContribution, IconContribution, contributionRegistry, TOPIC_CONTRIBUTEIONS_CHANGED } from \"./contributionregistry\";\nimport { rootContext } from \"./di\";\n\nexport const EVENT_SHOW_EDITOR = \"editors/showEditor\";\n\nexport interface EditorInput {\n key: string;\n title: string;\n icon?: string;\n data: any;\n component: (container: any, tab: HTMLElement) => any;\n state: { [key: string]: any };\n}\n\nexport interface EditorInputHandler {\n editorId: string;\n label: string;\n icon?: string;\n canHandle: (input: any) => boolean;\n handle: (input: any) => Promise<EditorInput>;\n lazyInit?: () => Promise<void> | void;\n ranking?: number;\n}\n\ninterface RegisteredEditorInputHandler {\n definition: EditorInputHandler;\n initialized: boolean;\n lazyInitPromise?: Promise<void>;\n}\n\n/**\n * Interface for editors that can provide content, selection, and snippets.\n * Implement this interface to make editor content accessible via commands.\n */\nexport interface EditorContentProvider {\n /**\n * Gets the complete contents of the editor.\n * @returns The full content as a string, or null if not available.\n */\n getContent(): string | null;\n\n /**\n * Gets the currently selected text in the editor.\n * @returns The selected text, or null if no selection exists.\n */\n getSelection(): string | null;\n\n /**\n * Gets a code snippet with n lines before and after the cursor position.\n * @param lines Number of lines before and after the cursor (default: 5).\n * @returns An object containing the snippet, cursor line number, or null if not available.\n */\n getSnippet(lines?: number): { snippet: string; cursorLine: number } | null;\n\n /**\n * Gets the programming language of the editor content.\n * @returns The language identifier (e.g., 'python', 'javascript'), or null if not available.\n */\n getLanguage(): string | null;\n\n /**\n * Returns whether the editor content is in the given language (case-insensitive).\n * Default implementation can use getLanguage() === lang.toLowerCase().\n */\n isLanguage?(lang: string): boolean;\n\n /**\n * Gets the workspace path of the file being edited.\n * @returns The file path relative to the workspace, or null if not available.\n */\n getFilePath(): string | null;\n}\n\nclass EditorRegistry {\n private editorInputHandlers: RegisteredEditorInputHandler[] = [];\n private cachedIconContributions: IconContribution[] | null = null;\n\n constructor() {\n subscribe(TOPIC_WORKSPACE_CONNECTED, () => {\n // TODO close all editors\n });\n \n subscribe(TOPIC_CONTRIBUTEIONS_CHANGED, (event: any) => {\n if (event.target === 'system.icons') {\n this.cachedIconContributions = null;\n }\n });\n }\n \n private getSortedIconContributions(): IconContribution[] {\n if (this.cachedIconContributions !== null) {\n return this.cachedIconContributions;\n }\n \n const contributions = contributionRegistry.getContributions('system.icons') as IconContribution[];\n \n // Sort by priority (higher priority first), then by label for tie-breaking\n this.cachedIconContributions = [...contributions].sort((a, b) => {\n const priorityA = a.priority ?? 0;\n const priorityB = b.priority ?? 0;\n if (priorityB !== priorityA) {\n // Higher priority comes first (descending order)\n return priorityB - priorityA;\n }\n return a.label.localeCompare(b.label);\n });\n \n return this.cachedIconContributions;\n }\n\n registerEditorInputHandler(editorInputHandler: EditorInputHandler) {\n this.editorInputHandlers.push({\n definition: editorInputHandler,\n initialized: false\n });\n // Sort by ranking (higher ranking first), default ranking is 0\n this.editorInputHandlers.sort((a, b) => {\n const rankA = a.definition.ranking ?? 0;\n const rankB = b.definition.ranking ?? 0;\n return rankB - rankA;\n });\n }\n\n private async ensureHandlerInitialized(entry: RegisteredEditorInputHandler): Promise<void> {\n const handler = entry.definition;\n if (!handler.lazyInit || entry.initialized) {\n return;\n }\n\n if (!entry.lazyInitPromise) {\n entry.lazyInitPromise = Promise.resolve(handler.lazyInit()).then(() => {\n entry.initialized = true;\n entry.lazyInitPromise = undefined;\n }).catch(error => {\n entry.lazyInitPromise = undefined;\n throw error;\n });\n }\n\n await entry.lazyInitPromise;\n }\n\n getEditorOptionsForInput(input: any): Array<{ editorId: string; title: string; icon?: string }> {\n const seen = new Set<string>();\n const options: Array<{ editorId: string; title: string; icon?: string }> = [];\n for (const entry of this.editorInputHandlers) {\n const handler = entry.definition;\n if (!handler.canHandle(input) || seen.has(handler.editorId)) continue;\n seen.add(handler.editorId);\n options.push({\n editorId: handler.editorId,\n title: handler.label,\n icon: handler.icon\n });\n }\n return options;\n }\n\n async handleInput(input: any, preferredEditorId?: string) {\n if (preferredEditorId !== undefined) {\n const entry = this.editorInputHandlers.find(\n e => e.definition.editorId === preferredEditorId\n );\n if (entry) {\n await this.ensureHandlerInitialized(entry);\n const result = await entry.definition.handle(input);\n if (result) (result as unknown as Record<string, unknown>).editorId = entry.definition.editorId;\n return result;\n }\n return undefined;\n }\n for (let i = 0; i < this.editorInputHandlers.length; i++) {\n const entry = this.editorInputHandlers[i];\n const editorInputHandler = entry.definition;\n if (editorInputHandler.canHandle(input)) {\n await this.ensureHandlerInitialized(entry);\n const result = await editorInputHandler.handle(input);\n if (result) (result as unknown as Record<string, unknown>).editorId = editorInputHandler.editorId;\n return result;\n }\n }\n }\n\n getEditorArea(): DocksTabs | null {\n return document.querySelector(`docks-tabs#${EDITOR_AREA_MAIN}`) as DocksTabs | null\n }\n\n /**\n * Tab label for the main editor area: basename for workspace files, otherwise the input title\n * (e.g. virtual editors like settings or AI config keep their full title).\n */\n private tabLabelForEditorInput(editorInput: EditorInput): string {\n if (editorInput.data instanceof File) {\n return editorInput.data.getName();\n }\n return editorInput.title;\n }\n\n async loadEditor(editorInput: EditorInput | any, preferredEditorId?: string) {\n if (!editorInput) {\n return\n }\n\n if (!(\"component\" in editorInput)) {\n editorInput = await this.handleInput(editorInput, preferredEditorId)\n }\n\n if (!editorInput || !(\"component\" in editorInput)) {\n return\n }\n\n const editorId = (editorInput as Record<string, unknown>).editorId as string | undefined ?? preferredEditorId;\n if (editorId) (editorInput as Record<string, unknown>).editorId = editorId;\n\n await this.openTab({\n name: editorInput.key,\n editorId,\n label: this.tabLabelForEditorInput(editorInput as EditorInput),\n icon: editorInput.icon,\n closable: true,\n component: editorInput.component\n } as TabContribution) \n }\n\n async openTab(tabContribution: TabContribution) {\n const editorArea = this.getEditorArea();\n \n if (!editorArea) {\n console.error(\"Editor area not found. The split pane system may not be initialized yet.\");\n return;\n }\n\n if (editorArea.has(tabContribution.name)) {\n editorArea.activate(tabContribution.name)\n return\n }\n\n editorArea.open(tabContribution)\n }\n\n getFileIcon(fileNameOrType: string): string {\n const extension = fileNameOrType.includes('.') \n ? fileNameOrType.split('.').pop()?.toLowerCase() || ''\n : fileNameOrType.toLowerCase();\n \n const sortedContributions = this.getSortedIconContributions();\n \n if (sortedContributions.length === 0) {\n return 'file';\n }\n \n for (const contribution of sortedContributions) {\n if (contribution.mappings && contribution.mappings[extension]) {\n return contribution.mappings[extension];\n }\n }\n \n return 'file';\n }\n}\n\nexport const editorRegistry = new EditorRegistry();\nrootContext.put(\"editorRegistry\", editorRegistry);\n\ncontributionRegistry.registerContribution<IconContribution>('system.icons', {\n label: 'Default File Icons',\n mappings: {\n 'pdf': 'file-pdf',\n 'md': 'book',\n 'txt': 'file-lines',\n 'ts': 'code',\n 'tsx': 'code',\n 'js': 'code',\n 'jsx': 'code',\n 'json': 'file-code',\n 'geojson': 'file-code',\n 'py': 'docks python',\n 'ipynb': 'docks jupyter',\n 'html': 'code',\n 'htm': 'code',\n 'css': 'code',\n 'scss': 'code',\n 'sass': 'code',\n 'xml': 'file-code',\n 'yaml': 'file-code',\n 'yml': 'file-code',\n 'sql': 'database',\n 'kml': 'file-code',\n 'gpx': 'file-code',\n 'jpg': 'image',\n 'jpeg': 'image',\n 'png': 'image',\n 'gif': 'image',\n 'svg': 'image',\n 'webp': 'image',\n 'bmp': 'image',\n 'ico': 'image',\n },\n priority: 0\n});","import {Contribution} from \"./contributionregistry\";\n\nexport interface TreeNode {\n data: any;\n label: string;\n icon?: string;\n leaf: boolean;\n children: TreeNode[];\n /**\n * Optional flag to indicate that the node's children\n * have been loaded at least once. This is useful for\n * distinguishing between \"not yet loaded\" (lazy) and\n * \"loaded but empty\", so UI elements like spinners\n * don't remain visible for empty folders.\n */\n loaded?: boolean;\n /** Set when {@link Directory.listChildren} fails for this node. */\n loadError?: string;\n /** Persisted workspace folder that could not be restored (see UnavailableWorkspaceFolderDirectory). */\n placeholderNotice?: string;\n /** Backend label for workspace roots (e.g. `webdav`, `indexeddb`). */\n workspaceTag?: string;\n}\n\nexport const treeNodeComparator = (c1: TreeNode, c2: TreeNode) => {\n if (!c1.leaf && c2.leaf) {\n return -1\n }\n if (c1.leaf && !c2.leaf) {\n return 1\n }\n return c1.label.localeCompare(c2.label)\n}\n\nexport interface TreeContribution extends Contribution {\n contributionId?: string;\n state?: { [key: string]: any }\n}","\nimport { css, html, TemplateResult, nothing } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\nimport { DocksPart } from \"../parts/part\";\nimport {\n Directory,\n File,\n Resource,\n TOPIC_WORKSPACE_CHANGED,\n TOPIC_WORKSPACE_CONNECTED,\n UnavailableWorkspaceFolderDirectory,\n workspaceService\n} from \"../core/filesys\";\nimport { when } from \"lit/directives/when.js\";\nimport { subscribe } from \"../core/events\";\nimport { createRef, ref } from \"lit/directives/ref.js\";\nimport { HIDE_DOT_RESOURCE } from \"../core/constants\";\n\nimport { TreeNode, treeNodeComparator } from \"../core/tree-utils\";\nimport { activeSelectionSignal } from \"../core/appstate\";\nimport { confirmDialog, infoDialog } from \"../dialogs\";\nimport { editorRegistry } from \"../core/editorregistry\";\nimport { TOPIC_CONTRIBUTEIONS_CHANGED, type ContributionChangeEvent } from '../core/contributionregistry';\nimport { icon } from '../core/icon-utils';\nimport { i18n } from '../core/i18n';\nimport { createLogger } from '../core/logger';\n\nconst logger = createLogger('DocksFileBrowser');\nconst t = await i18n(import.meta.glob('./filebrowser*.json'));\n\nconst WORKSPACE_CHANGED_DEBOUNCE_MS = 250;\n\n/** `wa-tree-item` exposes `.model` for the bound {@link TreeNode} (not in generated element types). */\ntype WaTreeItemElement = HTMLElement & { model?: TreeNode };\n\n@customElement('docks-filebrowser')\nexport class DocksFileBrowser extends DocksPart {\n\n private static readonly SETTINGS_VERSION = 1;\n private static readonly SETTINGS_KEY_SELECTED_PATH = 'selectedPath';\n private settingsLoaded = false;\n\n @state()\n private root?: TreeNode;\n @state()\n private fileEditorOptions: Array<{ editorId: string; title: string; icon?: string }> = [];\n private workspaceDir?: Directory\n private treeRef = createRef<HTMLElement>();\n private loadingNodes = new Set<TreeNode>();\n /** Bumped on every workspace tree rebuild so in-flight listChildren can bail out after disconnect/reconnect. */\n private treeBuildGeneration = 0;\n private workspaceChangedDebounceId: ReturnType<typeof setTimeout> | undefined;\n private pendingWorkspaceDir: Directory | undefined;\n\n protected doBeforeUI() {\n this.initializeWorkspace();\n\n subscribe(TOPIC_CONTRIBUTEIONS_CHANGED, (event: ContributionChangeEvent) => {\n if (event.target === 'system.icons') {\n this.requestUpdate();\n }\n });\n\n this.subscribe(TOPIC_WORKSPACE_CHANGED, (workspaceDir: Directory | undefined) => this.onWorkspaceChanged(workspaceDir));\n this.subscribe(TOPIC_WORKSPACE_CONNECTED, (workspaceDir: Directory | undefined) => this.onWorkspaceConnected(workspaceDir));\n }\n\n disconnectedCallback() {\n if (this.workspaceChangedDebounceId !== undefined) {\n clearTimeout(this.workspaceChangedDebounceId);\n this.workspaceChangedDebounceId = undefined;\n }\n this.pendingWorkspaceDir = undefined;\n super.disconnectedCallback();\n }\n\n protected firstUpdated(changedProperties: Map<string, any>) {\n super.firstUpdated(changedProperties);\n this.setupDragAndDrop();\n }\n\n protected updated(changedProperties: Map<string, any>) {\n super.updated(changedProperties);\n if (changedProperties.has('workspaceDir') && this.workspaceDir) {\n this.setupDragAndDrop();\n }\n }\n\n private async initializeWorkspace() {\n const workspaceDir = await workspaceService.getWorkspace()\n await this.loadWorkspace(workspaceDir ?? undefined)\n }\n\n protected renderToolbar() {\n return html`\n <docks-command icon=\"folder-open\" title=\"${t.CONNECT_WORKSPACE}\" dropdown=\"filebrowser.connections\"></docks-command>\n <docks-command cmd=\"refresh_resource\" icon=\"repeat\" title=\"${t.REFRESH_RESOURCE}\"></docks-command>\n <docks-command icon=\"docks file-plus\" title=\"${t.CREATE_NEW}\" dropdown=\"filebrowser.create\"></docks-command>\n `;\n }\n\n protected renderContextMenu() {\n const selection = activeSelectionSignal.get()\n const file = selection instanceof File ? selection : null\n const hasOpenWith = file && this.fileEditorOptions.length > 0\n return html`\n <docks-command cmd=\"open_editor\" icon=\"folder-open\">${t.OPEN}</docks-command>\n ${hasOpenWith ? html`\n <wa-dropdown-item>\n ${icon('folder-open', { slot: 'icon' })}\n ${t.OPEN_WITH}\n ${this.fileEditorOptions.map(opt => html`\n <docks-command\n slot=\"submenu\"\n cmd=\"open_editor\"\n icon=\"${opt.icon ?? 'file'}\"\n .params=${{ path: file!.getWorkspacePath(), editorId: opt.editorId }}>\n ${opt.title}\n </docks-command>\n `)}\n </wa-dropdown-item>\n ` : nothing}\n <docks-command icon=\"docks file-plus\" dropdown=\"filebrowser.create\">${t.CREATE_NEW}</docks-command>\n `;\n }\n\n onWorkspaceChanged(workspaceDir: Directory | undefined) {\n this.pendingWorkspaceDir = workspaceDir;\n if (this.workspaceChangedDebounceId !== undefined) {\n clearTimeout(this.workspaceChangedDebounceId);\n }\n this.workspaceChangedDebounceId = setTimeout(() => {\n this.workspaceChangedDebounceId = undefined;\n const dir = this.pendingWorkspaceDir;\n this.pendingWorkspaceDir = undefined;\n if (dir) this.applyWorkspaceChange(dir);\n else this.loadWorkspace(undefined, true);\n }, WORKSPACE_CHANGED_DEBOUNCE_MS);\n }\n\n private async applyWorkspaceChange(workspaceDir: Directory) {\n activeSelectionSignal.set(undefined);\n await this.loadWorkspace(workspaceDir, true);\n await this.syncTreeSelection();\n }\n\n async onWorkspaceConnected(workspaceDir: Directory | undefined) {\n activeSelectionSignal.set(undefined);\n await this.loadWorkspace(workspaceDir, true);\n }\n\n async loadWorkspace(workspaceDir?: Directory, forceRefresh = false) {\n this.treeBuildGeneration += 1;\n const buildGen = this.treeBuildGeneration;\n this.loadingNodes.clear();\n this.workspaceDir = workspaceDir;\n if (!workspaceDir) {\n this.root = undefined;\n if (this.settingsLoaded) {\n await this.persistSelectedPath(null);\n }\n return;\n }\n const root = await this.resourceToTreeNode(workspaceDir, true, forceRefresh);\n if (buildGen !== this.treeBuildGeneration) {\n return;\n }\n this.root = root;\n await this.restoreSelectionFromSettings();\n if (buildGen !== this.treeBuildGeneration) {\n return;\n }\n }\n\n private async persistSelectedPath(path: string | null) {\n await this.setDialogSetting({\n v: DocksFileBrowser.SETTINGS_VERSION,\n [DocksFileBrowser.SETTINGS_KEY_SELECTED_PATH]: path\n });\n }\n\n private async restoreSelectionFromSettings() {\n if (this.settingsLoaded) {\n return;\n }\n this.settingsLoaded = true;\n\n const persisted = await this.getDialogSetting();\n const selectedPath = persisted?.[DocksFileBrowser.SETTINGS_KEY_SELECTED_PATH];\n if (typeof selectedPath !== 'string' || selectedPath.length === 0) {\n return;\n }\n\n await this.updateComplete;\n\n const tree = this.treeRef.value?.querySelector('wa-tree') as any | null;\n if (!tree) return;\n\n if (typeof selectedPath === 'string' && selectedPath.length > 0) {\n const items = Array.from(tree.querySelectorAll('wa-tree-item')) as Array<any>;\n const match = items.find((item) => {\n const data = item?.model?.data as Resource | undefined;\n const path = data?.getWorkspacePath?.();\n return typeof path === 'string' && path === selectedPath;\n });\n if (match) {\n await this.selectTreeItem(match);\n return;\n }\n }\n\n await this.selectFirstConnectedFolder(tree);\n }\n\n private async selectTreeItem(item: any) {\n let parent = (item.parentElement as HTMLElement | null)?.closest?.('wa-tree-item') as any | null;\n while (parent) {\n parent.expanded = true;\n parent = (parent.parentElement as HTMLElement | null)?.closest?.('wa-tree-item') as any | null;\n }\n\n item.selected = true;\n await this.syncTreeSelection();\n }\n\n private async selectFirstConnectedFolder(tree: any) {\n const topLevelItems = Array.from(tree.children).filter(\n (child) => child instanceof HTMLElement && child.tagName.toLowerCase() === 'wa-tree-item'\n ) as Array<any>;\n if (topLevelItems.length === 0) return;\n\n const firstFolderItem = topLevelItems.find((item) => item?.model?.data instanceof Directory);\n const fallbackItem = firstFolderItem ?? topLevelItems[0];\n await this.selectTreeItem(fallbackItem);\n }\n\n private async syncTreeSelection() {\n await this.updateComplete\n const waTree = this.treeRef.value?.querySelector('wa-tree')\n // @ts-ignore\n const selectedItems = waTree?.selectedItems || []\n if (selectedItems.length > 0) {\n // @ts-ignore\n activeSelectionSignal.set(selectedItems[0].model?.data)\n }\n }\n\n async resourceToTreeNode(resource: Resource, loadChildren = false, forceRefreshChildren = false): Promise<TreeNode> {\n const buildGen = this.treeBuildGeneration;\n const isFile = resource instanceof File;\n const node: TreeNode = {\n data: resource,\n label: resource.getName(),\n leaf: isFile,\n children: []\n };\n\n if (resource instanceof Directory && !resource.getParent()) {\n // Root workspace directory: attach workspace metadata (name) so the\n // tree renderer can show a small backend tag without knowing about\n // concrete backend types.\n try {\n const info = await workspaceService.getFolderInfoForDirectory(resource);\n if (buildGen !== this.treeBuildGeneration) {\n node.loaded = !node.leaf;\n return node;\n }\n if (info?.backendName) {\n node.workspaceTag = info.backendName;\n }\n } catch (e) {\n logger.debug('Failed to get workspace info for directory', e);\n }\n }\n\n if (resource instanceof Directory && loadChildren) {\n try {\n const children = await resource.listChildren(forceRefreshChildren);\n if (buildGen !== this.treeBuildGeneration) {\n node.loaded = true;\n return node;\n }\n for (const childResource of children) {\n if (HIDE_DOT_RESOURCE && childResource.getName().startsWith(\".\")) {\n continue;\n }\n const child = await this.resourceToTreeNode(childResource, true, forceRefreshChildren);\n if (buildGen !== this.treeBuildGeneration) {\n node.loaded = true;\n return node;\n }\n node.children.push(child);\n }\n node.children.sort(treeNodeComparator);\n } catch (error) {\n if (buildGen !== this.treeBuildGeneration) {\n node.loaded = true;\n return node;\n }\n if (!(await workspaceService.isResourceInCurrentWorkspace(resource))) {\n node.loaded = true;\n return node;\n }\n const detail = error instanceof Error ? error.message : String(error);\n node.loadError = detail;\n logger.error('Failed to load directory children:', error);\n }\n // Mark directory as loaded even if it has no children or loading failed,\n // so empty folders don't stay in a perpetual \"loading\" state.\n node.loaded = true;\n }\n\n if (resource instanceof UnavailableWorkspaceFolderDirectory) {\n node.placeholderNotice = resource.getFailureReason();\n }\n\n return node;\n }\n\n createTreeItems(node: TreeNode, expanded = false): TemplateResult {\n if (!node) {\n return html``\n }\n\n // Treat a directory as \"lazy\" only if its children\n // have never been loaded. Once loaded (even if empty),\n // we clear the lazy flag so the progress ring disappears.\n const isLazy = !node.leaf && !node.loaded;\n const resource = node.data as Resource;\n const isFile = resource instanceof File;\n const isDraggable = !!resource.getParent();\n const iconSpec = isFile\n ? editorRegistry.getFileIcon(resource.getName())\n : (node.icon || \"folder-open\");\n const workspaceTag = node.workspaceTag;\n const loadError = node.loadError;\n const placeholderNotice = node.placeholderNotice;\n const issueText = loadError\n ? t.FOLDER_LOAD_FAILED({ detail: loadError })\n : placeholderNotice\n ? t.FOLDER_UNAVAILABLE({ detail: placeholderNotice })\n : null;\n\n return html`\n <wa-tree-item \n draggable=${isDraggable}\n @dragstart=${isDraggable ? this.nobubble((e: Event) => this.onDragStart(e as DragEvent, resource)) : undefined}\n @dblclick=${this.nobubble(this.onFileDoubleClicked)}\n @wa-lazy-load=${this.nobubble((e: Event) => this.onLazyLoad(e, node))}\n .model=${node} \n ?expanded=${expanded}\n ?lazy=${isLazy}>\n <div class=\"tree-item-rows\">\n <div class=\"tree-item-label-row\">\n <span class=\"tree-label\">\n ${icon(iconSpec, { label: node.leaf ? t.FILE : t.FOLDER })}\n <span class=\"tree-label-text\">${node.label}</span>\n ${!node.leaf && workspaceTag\n ? html`<wa-badge appearance=\"outlined\" variant=\"neutral\" style=\"font-size: var(--wa-font-size-xs);\">${workspaceTag}</wa-badge>`\n : null}\n </span>\n </div>\n ${issueText\n ? html`<div class=\"tree-item-detail-row tree-item-error-text\">${issueText}</div>`\n : nothing}\n </div>\n ${node.children.map(child => this.createTreeItems(child, false))}\n </wa-tree-item>`\n }\n\n private onDragStart(e: DragEvent, resource: Resource) {\n if (!e.dataTransfer) return;\n\n // Do not allow dragging the synthetic workspace root node.\n if (!resource.getParent()) return;\n\n const currentTarget = e.currentTarget as HTMLElement | null;\n const tree = currentTarget?.closest('wa-tree') as any | null;\n\n const selectedItems: Array<{ model?: TreeNode }> = Array.isArray(tree?.selectedItems)\n ? tree.selectedItems\n : [];\n\n const resources: Resource[] = [];\n\n if (selectedItems.length > 0) {\n for (const item of selectedItems) {\n const node = item.model as TreeNode | undefined;\n const data = node?.data as Resource | undefined;\n if (data && data.getParent()) {\n resources.push(data);\n }\n }\n }\n\n if (resources.length === 0) {\n resources.push(resource);\n }\n\n const workspacePaths = resources.map(r => r.getWorkspacePath());\n const primaryName = resources.length === 1 ? resources[0].getName() : `${resources.length} items`;\n\n e.dataTransfer.effectAllowed = 'copyMove';\n const payload = workspacePaths.join('\\n');\n\n e.dataTransfer.setData('text/plain', payload);\n e.dataTransfer.setData('application/x-workspace-file', payload);\n e.dataTransfer.setData('text/uri-list', payload);\n\n if (e.dataTransfer.setDragImage) {\n const dragImage = document.createElement('div');\n dragImage.textContent = primaryName;\n dragImage.style.position = 'absolute';\n dragImage.style.top = '-1000px';\n dragImage.style.padding = '4px 8px';\n dragImage.style.background = 'var(--wa-color-neutral-10)';\n dragImage.style.border = '1px solid var(--wa-color-neutral-30)';\n dragImage.style.borderRadius = '4px';\n document.body.appendChild(dragImage);\n e.dataTransfer.setDragImage(dragImage, 0, 0);\n setTimeout(() => document.body.removeChild(dragImage), 0);\n }\n }\n\n private async onLazyLoad(event: Event, node: TreeNode) {\n const resource = node.data as Resource;\n if (resource instanceof Directory && node.children.length === 0) {\n await this.loadNodeChildren(node, resource);\n }\n }\n\n private async loadNodeChildren(node: TreeNode, resource: Directory) {\n if (this.loadingNodes.has(node)) {\n return;\n }\n\n const buildGen = this.treeBuildGeneration;\n this.loadingNodes.add(node);\n try {\n const children = await resource.listChildren(false);\n if (buildGen !== this.treeBuildGeneration) {\n return;\n }\n for (const childResource of children) {\n if (HIDE_DOT_RESOURCE && childResource.getName().startsWith(\".\")) {\n continue;\n }\n const child = await this.resourceToTreeNode(childResource, false);\n if (buildGen !== this.treeBuildGeneration) {\n return;\n }\n node.children.push(child);\n }\n node.children.sort(treeNodeComparator);\n // Children have now been loaded at least once (even if none remain\n // after filtering), so mark the node as loaded to disable lazy mode.\n node.loaded = true;\n this.requestUpdate();\n } catch (error) {\n if (buildGen !== this.treeBuildGeneration) {\n return;\n }\n if (!(await workspaceService.isResourceInCurrentWorkspace(resource))) {\n node.loaded = true;\n this.requestUpdate();\n return;\n }\n const detail = error instanceof Error ? error.message : String(error);\n node.loadError = detail;\n logger.error('Failed to load directory children:', error);\n this.requestUpdate();\n } finally {\n this.loadingNodes.delete(node);\n }\n }\n\n async onFileDoubleClicked(event: Event) {\n const item = event.currentTarget as HTMLElement & { model?: TreeNode; expanded?: boolean };\n const node = item.model;\n if (!node) {\n return;\n }\n\n const resource = node.data as Resource;\n if (resource instanceof File) {\n activeSelectionSignal.set(resource);\n void this.executeCommand(\"open_editor\", {});\n return;\n }\n\n if (!node.leaf && \"expanded\" in item) {\n item.expanded = !item.expanded;\n }\n }\n\n onSelectionChanged(event: Event) {\n // @ts-ignore\n const selection = event.detail.selection\n if (selection && selection.length > 0) {\n const node: TreeNode = selection[0].model\n const data = node.data\n activeSelectionSignal.set(data)\n const resource = data as Resource;\n const path = resource?.getWorkspacePath?.();\n if (typeof path === 'string') {\n this.persistSelectedPath(path);\n } else {\n this.persistSelectedPath(null);\n }\n if (data instanceof File) {\n this.fileEditorOptions = editorRegistry.getEditorOptionsForInput(data)\n } else {\n this.fileEditorOptions = []\n }\n } else {\n activeSelectionSignal.set(undefined)\n this.persistSelectedPath(null);\n this.fileEditorOptions = []\n }\n }\n\n private currentDropTarget?: HTMLElement;\n\n private getDirectoryDropTargetFromEvent(e: DragEvent): Directory | undefined {\n if (!this.workspaceDir) return undefined;\n\n const target = e.target as HTMLElement;\n const treeItem = target.closest('wa-tree-item');\n if (!treeItem) {\n const connectedRoots = this.root?.children ?? [];\n if (connectedRoots.length !== 1) {\n return undefined;\n }\n const singleRootResource = connectedRoots[0]?.data;\n return singleRootResource instanceof Directory ? singleRootResource : undefined;\n }\n\n const node: TreeNode | undefined = (treeItem as WaTreeItemElement).model;\n const resource = node?.data as Resource | undefined;\n if (resource instanceof Directory) {\n return resource;\n }\n return undefined;\n }\n\n private setupDragAndDrop() {\n const treeElement = this.treeRef.value;\n if (!treeElement) return;\n\n const dragOverHandler = (e: DragEvent) => {\n const types = e.dataTransfer?.types;\n if (!types) return;\n\n const isOsFileDrop = types.includes('Files');\n const isWorkspaceDrop = types.includes('application/x-workspace-file');\n if (!isOsFileDrop && !isWorkspaceDrop) return;\n\n const targetDir = this.getDirectoryDropTargetFromEvent(e);\n if (!targetDir) {\n this.currentDropTarget?.classList.remove('drop-target');\n this.currentDropTarget = undefined;\n treeElement.classList.remove('drag-over');\n return;\n }\n\n e.preventDefault();\n if (e.dataTransfer) {\n if (isWorkspaceDrop) {\n e.dataTransfer.dropEffect = (e.ctrlKey || e.metaKey) ? 'copy' : 'move';\n } else {\n e.dataTransfer.dropEffect = 'copy';\n }\n }\n\n treeElement.classList.add('drag-over');\n\n const target = e.target as HTMLElement;\n const treeItem = target.closest('wa-tree-item') as HTMLElement;\n\n if (!treeItem) {\n this.currentDropTarget?.classList.remove('drop-target');\n this.currentDropTarget = undefined;\n return;\n }\n\n if (treeItem !== this.currentDropTarget) {\n this.currentDropTarget?.classList.remove('drop-target');\n this.currentDropTarget = treeItem;\n treeItem.classList.add('drop-target');\n }\n };\n\n const dragEnterHandler = (e: DragEvent) => {\n const types = e.dataTransfer?.types;\n if (!types) return;\n\n const isOsFileDrop = types.includes('Files');\n const isWorkspaceDrop = types.includes('application/x-workspace-file');\n if (!isOsFileDrop && !isWorkspaceDrop) return;\n\n const targetDir = this.getDirectoryDropTargetFromEvent(e);\n if (!targetDir) return;\n\n e.preventDefault();\n treeElement.classList.add('drag-over');\n };\n\n const dragLeaveHandler = (e: DragEvent) => {\n const rect = treeElement.getBoundingClientRect();\n const x = e.clientX;\n const y = e.clientY;\n\n if (x <= rect.left || x >= rect.right || y <= rect.top || y >= rect.bottom) {\n treeElement.classList.remove('drag-over');\n this.currentDropTarget?.classList.remove('drop-target');\n this.currentDropTarget = undefined;\n }\n };\n\n const dropHandler = async (e: DragEvent) => {\n e.preventDefault();\n treeElement.classList.remove('drag-over');\n this.currentDropTarget?.classList.remove('drop-target');\n this.currentDropTarget = undefined;\n\n if (!e.dataTransfer || !this.workspaceDir) return;\n\n const targetDir = this.getDirectoryDropTargetFromEvent(e);\n if (!targetDir) return;\n const types = e.dataTransfer.types;\n\n if (types.includes('Files')) {\n const files = Array.from(e.dataTransfer.files);\n if (files.length === 0) return;\n await this.handleFilesDrop(files, targetDir);\n return;\n }\n\n if (types.includes('application/x-workspace-file')) {\n await this.handleWorkspaceDrop(e, targetDir);\n return;\n }\n };\n\n treeElement.removeEventListener('dragover', dragOverHandler as any);\n treeElement.removeEventListener('dragenter', dragEnterHandler as any);\n treeElement.removeEventListener('dragleave', dragLeaveHandler as any);\n treeElement.removeEventListener('drop', dropHandler as any);\n\n treeElement.addEventListener('dragover', dragOverHandler);\n treeElement.addEventListener('dragenter', dragEnterHandler);\n treeElement.addEventListener('dragleave', dragLeaveHandler);\n treeElement.addEventListener('drop', dropHandler);\n }\n\n private async handleWorkspaceDrop(e: DragEvent, targetDir: Directory) {\n if (!e.dataTransfer) return;\n\n const payload = e.dataTransfer.getData('application/x-workspace-file');\n if (!payload) return;\n\n const paths = payload\n .split(/\\r?\\n/)\n .map(p => p.trim())\n .filter(p => !!p);\n\n if (paths.length === 0) return;\n\n const workspace = await workspaceService.getWorkspace();\n if (!workspace) {\n logger.warn('Workspace drop ignored because no workspace is connected');\n return;\n }\n\n const moveWithinSameBackend = async (src: Resource): Promise<boolean> => {\n const srcRoot = src.getWorkspace();\n const destRoot = targetDir.getWorkspace();\n if (!srcRoot || !destRoot) return false;\n\n // Only allow move when source and destination share the same backend root.\n return srcRoot === destRoot && !(e.ctrlKey || e.metaKey);\n };\n\n const srcRoots = new Set<Directory>();\n const destRoot = targetDir.getWorkspace();\n\n let processed = 0;\n let failed = 0;\n\n const sources: { path: string; resource: Resource }[] = [];\n\n for (const path of paths) {\n try {\n const src = await workspace.getResource(path);\n if (!src) {\n logger.warn(`Workspace drop: source not found for path \"${path}\"`);\n failed++;\n continue;\n }\n\n sources.push({ path, resource: src });\n const root = src.getWorkspace();\n if (root) {\n srcRoots.add(root);\n }\n } catch (error) {\n logger.error(`Failed to handle workspace drop for \"${path}\":`, error);\n failed++;\n }\n }\n\n if (sources.length === 0) {\n if (failed > 0) {\n logger.info(`Workspace drop failed for ${failed} item(s)`);\n }\n return;\n }\n\n let isCrossConnection = false;\n if (destRoot) {\n for (const root of srcRoots) {\n if (root !== destRoot) {\n isCrossConnection = true;\n break;\n }\n }\n }\n\n if (isCrossConnection && destRoot) {\n try {\n const srcRootsArray = Array.from(srcRoots);\n const srcInfo = await workspaceService.getFolderInfoForDirectory(\n srcRootsArray[0]\n );\n const destInfo = await workspaceService.getFolderInfoForDirectory(destRoot);\n const srcBackend = srcInfo?.backendName ?? t.UNKNOWN_BACKEND;\n const destBackend = destInfo?.backendName ?? t.UNKNOWN_BACKEND;\n\n const confirmed = await confirmDialog(t.DND_CROSS_CONNECTION_CONFIRM({\n count: String(sources.length),\n srcBackend,\n destBackend\n }));\n if (!confirmed) {\n return;\n }\n } catch (err) {\n logger.debug('Failed to resolve cross-connection info for DnD', err);\n }\n }\n\n for (const { path, resource } of sources) {\n try {\n const move = await moveWithinSameBackend(resource);\n await workspaceService.copyResource(resource, targetDir, { move });\n processed++;\n } catch (error) {\n logger.error(`Failed to handle workspace drop for \"${path}\":`, error);\n failed++;\n }\n }\n\n logger.info(\n `Workspace drop completed: ${processed}/${sources.length} items ${failed > 0 ? `, ${failed} failed` : ''}`\n );\n\n await this.loadWorkspace(this.workspaceDir, true);\n }\n\n private async handleFilesDrop(files: globalThis.File[], targetDir: Directory) {\n const total = files.length;\n let processed = 0;\n let failed = 0;\n let skipped = 0;\n\n for (const file of files) {\n try {\n const targetPath = this.buildTargetPath(targetDir, file.name);\n\n const existingFile = await this.workspaceDir!.getResource(targetPath);\n if (existingFile) {\n const overwrite = await confirmDialog(t.FILE_EXISTS_OVERWRITE({ fileName: file.name }));\n if (!overwrite) {\n skipped++;\n continue;\n }\n }\n\n const workspaceFile = await this.workspaceDir!.getResource(\n targetPath,\n { create: true }\n ) as File;\n\n await workspaceFile.saveContents(file);\n\n processed++;\n } catch (error) {\n logger.error(`Failed to upload ${file.name}:`, error);\n failed++;\n }\n }\n\n logger.info(`Uploaded ${processed}/${total} files${skipped > 0 ? `, ${skipped} skipped` : ''}${failed > 0 ? `, ${failed} failed` : ''}`);\n\n await this.loadWorkspace(this.workspaceDir);\n }\n\n private buildTargetPath(targetDir: Directory, fileName: string): string {\n const dirPath = targetDir.getWorkspacePath();\n return dirPath ? `${dirPath}/${fileName}` : fileName;\n }\n\n protected renderContent() {\n return html`\n <div class=\"tree\" ${ref(this.treeRef)} style=\"--drop-files-text: '${t.DROP_FILES_HERE}'\">\n ${when(!this.workspaceDir, () => html`\n <docks-no-content message=\"${t.SELECT_WORKSPACE}\"></docks-no-content>`, () => when(this.root, () => html`\n <wa-tree @wa-selection-change=${this.nobubble(this.onSelectionChanged)}\n style=\"--indent-guide-width: 1px;\">\n ${this.root!.children.map(child => this.createTreeItems(child, true))}\n </wa-tree>`, () => html``))}\n </div>\n `\n }\n\n static styles = css`\n :host {\n }\n \n .tree {\n height: 100%;\n position: relative;\n transition: all 0.2s ease;\n }\n \n .tree.drag-over {\n background-color: var(--wa-color-brand-fill-quiet);\n outline: 2px dashed var(--wa-color-brand-border-normal);\n outline-offset: -4px;\n border-radius: var(--wa-border-radius-medium);\n }\n \n .tree.drag-over::before {\n content: var(--drop-files-text);\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n background: var(--wa-color-brand-fill-loud);\n color: var(--wa-color-brand-on-loud);\n padding: var(--wa-spacing-large);\n border-radius: var(--wa-border-radius-large);\n font-weight: bold;\n pointer-events: none;\n z-index: 1000;\n opacity: 0.3;\n }\n\n .tree-item-rows {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n gap: var(--wa-space-2xs);\n min-width: 0;\n width: 100%;\n }\n\n .tree-item-label-row {\n min-width: 0;\n }\n\n .tree-item-detail-row {\n width: 100%;\n min-width: 0;\n box-sizing: border-box;\n overflow-wrap: anywhere;\n }\n\n .tree-item-error-text {\n font-size: var(--wa-font-size-s);\n line-height: var(--wa-line-height-normal);\n color: var(--wa-color-danger-text, #c62828);\n }\n\n .tree-label {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n }\n\n .tree-label-text {\n white-space: nowrap;\n }\n\n wa-tree-item.drop-target {\n background-color: var(--wa-color-brand-fill-loud);\n color: var(--wa-color-brand-on-loud);\n border-radius: var(--wa-border-radius-small);\n outline: 2px solid var(--wa-color-brand-border-loud);\n outline-offset: -2px;\n }\n `;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'docks-filebrowser': DocksFileBrowser\n }\n}\n","import {contributionRegistry, HTMLContribution} from \"../core/contributionregistry\";\nimport {TOOLBAR_BOTTOM_CENTER} from \"../core/constants\";\nimport {customElement} from \"lit/decorators.js\";\nimport { DocksElement } from \"../parts/element\";\nimport {css, html, render} from \"lit\";\nimport {activeTasksSignal} from \"../core/appstate\";\nimport {taskService, ProgressMonitor} from \"../core/taskservice\";\nimport {i18n} from \"../core/i18n\";\n\nconst t = await i18n(import.meta.glob('./tasks*.json'));\n\ncontributionRegistry.registerContribution(TOOLBAR_BOTTOM_CENTER, {\n component: \"<docks-tasks></docks-tasks>\"\n} as HTMLContribution)\n\n// Singleton dialog container for progress dialog\nlet progressDialogContainer: HTMLElement | null = null;\n\nfunction getProgressDialogContainer(): HTMLElement {\n if (!progressDialogContainer) {\n progressDialogContainer = document.createElement('div');\n progressDialogContainer.id = 'progress-dialog-container';\n document.body.appendChild(progressDialogContainer);\n }\n return progressDialogContainer;\n}\n\nfunction getDialogElement(): any {\n const container = getProgressDialogContainer();\n return container.querySelector('wa-dialog') as any;\n}\n\nfunction showProgressDialog() {\n updateProgressDialog(true);\n}\n\nfunction updateProgressDialog(forceOpen = false) {\n const container = getProgressDialogContainer();\n const tasks = taskService.getActiveTasks();\n const currentTaskCount = tasks.length;\n \n if (currentTaskCount === 0) {\n render(html``, container);\n return;\n }\n\n // Check if dialog exists and is open (before rendering, since render replaces DOM)\n const existingDialog = getDialogElement();\n const isOpen = forceOpen || (existingDialog?.open === true);\n\n // Only update dialog if it's open or if we're forcing it open\n // If it was closed (dismissed), don't show it again on progress updates\n if (!isOpen) {\n return;\n }\n\n const handleClose = () => {\n // Close the dialog - this prevents it from showing again on progress updates\n const dialog = getDialogElement();\n if (dialog) {\n dialog.open = false;\n }\n };\n\n const handleAfterHide = () => {\n // Clean up after the dialog closes and animations complete\n render(html``, container);\n };\n\n const template = html`\n <wa-dialog \n label=\"${t.ACTIVE_TASKS}\" \n open\n light-dismiss\n style=\"--width: 600px;\"\n @wa-request-close=${handleClose}\n @wa-after-hide=${handleAfterHide}\n >\n <style>\n .progress-dialog-content {\n display: flex;\n flex-direction: column;\n gap: 1.5rem;\n }\n \n .tasitem {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n padding: 1rem;\n background: var(--wa-color-neutral-10);\n border-radius: 8px;\n border: 1px solid var(--wa-color-neutral-20);\n }\n \n :host-context(.wa-light) .tasitem {\n background: var(--wa-color-neutral-95);\n border: 1px solid var(--wa-color-neutral-85);\n }\n \n .tasheader {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n }\n \n .tasname {\n font-weight: 600;\n font-size: 1rem;\n color: var(--wa-color-neutral-90);\n }\n \n :host-context(.wa-light) .tasname {\n color: var(--wa-color-neutral-10);\n }\n \n .tasmessage {\n font-size: 0.875rem;\n color: var(--wa-color-neutral-70);\n margin-top: 0.25rem;\n }\n \n :host-context(.wa-light) .tasmessage {\n color: var(--wa-color-neutral-30);\n }\n \n .tasprogress {\n margin-top: 0.5rem;\n }\n \n wa-progress-bar {\n --tracheight: 1.5rem;\n }\n \n wa-progress-bar::part(label) {\n text-align: center;\n width: 100%;\n font-size: 0.875rem;\n }\n \n .no-tasks {\n text-align: center;\n padding: 2rem;\n color: var(--wa-color-neutral-60);\n }\n \n :host-context(.wa-light) .no-tasks {\n color: var(--wa-color-neutral-40);\n }\n </style>\n \n <div class=\"progress-dialog-content\">\n ${tasks.map((taskProgress: ProgressMonitor) => {\n const hasProgress = taskProgress.progress >= 0 || taskProgress.totalSteps > 0\n const progress = taskProgress.progress >= 0\n ? taskProgress.progress\n : (taskProgress.totalSteps > 0 \n ? Math.round((taskProgress.currentStep / taskProgress.totalSteps) * 100)\n : 0)\n \n const showSteps = taskProgress.progress < 0 && taskProgress.totalSteps > 0\n \n return html`\n <div class=\"tasitem\">\n <div class=\"tasheader\">\n <wa-icon name=\"hourglass\" style=\"color: var(--wa-color-warning-fill-loud);\"></wa-icon>\n <div style=\"flex: 1;\">\n <div class=\"tasname\">${taskProgress.name}</div>\n ${taskProgress.message ? html`\n <div class=\"tasmessage\">${taskProgress.message}</div>\n ` : ''}\n </div>\n </div>\n <div class=\"tasprogress\">\n ${hasProgress ? html`\n <wa-progress-bar value=\"${progress}\">\n ${showSteps ? `${taskProgress.currentStep}/${taskProgress.totalSteps} - ` : ''}${progress}%\n </wa-progress-bar>\n ` : html`\n <wa-progress-bar indeterminate></wa-progress-bar>\n `}\n </div>\n </div>\n `\n })}\n </div>\n </wa-dialog>\n `;\n\n render(template, container);\n}\n\n@customElement('docks-tasks')\nexport class DocksTasks extends DocksElement {\n static styles = css`\n :host {\n display: flex;\n align-items: center;\n }\n \n .tasindicator {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n cursor: pointer;\n padding: 0.25rem 0.5rem;\n border-radius: 4px;\n transition: background-color 0.2s;\n }\n \n .tasindicator:hover {\n background: var(--wa-color-neutral-15);\n }\n \n :host-context(.wa-light) .tasindicator:hover {\n background: var(--wa-color-neutral-85);\n }\n \n .tascount {\n font-size: 0.875rem;\n color: var(--wa-color-neutral-70);\n }\n \n :host-context(.wa-light) .tascount {\n color: var(--wa-color-neutral-30);\n }\n \n .tasbar-wrap {\n width: 3rem;\n }\n \n .tasbar-wrap wa-progress-bar {\n --tracheight: 4px;\n }\n `\n\n protected doBeforeUI() {\n this.watch(activeTasksSignal, () => {\n // Update dialog content if it's open, and always update the indicator\n updateProgressDialog();\n this.requestUpdate();\n });\n }\n\n private handleIndicatorClick() {\n showProgressDialog();\n }\n\n protected render() {\n activeTasksSignal.get();\n const tasks = taskService.getActiveTasks();\n const taskCount = tasks.length;\n\n if (taskCount === 0) {\n return html``;\n }\n\n return html`\n <div class=\"tasindicator\" @click=${this.handleIndicatorClick} title=\"${t.ACTIVE_TASKS_TITLE({ taskCount: taskCount.toString() })}\">\n <wa-spinner\n style=\"font-size: 1rem; --indicator-color: var(--wa-color-warning-fill-loud);\"\n label=\"${t.ACTIVE_TASKS}\"\n ></wa-spinner>\n <wa-badge appearance=\"outlined\" variant=\"neutral\" pill>${taskCount}</wa-badge>\n <div class=\"tasbar-wrap\"><wa-progress-bar indeterminate></wa-progress-bar></div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'docks-tasks': DocksTasks\n }\n}","import { appLoaderService } from '../core/apploader';\nimport { activePartSignal } from '../core/appstate';\nimport { i18n } from '../core/i18n';\nimport { watchSignal } from '../core/signals';\n\nconst t = await i18n(import.meta.glob('./partname*.json'));\n\n/**\n * Human-readable label for the focused part (same logic as docks-part-name).\n */\nexport function getActivePartDisplayName(): string {\n const activePart = activePartSignal.get();\n if (!activePart) {\n return t.NO_PART;\n }\n return activePart.tabContribution?.label || activePart.getAttribute('id') || t.NO_PART;\n}\n\n/** Wait after the last active-part change before updating `document.title` (rapid tab switches). */\nconst TITLE_DEBOUNCE_MS = 250;\n\nlet titleDebounceTimer: ReturnType<typeof setTimeout> | null = null;\n\nfunction applyDocumentTitle(): void {\n const appName = appLoaderService.getCurrentApp()?.name ?? '';\n const activePart = activePartSignal.get();\n if (!activePart) {\n document.title = appName;\n return;\n }\n const part =\n activePart.tabContribution?.label || activePart.getAttribute('id') || t.NO_PART;\n\n if (appName) {\n document.title = `${appName} | ${part}`;\n } else {\n document.title = part;\n }\n}\n\nfunction scheduleApplyDocumentTitle(): void {\n if (titleDebounceTimer !== null) {\n clearTimeout(titleDebounceTimer);\n }\n titleDebounceTimer = setTimeout(() => {\n titleDebounceTimer = null;\n applyDocumentTitle();\n }, TITLE_DEBOUNCE_MS);\n}\n\nwatchSignal(activePartSignal, () => scheduleApplyDocumentTitle());\n\nwindow.addEventListener('app-loaded', () => {\n if (titleDebounceTimer !== null) {\n clearTimeout(titleDebounceTimer);\n titleDebounceTimer = null;\n }\n applyDocumentTitle();\n});\n","import {customElement} from \"lit/decorators.js\";\nimport {DocksElement} from \"../parts/element\";\nimport {html} from \"lit\";\nimport {activePartSignal} from \"../core/appstate\";\nimport {getActivePartDisplayName} from \"./document-title\";\nimport {contributionRegistry, HTMLContribution} from \"../core/contributionregistry\";\nimport {TOOLBAR_BOTTOM_CENTER} from \"../core/constants\";\nimport { icon } from '../core/icon-utils';\nimport { i18n } from '../core/i18n';\n\nconst t = await i18n(import.meta.glob('./partname*.json'));\n\ncontributionRegistry.registerContribution(TOOLBAR_BOTTOM_CENTER, {\n component: \"<docks-part-name></docks-part-name>\"\n} as HTMLContribution)\n\n@customElement('docks-part-name')\nexport class DocksPartName extends DocksElement {\n protected doBeforeUI() {\n this.watch(activePartSignal, () => {\n this.requestUpdate();\n });\n }\n \n protected render() {\n const activePart = activePartSignal.get();\n const partIcon = activePart?.tabContribution?.icon || \"box\";\n \n return html`\n <wa-button \n appearance=\"plain\"\n size=\"small\"\n title=\"${t.ACTIVE_PART}\">\n ${icon(partIcon, { label: 'Part', slot: 'start' })}\n ${getActivePartDisplayName()}\n </wa-button>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'docks-part-name': DocksPartName\n }\n}\n\n","import {css, html} from 'lit'\nimport {when} from \"lit/directives/when.js\";\nimport {customElement, state} from 'lit/decorators.js'\nimport { DocksPart } from \"../parts/part\";\nimport {Extension, extensionRegistry, TOPIC_EXTENSIONS_CHANGED} from \"../core/extensionregistry\";\nimport { icon } from '../core/icon-utils';\nimport {subscribe} from \"../core/events\";\nimport {appLoaderService} from \"../core/apploader\";\nimport {i18n} from \"../core/i18n\";\nimport {promptDialog} from \"../dialogs/prompt-dialog\";\nimport {toastError, toastInfo} from \"../core/toast\";\nimport {esmShService, EsmShSource} from \"../core/esmsh-service\";\nimport {taskService} from \"../core/taskservice\";\nimport {createLogger} from \"../core/logger\";\n\nconst logger = createLogger('DocksExtensions');\n\nconst t = await i18n(import.meta.glob('./extensions*.json'));\n\n\n@customElement('docks-extensions')\nexport class DocksExtensions extends DocksPart {\n @state()\n private selectedExtension?: Extension;\n\n @state()\n private filterText: string = '';\n\n @state()\n private showRegisterDialog: boolean = false;\n\n @state()\n private registerExtensionData: Partial<Extension> = {};\n\n\n\n protected doInitUI() {\n subscribe(TOPIC_EXTENSIONS_CHANGED, () => {\n this.requestUpdate()\n })\n }\n\n onExtensionDblClick() {\n\n }\n\n enable(extension: Extension) {\n extensionRegistry.enable(extension.id, true);\n this.requestUpdate()\n }\n\n disable(extension: Extension) {\n extensionRegistry.disable(extension.id, true);\n this.requestUpdate()\n }\n\n\n private isExtensionRequired(extensionId: string): boolean {\n const currentApp = appLoaderService.getCurrentApp();\n if (!currentApp || !currentApp.extensions) {\n return false;\n }\n return currentApp.extensions.includes(extensionId);\n }\n\n selectionChanged(e: CustomEvent) {\n const selection = e.detail.selection || [];\n if (selection.length > 0 && selection[0].model) {\n // @ts-ignore\n this.selectedExtension = selection[0].model;\n } else {\n this.selectedExtension = undefined;\n }\n }\n\n private getFilteredExtensions(): Extension[] {\n if (!this.filterText.trim()) {\n return extensionRegistry.getExtensions();\n }\n const filter = this.filterText.toLowerCase();\n return extensionRegistry.getExtensions().filter(ext => {\n return String(ext.name).toLowerCase().includes(filter) ||\n (ext.description ? String(ext.description).toLowerCase().includes(filter) : false) ||\n ext.id.toLowerCase().includes(filter);\n });\n }\n\n\n private getGroupedExtensions(): { enabled: Extension[], available: Extension[] } {\n const filtered = this.getFilteredExtensions();\n const enabled: Extension[] = [];\n const available: Extension[] = [];\n \n filtered.forEach(ext => {\n if (extensionRegistry.isEnabled(ext.id)) {\n enabled.push(ext);\n } else {\n available.push(ext);\n }\n });\n \n enabled.sort((a, b) => String(a.name).localeCompare(String(b.name)));\n available.sort((a, b) => String(a.name).localeCompare(String(b.name)));\n \n return { enabled, available };\n }\n\n private isExternalExtension(extension: Extension): boolean {\n return extension.external === true;\n }\n\n\n private handleFilterInput(e: Event) {\n this.filterText = (e.target as HTMLInputElement).value;\n this.requestUpdate();\n }\n\n private clearFilter() {\n this.filterText = '';\n this.requestUpdate();\n }\n\n private async handleRegisterExtension() {\n try {\n const url = await promptDialog(\"Enter extension URL or source identifier:\", \"\", false);\n if (!url) {\n return;\n }\n\n await taskService.runAsync(\"Registering extension\", async () => {\n let finalUrl = url;\n \n if (esmShService.isGitHubUrl(url)) {\n finalUrl = esmShService.convertGitHubUrlToSource(url);\n }\n \n const parsed = esmShService.parseSource(finalUrl);\n \n if (parsed?.type === 'github') {\n await this.fetchGitHubMetadata(parsed, finalUrl);\n } else {\n this.registerExtensionData = {\n url: finalUrl,\n id: '',\n name: '',\n description: ''\n };\n this.showRegisterDialog = true;\n this.requestUpdate();\n }\n });\n } catch (error) {\n toastError(`Failed to register extension: ${error}`);\n }\n }\n\n private async fetchGitHubMetadata(parsed: EsmShSource, url: string) {\n try {\n const packageJson = await esmShService.fetchGitHubPackageJson(parsed);\n \n const owner = parsed.owner!;\n const repo = parsed.repo!;\n const extensionId = packageJson.name || `ext.${owner}-${repo}`;\n const extensionName = packageJson.name || `${owner}/${repo}`;\n const description = packageJson.description || '';\n const version = packageJson.version || '';\n const author = packageJson.author || (typeof packageJson.author === 'string' ? packageJson.author : packageJson.author?.name) || '';\n \n this.registerExtensionData = {\n id: extensionId,\n name: extensionName,\n description: description,\n url: url,\n version: version,\n author: author,\n icon: 'puzzle-piece',\n external: true\n };\n \n this.showRegisterDialog = true;\n this.requestUpdate();\n } catch (error) {\n logger.warn(`Could not fetch package.json, using defaults: ${error}`);\n this.registerExtensionData = {\n url: url,\n id: '',\n name: '',\n description: ''\n };\n this.showRegisterDialog = true;\n this.requestUpdate();\n }\n }\n\n private async confirmRegisterExtension() {\n if (!this.registerExtensionData.url) {\n toastError(\"URL is required\");\n return;\n }\n\n if (!this.registerExtensionData.id) {\n toastError(\"Extension ID is required\");\n return;\n }\n\n if (!this.registerExtensionData.name) {\n toastError(\"Extension name is required\");\n return;\n }\n\n try {\n await taskService.runAsync(\"Registering extension\", async () => {\n const extension: Extension = {\n id: this.registerExtensionData.id!,\n name: this.registerExtensionData.name!,\n description: this.registerExtensionData.description,\n url: this.registerExtensionData.url!,\n version: this.registerExtensionData.version,\n author: this.registerExtensionData.author,\n icon: this.registerExtensionData.icon || 'puzzle-piece',\n external: true\n };\n\n extensionRegistry.registerExtension(extension);\n await extensionRegistry.loadExtensionFromUrl(this.registerExtensionData.url!, extension.id);\n \n toastInfo(`Extension ${extension.name} registered successfully`);\n this.showRegisterDialog = false;\n this.registerExtensionData = {};\n this.requestUpdate();\n });\n } catch (error) {\n toastError(`Failed to register extension: ${error}`);\n }\n }\n\n private cancelRegisterExtension() {\n this.showRegisterDialog = false;\n this.registerExtensionData = {};\n this.requestUpdate();\n }\n\n protected renderToolbar() {\n return html`\n <wa-input\n placeholder=\"${t.FILTER_PLACEHOLDER}\"\n .value=${this.filterText}\n @input=${(e: Event) => this.handleFilterInput(e)}\n @wa-clear=${() => this.clearFilter()}\n with-clear\n size=\"small\"\n style=\"width: 300px;\">\n <wa-icon slot=\"start\" name=\"magnifying-glass\" label=\"Filter\"></wa-icon>\n </wa-input>\n <wa-button \n variant=\"primary\" \n appearance=\"plain\"\n @click=${() => this.handleRegisterExtension()}\n title=\"Register a new extension\">\n <wa-icon name=\"plus\" label=\"Add\"></wa-icon>\n Register Extension\n </wa-button>\n `;\n }\n\n protected renderContent() {\n const grouped = this.getGroupedExtensions();\n const hasAnyExtensions = grouped.enabled.length > 0 || grouped.available.length > 0;\n \n return html`\n ${when(this.showRegisterDialog, () => html`\n <wa-dialog \n label=\"Register Extension\"\n open\n @wa-request-close=${() => this.cancelRegisterExtension()}\n style=\"--wa-dialog-width: 500px;\">\n <div style=\"display: flex; flex-direction: column; gap: 1rem; padding: 1rem;\">\n <wa-input\n label=\"Extension ID *\"\n .value=${this.registerExtensionData.id || ''}\n @input=${(e: Event) => {\n this.registerExtensionData.id = (e.target as HTMLInputElement).value;\n this.requestUpdate();\n }}\n required\n hint=\"Unique identifier for the extension (e.g., 'ext.my-extension')\">\n </wa-input>\n \n <wa-input\n label=\"Name *\"\n .value=${this.registerExtensionData.name || ''}\n @input=${(e: Event) => {\n this.registerExtensionData.name = (e.target as HTMLInputElement).value;\n this.requestUpdate();\n }}\n required\n hint=\"Display name of the extension\">\n </wa-input>\n \n <wa-input\n label=\"Description\"\n .value=${this.registerExtensionData.description || ''}\n @input=${(e: Event) => {\n this.registerExtensionData.description = (e.target as HTMLInputElement).value;\n this.requestUpdate();\n }}\n hint=\"Description of what the extension does\">\n </wa-input>\n \n <wa-input\n label=\"URL *\"\n .value=${this.registerExtensionData.url || ''}\n @input=${(e: Event) => {\n this.registerExtensionData.url = (e.target as HTMLInputElement).value;\n this.requestUpdate();\n }}\n required\n readonly\n hint=\"Extension source URL or identifier\">\n </wa-input>\n \n <div style=\"display: flex; gap: 0.5rem;\">\n <wa-input\n label=\"Version\"\n .value=${this.registerExtensionData.version || ''}\n @input=${(e: Event) => {\n this.registerExtensionData.version = (e.target as HTMLInputElement).value;\n this.requestUpdate();\n }}\n style=\"flex: 1;\"\n hint=\"Extension version\">\n </wa-input>\n \n <wa-input\n label=\"Author\"\n .value=${this.registerExtensionData.author || ''}\n @input=${(e: Event) => {\n this.registerExtensionData.author = (e.target as HTMLInputElement).value;\n this.requestUpdate();\n }}\n style=\"flex: 1;\"\n hint=\"Extension author\">\n </wa-input>\n </div>\n \n <wa-input\n label=\"Icon\"\n .value=${this.registerExtensionData.icon || 'puzzle-piece'}\n @input=${(e: Event) => {\n this.registerExtensionData.icon = (e.target as HTMLInputElement).value;\n this.requestUpdate();\n }}\n hint=\"Icon name (FontAwesome icon)\">\n </wa-input>\n \n <div style=\"display: flex; justify-content: flex-end; gap: 0.5rem; margin-top: 1rem;\">\n <wa-button \n variant=\"default\" \n @click=${() => this.cancelRegisterExtension()}>\n Cancel\n </wa-button>\n <wa-button \n variant=\"primary\" \n @click=${() => this.confirmRegisterExtension()}\n ?disabled=${!this.registerExtensionData.id || !this.registerExtensionData.name || !this.registerExtensionData.url}>\n Register\n </wa-button>\n </div>\n </div>\n </wa-dialog>\n `)}\n <wa-split-panel position=\"30\" class=\"extensions-split-panel\">\n <div slot=\"start\" class=\"extensions-tree-panel\">\n <wa-scroller class=\"extensions-tree-scroller\" orientation=\"vertical\">\n <wa-tree \n selection=\"leaf\"\n style=\"--indent-guide-width: 1px;\" \n @wa-selection-change=\"${this.selectionChanged}\">\n ${hasAnyExtensions ? html`\n ${grouped.enabled.length > 0 ? html`\n <wa-tree-item expanded>\n <span>\n <wa-icon name=\"check-circle\" style=\"color: var(--wa-color-success-50);\"></wa-icon>\n ${t.INSTALLED} (${grouped.enabled.length})\n </span>\n ${grouped.enabled.map(e => {\n const isExternal = this.isExternalExtension(e);\n return html`\n <wa-tree-item @dblclick=${this.nobubble(this.onExtensionDblClick)} .model=${e}>\n <span>${icon(e.icon)}</span> ${e.name}${isExternal ? html` <span style=\"opacity: 0.6; font-size: 0.9em; margin-left: 0.5rem;\">(External)</span>` : ''}\n </wa-tree-item>\n `;\n })}\n </wa-tree-item>\n ` : ''}\n ${grouped.available.length > 0 ? html`\n <wa-tree-item expanded>\n <span>\n <wa-icon name=\"circle\" style=\"color: var(--wa-color-neutral-50);\"></wa-icon>\n ${t.AVAILABLE} (${grouped.available.length})\n </span>\n ${grouped.available.map(e => {\n const isExternal = this.isExternalExtension(e);\n return html`\n <wa-tree-item @dblclick=${this.nobubble(this.onExtensionDblClick)} .model=${e}>\n <span>${icon(e.icon)}</span> ${e.name}${isExternal ? html` <span style=\"opacity: 0.6; font-size: 0.9em; margin-left: 0.5rem;\">(External)</span>` : ''}\n </wa-tree-item>\n `;\n })}\n </wa-tree-item>\n ` : ''}\n ` : ''}\n ${!hasAnyExtensions ? html`\n <div style=\"padding: 1em; text-align: center; opacity: 0.7;\">\n ${t.NO_MATCHES({ filterText: this.filterText })}\n </div>\n ` : ''}\n </wa-tree>\n </wa-scroller>\n </div>\n <wa-scroller slot=\"end\" class=\"extensions-detail-scroller\" orientation=\"vertical\">\n <div class=\"extensions-detail-content\">\n ${when(this.selectedExtension, (e) => {\n const isExternal = this.isExternalExtension(e);\n const isEnabled = extensionRegistry.isEnabled(e.id);\n \n return html`\n <h1>${icon(e.icon)} ${e.name}${isExternal ? ' (External)' : ''}</h1>\n ${when(isExternal, () => html`\n <div class=\"marketplace-badge\">\n <wa-icon name=\"store\"></wa-icon>\n <span>${t.EXTERNAL_EXTENSION}</span>\n </div>\n `)}\n <hr>\n <div>\n ${when(isEnabled, () => html`\n <wa-button \n title=\"${this.isExtensionRequired(e.id) ? t.REQUIRED_HINT : t.DISABLE_TITLE}\" \n @click=\"${() => this.disable(e)}\"\n variant=\"danger\" \n appearance=\"plain\"\n ?disabled=${this.isExtensionRequired(e.id)}>\n <wa-icon name=\"xmark\" label=\"Uninstall\"></wa-icon> ${t.UNINSTALL}\n </wa-button>\n ${when(this.isExtensionRequired(e.id), () => html`\n <div class=\"required-hint\">\n <wa-icon name=\"info-circle\" style=\"color: var(--wa-color-primary-50);\"></wa-icon>\n <span>${t.REQUIRED_HINT}</span>\n </div>\n `)}\n `, () => html`\n <wa-button \n title=\"${t.ENABLE_TITLE}\" \n @click=\"${() => this.enable(e)}\"\n variant=\"brand\" \n appearance=\"plain\">\n <wa-icon name=\"download\" label=\"Install\"></wa-icon> ${t.INSTALL}\n </wa-button>\n `)}\n </div>\n\n ${when(e.experimental, () => html`\n <div style=\"margin-top: 1em;\">\n <wa-button size=\"small\" variant=\"warning\" appearance=\"plain\">\n <wa-icon name=\"triangle-exclamation\" label=\"Warning\"></wa-icon>\n </wa-button>\n <small><i>${t.EXPERIMENTAL}</i></small>\n </div>\n `)}\n\n ${when(e.version || e.author, () => html`\n <div style=\"margin-top: 1em; display: flex; flex-direction: column; gap: 0.5rem;\">\n ${when(e.version, () => html`\n <div style=\"display: flex; align-items: center; gap: 0.5rem;\">\n <wa-icon name=\"tag\" style=\"font-size: 0.9em; opacity: 0.7;\"></wa-icon>\n <span style=\"font-size: 0.9em; opacity: 0.8;\">${t.VERSION} <strong>${e.version}</strong></span>\n </div>\n `)}\n ${when(e.author, () => html`\n <div style=\"display: flex; align-items: center; gap: 0.5rem;\">\n <wa-icon name=\"user\" style=\"font-size: 0.9em; opacity: 0.7;\"></wa-icon>\n <span style=\"font-size: 0.9em; opacity: 0.8;\">${t.AUTHOR} <strong>${e.author}</strong></span>\n </div>\n `)}\n </div>\n `)}\n\n <p style=\"margin-top: 1em;\">${e.description}</p>\n\n ${when(e.dependencies && e.dependencies.length > 0, () => html`\n <div style=\"margin-top: 1.5em;\">\n <h3 style=\"margin-bottom: 0.5em;\">\n <wa-icon name=\"puzzle-piece\" style=\"font-size: 0.9em;\"></wa-icon>\n ${t.DEPENDENCIES}\n </h3>\n <div class=\"dependencies-list\">\n ${e.dependencies!.map(depId => {\n const depExt = extensionRegistry.getExtensions().find(ex => ex.id === depId);\n const isEnabled = extensionRegistry.isEnabled(depId);\n return html`\n <div class=\"dependency-item\">\n <wa-icon \n name=\"${isEnabled ? 'check-circle' : 'circle'}\" \n style=\"color: ${isEnabled ? 'var(--wa-color-success-50)' : 'var(--wa-color-neutral-50)'};\">\n </wa-icon>\n ${icon(depExt?.icon ?? 'puzzle-piece')}\n <span>${depExt?.name || depId}</span>\n ${!isEnabled ? html`\n <span class=\"dependency-badge\">${t.NOT_INSTALLED}</span>\n ` : ''}\n </div>\n `;\n })}\n </div>\n <small style=\"opacity: 0.7; display: block; margin-top: 0.5em;\">\n <wa-icon name=\"info-circle\" style=\"font-size: 0.9em;\"></wa-icon>\n ${t.DEPENDENCIES_HINT}\n </small>\n </div>\n `)}\n `;\n })}\n </div>\n </wa-scroller>\n </wa-split-panel>\n `\n }\n\n static styles = css`\n :host {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n\n .extensions-split-panel {\n flex: 1;\n min-height: 0;\n height: 100%;\n }\n\n .extensions-tree-panel {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n overflow: hidden;\n }\n\n .extensions-tree-scroller {\n flex: 1;\n min-height: 0;\n }\n\n .extensions-detail-scroller {\n height: 100%;\n min-height: 0;\n }\n\n .extensions-detail-content {\n padding: 1em;\n }\n\n wa-tree-item > span {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n }\n\n wa-tree-item:has(> wa-tree-item) {\n font-weight: 500;\n }\n\n .dependencies-list {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n }\n\n .dependency-item {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem;\n border-radius: 4px;\n background: var(--wa-color-surface-variant);\n }\n\n .dependency-item wa-icon:first-child {\n flex-shrink: 0;\n }\n\n .dependency-item icon {\n flex-shrink: 0;\n }\n\n .dependency-item span:not(.dependency-badge) {\n flex: 1;\n }\n\n .dependency-badge {\n font-size: 0.85rem;\n padding: 0.25rem 0.5rem;\n border-radius: 4px;\n background: var(--wa-color-warning-100);\n color: var(--wa-color-warning-900);\n }\n\n .required-hint {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n margin-top: 0.75rem;\n padding: 0.5rem;\n border-radius: 4px;\n background: var(--wa-color-primary-10);\n color: var(--wa-color-primary-70);\n font-size: 0.875rem;\n }\n\n .required-hint wa-icon {\n flex-shrink: 0;\n }\n\n .required-hint span {\n line-height: 1.4;\n }\n\n .marketplace-badge {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.375rem 0.875rem;\n border-radius: 4px;\n background: var(--wa-color-primary-10);\n color: var(--wa-color-primary-70);\n font-size: 0.875rem;\n font-weight: 500;\n margin-top: 0.75rem;\n margin-bottom: 0.5rem;\n border: 1px solid var(--wa-color-primary-30);\n }\n `;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'docks-extensions': DocksExtensions\n }\n}\n","import { css, html } from 'lit';\nimport { customElement, state } from 'lit/decorators.js';\nimport { DocksPart } from '../parts/part';\nimport { createRef, ref, Ref } from 'lit/directives/ref.js';\nimport { registerLogHandler, unregisterLogHandler, type LogLevel } from '../core/logger';\nimport { i18n } from '../core/i18n';\n\nconst t = await i18n(import.meta.glob('./logterminal*.json'));\n\nexport interface LogMessage {\n timestamp: Date;\n level: LogLevel;\n source: string;\n message: string;\n}\n\n@customElement('docks-log-terminal')\nexport class DocksLogTerminal extends DocksPart {\n @state()\n private messages: LogMessage[] = [];\n\n @state()\n private autoScroll: boolean = true;\n\n @state()\n private filter: LogLevel | 'all' = 'all';\n\n private containerRef: Ref<HTMLDivElement> = createRef();\n\n connectedCallback() {\n super.connectedCallback();\n // Load persisted settings\n this.loadSettings();\n // Register this terminal as the log handler\n registerLogHandler(this.log.bind(this));\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n // Unregister log handler\n unregisterLogHandler();\n }\n\n public log(source: string, message: string, level: LogLevel = 'info') {\n const logMessage: LogMessage = {\n timestamp: new Date(),\n level,\n source,\n message\n };\n \n this.messages = [...this.messages, logMessage];\n \n if (this.autoScroll) {\n this.updateComplete.then(() => {\n const container = this.containerRef.value;\n if (container) {\n container.scrollTop = container.scrollHeight;\n }\n });\n }\n }\n\n public clear() {\n this.messages = [];\n }\n\n private getFilteredMessages() {\n if (this.filter === 'all') {\n return this.messages;\n }\n return this.messages.filter(m => m.level === this.filter);\n }\n\n private formatTimestamp(date: Date): string {\n return date.toLocaleTimeString('en-US', { \n hour12: false, \n hour: '2-digit', \n minute: '2-digit', \n second: '2-digit' \n });\n }\n\n private getLevelIcon(level: LogLevel): string {\n switch (level) {\n case 'info': return 'circle-info';\n case 'warning': return 'triangle-exclamation';\n case 'error': return 'circle-xmark';\n case 'debug': return 'bug';\n }\n }\n\n private getLevelColor(level: LogLevel): string {\n switch (level) {\n case 'info': return 'var(--wa-color-primary-text, #0066cc)';\n case 'warning': return 'var(--wa-color-warning-text, #ff9800)';\n case 'error': return 'var(--wa-color-danger-text, #dc3545)';\n case 'debug': return 'var(--wa-color-neutral-text-subtle, #6c757d)';\n }\n }\n\n protected renderToolbar() {\n const infoCount = this.messages.filter(m => m.level === 'info').length;\n const warningCount = this.messages.filter(m => m.level === 'warning').length;\n const errorCount = this.messages.filter(m => m.level === 'error').length;\n const debugCount = this.messages.filter(m => m.level === 'debug').length;\n\n return html`\n <docks-command \n icon=\"list\"\n title=\"${t.ALL_LOGS}\"\n appearance=\"${this.filter === 'all' ? 'filled' : 'plain'}\"\n variant=\"${this.filter === 'all' ? 'brand' : 'neutral'}\"\n .action=${() => {\n this.filter = 'all';\n this.saveSettings();\n }}>\n ${t.ALL} (${this.messages.length})\n </docks-command>\n\n <docks-command \n icon=\"circle-info\"\n title=\"${t.INFO_LOGS}\"\n appearance=\"${this.filter === 'info' ? 'filled' : 'plain'}\"\n variant=\"${this.filter === 'info' ? 'brand' : 'neutral'}\"\n .action=${() => {\n this.filter = 'info';\n this.saveSettings();\n }}>\n ${t.INFO}${infoCount > 0 ? ` (${infoCount})` : ''}\n </docks-command>\n\n <docks-command \n icon=\"triangle-exclamation\"\n title=\"${t.WARNING_LOGS}\"\n appearance=\"${this.filter === 'warning' ? 'filled' : 'plain'}\"\n variant=\"${this.filter === 'warning' ? 'brand' : 'neutral'}\"\n .action=${() => {\n this.filter = 'warning';\n this.saveSettings();\n }}>\n ${t.WARNINGS}${warningCount > 0 ? ` (${warningCount})` : ''}\n </docks-command>\n\n <docks-command \n icon=\"circle-xmark\"\n title=\"${t.ERROR_LOGS}\"\n appearance=\"${this.filter === 'error' ? 'filled' : 'plain'}\"\n variant=\"${this.filter === 'error' ? 'brand' : 'neutral'}\"\n .action=${() => {\n this.filter = 'error';\n this.saveSettings();\n }}>\n ${t.ERRORS}${errorCount > 0 ? ` (${errorCount})` : ''}\n </docks-command>\n\n <docks-command \n icon=\"bug\"\n title=\"${t.DEBUG_LOGS}\"\n appearance=\"${this.filter === 'debug' ? 'filled' : 'plain'}\"\n variant=\"${this.filter === 'debug' ? 'brand' : 'neutral'}\"\n .action=${() => {\n this.filter = 'debug';\n this.saveSettings();\n }}>\n ${t.DEBUG}${debugCount > 0 ? ` (${debugCount})` : ''}\n </docks-command>\n\n <wa-divider orientation=\"vertical\"></wa-divider>\n\n <docks-command \n icon=\"arrow-down\" \n title=\"${this.autoScroll ? t.AUTO_SCROLL_ENABLED : t.AUTO_SCROLL_DISABLED}\"\n appearance=\"${this.autoScroll ? 'filled' : 'plain'}\"\n variant=\"${this.autoScroll ? 'brand' : 'neutral'}\"\n .action=${() => {\n this.autoScroll = !this.autoScroll;\n this.saveSettings();\n }}>\n ${this.autoScroll ? t.AUTO_SCROLL : t.MANUAL}\n </docks-command>\n\n <docks-command \n icon=\"trash\" \n title=\"${t.CLEAR_LOGS}\"\n .action=${() => this.clear()}>\n ${t.CLEAR}\n </docks-command>\n `;\n }\n\n protected renderContent() {\n const filteredMessages = this.getFilteredMessages();\n\n return html`\n <div class=\"log-terminal\">\n <div class=\"messages\" ${ref(this.containerRef)}>\n ${filteredMessages.length === 0 \n ? html`<div class=\"empty-state\">${t.NO_LOG_MESSAGES}</div>`\n : filteredMessages.map(msg => html`\n <div class=\"message\" data-level=\"${msg.level}\">\n <span class=\"timestamp\">${this.formatTimestamp(msg.timestamp)}</span>\n <wa-icon \n name=\"${this.getLevelIcon(msg.level)}\" \n label=\"${msg.level}\"\n style=\"color: ${this.getLevelColor(msg.level)}\">\n </wa-icon>\n <span class=\"source\">[${msg.source}]</span>\n <span class=\"text\">${msg.message}</span>\n </div>\n `)\n }\n </div>\n </div>\n `;\n }\n\n static styles = css`\n :host {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n }\n\n .log-terminal {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n }\n\n .messages {\n flex: 1;\n overflow-y: auto;\n padding: 0.5rem;\n font-family: var(--wa-font-mono);\n font-size: 0.875rem;\n line-height: 1.5;\n }\n\n .message {\n display: flex;\n gap: 0.5rem;\n padding: 0.25rem 0.5rem;\n align-items: baseline;\n border-radius: var(--wa-border-radius-small);\n }\n\n .message:hover {\n background: var(--wa-color-neutral-background-hover);\n }\n\n .timestamp {\n color: var(--wa-color-neutral-text-subtle);\n font-size: 0.75rem;\n white-space: nowrap;\n }\n\n .source {\n color: var(--wa-color-primary-text);\n font-weight: 500;\n white-space: nowrap;\n }\n\n .text {\n color: var(--wa-color-neutral-text);\n word-break: breaword;\n }\n\n .message[data-level=\"error\"] .text {\n color: var(--wa-color-danger-text);\n }\n\n .message[data-level=\"warning\"] .text {\n color: var(--wa-color-warning-text);\n }\n\n .message[data-level=\"debug\"] .text {\n color: var(--wa-color-neutral-text-subtle);\n }\n\n .empty-state {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n color: var(--wa-color-neutral-text-subtle);\n font-style: italic;\n }\n\n wa-icon {\n flex-shrink: 0;\n }\n `;\n\n private async loadSettings() {\n const persisted = await this.getDialogSetting();\n \n if (persisted) {\n if (typeof persisted.filter === 'string' && \n (persisted.filter === 'all' || ['info', 'warning', 'error', 'debug'].includes(persisted.filter))) {\n this.filter = persisted.filter;\n }\n if (typeof persisted.autoScroll === 'boolean') {\n this.autoScroll = persisted.autoScroll;\n }\n }\n }\n\n private async saveSettings() {\n await this.setDialogSetting({\n filter: this.filter,\n autoScroll: this.autoScroll\n });\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'docks-log-terminal': DocksLogTerminal;\n }\n \n interface Window {\n logToTerminal?: (source: string, message: string, level?: LogLevel) => void;\n }\n}\n\n","import { css, html, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { createRef, ref, Ref } from 'lit/directives/ref.js'\nimport { DocksWidget } from '../widgets/widget'\nimport { icon } from '../core/icon-utils'\nimport { contributionRegistry, TabContribution, ContributionChangeEvent, TOPIC_CONTRIBUTEIONS_CHANGED } from '../core/contributionregistry'\nimport { subscribe } from '../core/events'\nimport { Signal } from '@lit-labs/signals'\nimport { DocksTabs } from '../parts/tabs'\nimport { i18n } from '../core/i18n'\n\nconst t = await i18n(import.meta.glob('./fastviews*.json'));\n\n@customElement('docks-fastviews')\nexport class DocksFastViews extends DocksWidget {\n @property()\n target: string = ''\n\n @property()\n title: string = ''\n\n @property()\n icon?: string\n\n @property({ type: Boolean })\n disabled: boolean = false\n\n @property()\n appearance: 'default' | 'plain' | 'outline' = 'plain'\n\n @property()\n size: 'small' | 'medium' | 'large' = 'small'\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 @property()\n containerId?: string\n\n @state()\n private tabContributions: TabContribution[] = []\n\n @state()\n private drawerOpen: boolean = false\n\n @state()\n private drawerSize: string = '50vw'\n\n private drawerRef: Ref<HTMLElement> = createRef()\n private tabsRef: Ref<DocksTabs> = createRef()\n private resizeHandleRef: Ref<HTMLElement> = createRef()\n\n private resizing: {\n startX: number\n startSize: number\n handleMouseMove: (e: MouseEvent) => void\n handleMouseUp: () => void\n rafId: number | null\n } | null = null\n\n private getDrawerTabsId(): string {\n return `fastviews-drawer-tabs-${this.target}`\n }\n\n private handleTabClick(contribution: TabContribution) {\n if (this.disabled) return\n\n if (this.containerId) {\n const tabContainer = document.querySelector(`docks-tabs#${this.containerId}`) as DocksTabs | null\n if (!tabContainer) {\n console.error(`fastviews: Tab container with id \"${this.containerId}\" not found`)\n return\n }\n tabContainer.open(contribution)\n } else {\n this.drawerOpen = true\n \n this.updateComplete.then(() => {\n const tabsContainer = this.tabsRef.value\n if (tabsContainer) {\n tabsContainer.open(contribution)\n }\n })\n }\n }\n\n private handleDrawerHide() {\n this.drawerOpen = false\n }\n\n private startResize(e: MouseEvent) {\n e.preventDefault()\n e.stopPropagation()\n \n const drawer = this.drawerRef.value as any\n if (!drawer) return\n\n const getDrawerSize = (): number => {\n const drawerPanel = drawer.shadowRoot?.querySelector('[part=\"panel\"]') as HTMLElement\n if (drawerPanel && drawerPanel.offsetWidth > 0) {\n return drawerPanel.offsetWidth\n }\n const computedStyle = window.getComputedStyle(drawer)\n const sizeValue = computedStyle.getPropertyValue('--size') || this.drawerSize\n const match = sizeValue.match(/^(\\d+(?:\\.\\d+)?)(px|vw|vh|%)$/)\n if (match) {\n const value = parseFloat(match[1])\n const unit = match[2]\n if (unit === 'px') return value\n if (unit === 'vw') return (value / 100) * window.innerWidth\n if (unit === 'vh') return (value / 100) * window.innerHeight\n if (unit === '%') return (value / 100) * window.innerWidth\n }\n return 0\n }\n \n let currentSize = getDrawerSize()\n if (currentSize === 0) {\n currentSize = window.innerWidth * 0.5\n }\n \n const handleMouseMove = (moveEvent: MouseEvent) => {\n if (!this.resizing) return\n \n moveEvent.preventDefault()\n moveEvent.stopPropagation()\n\n if (this.resizing.rafId !== null) {\n cancelAnimationFrame(this.resizing.rafId)\n }\n\n this.resizing.rafId = requestAnimationFrame(() => {\n if (!this.resizing) return\n \n const delta = this.resizing.startX - moveEvent.clientX\n const newSize = Math.round(this.resizing.startSize + delta)\n const minSize = 200\n const maxSize = Math.round(window.innerWidth * 0.9)\n\n if (newSize >= minSize && newSize <= maxSize) {\n this.drawerSize = `${newSize}px`\n \n const drawer = this.drawerRef.value as any\n if (drawer) {\n drawer.style.setProperty('--size', this.drawerSize)\n drawer.style.setProperty('transition', 'none')\n }\n }\n this.resizing.rafId = null\n })\n }\n\n const handleMouseUp = () => {\n if (this.resizing) {\n if (this.resizing.rafId !== null) {\n cancelAnimationFrame(this.resizing.rafId)\n this.resizing.rafId = null\n }\n \n document.removeEventListener('mousemove', this.resizing.handleMouseMove)\n document.removeEventListener('mouseup', this.resizing.handleMouseUp)\n document.body.style.cursor = ''\n document.body.style.userSelect = ''\n \n const drawer = this.drawerRef.value as any\n if (drawer) {\n drawer.style.removeProperty('transition')\n }\n \n this.resizing = null\n }\n }\n\n this.resizing = {\n startX: e.clientX,\n startSize: currentSize,\n handleMouseMove,\n handleMouseUp,\n rafId: null\n }\n\n document.addEventListener('mousemove', handleMouseMove, { passive: false })\n document.addEventListener('mouseup', handleMouseUp, { passive: false })\n document.body.style.cursor = 'col-resize'\n document.body.style.userSelect = 'none'\n }\n\n protected doBeforeUI() {\n if (this.target) {\n this.loadTabContributions()\n \n subscribe(TOPIC_CONTRIBUTEIONS_CHANGED, (event: ContributionChangeEvent) => {\n if (this.target && event.target === this.target) {\n this.loadTabContributions()\n }\n })\n }\n }\n\n private loadTabContributions() {\n if (!this.target) return\n \n const allContributions = contributionRegistry.getContributions(this.target)\n this.tabContributions = allContributions.filter((c): c is TabContribution => 'name' in c)\n this.requestUpdate()\n }\n\n private renderTabContribution(contribution: TabContribution) {\n return html`\n <wa-dropdown-item \n @click=${() => this.handleTabClick(contribution)}>\n ${icon(contribution.icon, { label: contribution.label, slot: 'icon' })}\n ${contribution.label}\n </wa-dropdown-item>\n `\n }\n\n render() {\n if (!this.target) {\n return nothing\n }\n\n if (this.tabContributions.length === 0) {\n return nothing\n }\n\n return html`\n <wa-dropdown placement=${this.placement}>\n <wa-button \n slot=\"trigger\"\n appearance=${this.appearance}\n size=${this.size}\n ?disabled=${this.disabled}\n with-caret\n title=${this.title}>\n ${icon(this.icon, { label: this.title, slot: 'start' })}\n <slot></slot>\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.tabContributions.map(c => this.renderTabContribution(c))}\n </wa-dropdown>\n\n ${!this.containerId ? html`\n <wa-drawer \n ${ref(this.drawerRef)}\n label=\"${this.title || t.FAST_VIEWS}\"\n placement=\"end\"\n ?open=${this.drawerOpen}\n @wa-hide=${this.handleDrawerHide}\n style=\"--size: ${this.drawerSize};\">\n <div \n ${ref(this.resizeHandleRef)}\n class=\"resize-handle\"\n @mousedown=${this.startResize}>\n </div>\n <docks-tabs \n ${ref(this.tabsRef)}\n id=\"${this.getDrawerTabsId()}\"\n style=\"width: 100%; height: 100%; display: flex; flex-direction: column;\">\n </docks-tabs>\n </wa-drawer>\n ` : nothing}\n `\n }\n\n static styles = css`\n :host {\n display: inline-block;\n }\n\n wa-drawer {\n position: relative;\n }\n\n wa-drawer::part(panel) {\n position: relative;\n }\n\n .resize-handle {\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 4px;\n cursor: col-resize;\n z-index: 1000;\n background: transparent;\n transition: background-color 0.2s;\n user-select: none;\n touch-action: none;\n }\n\n .resize-handle:hover {\n background: var(--wa-color-brand-fill-loud);\n }\n\n .resize-handle:active {\n background: var(--wa-color-brand-fill-loud);\n }\n `\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'docks-fastviews': DocksFastViews\n }\n}\n\n","import { html, render, css } from \"lit\";\nimport { customElement } from \"lit/decorators.js\";\nimport { DocksElement } from \"../parts/element\";\nimport { currentLanguageSignal, supportedLocalesSignal, SETTINGS_KEY_LANGUAGE } from \"../core/i18n\";\nimport { appSettings } from \"../core/settingsservice\";\n\nfunction getDialogContainer(): HTMLElement {\n let container = document.getElementById('global-dialog-container');\n if (!container) {\n container = document.createElement('div');\n container.id = 'global-dialog-container';\n document.body.appendChild(container);\n }\n return container;\n}\n\nconst getLanguageName = (code: string): string => {\n try {\n return new Intl.DisplayNames([code], { type: 'language' }).of(code) || code.toUpperCase();\n } catch {\n return code.toUpperCase();\n }\n};\n\nconst getAvailableLanguages = (): string[] => [...supportedLocalesSignal.get()].sort();\n\nexport const showLanguageSelectorDialog = async (): Promise<void> => {\n const availableLanguages = getAvailableLanguages();\n const currentLanguage = currentLanguageSignal.get();\n \n return new Promise((resolve) => {\n const container = getDialogContainer();\n\n let isResolved = false;\n\n const handleClose = () => {\n const dialog = container.querySelector('wa-dialog') as any;\n if (dialog && !isResolved) {\n dialog.open = false;\n }\n };\n\n const handleAfterHide = () => {\n if (isResolved) return;\n isResolved = true;\n render(html``, container);\n resolve();\n };\n\n const selectLanguage = async (language: string) => {\n await appSettings.set(SETTINGS_KEY_LANGUAGE, language);\n handleClose();\n };\n\n const template = html`\n <wa-dialog \n label=\"Select Language\" \n open \n light-dismiss\n @wa-request-close=${handleClose}\n @wa-after-hide=${handleAfterHide}>\n <style>\n .language-list {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n padding: 1rem;\n min-width: 300px;\n max-height: 400px;\n overflow-y: auto;\n }\n \n .language-item {\n display: flex;\n align-items: center;\n padding: 0.75rem;\n border-radius: var(--wa-border-radius-small);\n cursor: pointer;\n transition: background-color 0.2s;\n }\n \n .language-item:hover {\n background-color: var(--wa-color-neutral-fill-quiet);\n }\n \n .language-item.active {\n background-color: var(--wa-color-brand-fill-quiet);\n font-weight: 600;\n }\n \n .language-code {\n font-family: monospace;\n margin-right: 0.75rem;\n min-width: 3rem;\n color: var(--wa-color-neutral-600);\n }\n \n .language-name {\n flex: 1;\n }\n </style>\n \n <div class=\"language-list\">\n ${availableLanguages.map(lang => html`\n <div \n class=\"language-item ${lang === currentLanguage ? 'active' : ''}\"\n @click=${() => selectLanguage(lang)}>\n <span class=\"language-code\">${lang.toUpperCase()}</span>\n <span class=\"language-name\">${getLanguageName(lang)}</span>\n </div>\n `)}\n </div>\n </wa-dialog>\n `;\n\n render(template, container);\n });\n};\n\n@customElement('docks-language-selector')\nexport class DocksLanguageSelector extends DocksElement {\n static styles = css`\n :host {\n display: inline-block;\n }\n `;\n\n protected render() {\n const currentLanguage = currentLanguageSignal.get();\n const languageName = getLanguageName(currentLanguage);\n const buttonLabel = `${currentLanguage.toUpperCase()} ${languageName}`;\n \n return html`\n <wa-button \n appearance=\"plain\" \n size=\"small\"\n title=\"Current language: ${languageName}\"\n @click=${() => showLanguageSelectorDialog()}>\n ${buttonLabel}\n </wa-button>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'docks-language-selector': DocksLanguageSelector;\n }\n}\n\n","import { html, css } from \"lit\";\nimport { customElement, state } from \"lit/decorators.js\";\nimport { DocksElement } from \"../parts/element\";\nimport { appLoaderService } from \"../core/apploader\";\nimport { icon } from '../core/icon-utils';\n\n@customElement('docks-layout-switcher')\nexport class DocksLayoutSwitcher extends DocksElement {\n @state()\n private currentLayoutId = 'standard';\n\n protected doBeforeUI() {\n this.currentLayoutId = appLoaderService.getCurrentLayoutId();\n const updateLayout = () => {\n this.currentLayoutId = appLoaderService.getCurrentLayoutId();\n this.requestUpdate();\n };\n window.addEventListener('app-loaded', updateLayout);\n window.addEventListener('layout-changed', updateLayout);\n return () => {\n window.removeEventListener('app-loaded', updateLayout);\n window.removeEventListener('layout-changed', updateLayout);\n };\n }\n\n private async handleSelect(e: CustomEvent) {\n const layoutId = e.detail?.item?.value;\n if (!layoutId || layoutId === this.currentLayoutId) return;\n try {\n await appLoaderService.setPreferredLayoutId(layoutId);\n } catch (err) {\n console.error('Failed to switch layout:', err);\n }\n }\n\n protected render() {\n const layouts = appLoaderService.getRegisteredLayouts();\n if (layouts.length <= 1) {\n return html``;\n }\n\n const currentLayout = layouts.find((l) => l.id === this.currentLayoutId);\n const layoutName = currentLayout?.name ?? this.currentLayoutId;\n\n return html`\n <wa-dropdown\n placement=\"bottom-end\"\n distance=\"4\"\n size=\"small\"\n @wa-select=${this.handleSelect}>\n <wa-button\n slot=\"trigger\"\n appearance=\"plain\"\n size=\"small\"\n with-caret\n title=\"Switch layout (current: ${layoutName})\">\n <wa-icon name=\"table-cells\" label=\"Layout\"></wa-icon>\n </wa-button>\n ${layouts.map(\n (layout) => html`\n <wa-dropdown-item\n value=\"${layout.id}\"\n type=\"checkbox\"\n ?checked=${layout.id === this.currentLayoutId}>\n ${icon(layout.icon, { label: layout.name, slot: 'icon' })}\n ${layout.name}\n </wa-dropdown-item>\n `\n )}\n </wa-dropdown>\n `;\n }\n\n static styles = css`\n :host {\n display: inline-block;\n }\n `;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'docks-layout-switcher': DocksLayoutSwitcher;\n }\n}\n","export const VIEW_FILEBROWSER = \"view.filebrowser\";\nexport const VIEW_LOG_TERMINAL = \"view.logTerminal\";\n\nexport const TOOLBAR_INFO = \"toolbar.info\";\nexport const TOOLBAR_FAST_VIEWS = \"toolbar.fastViews\";\nexport const TOOLBAR_LANGUAGE_SELECTOR = \"toolbar.languageSelector\";\nexport const TOOLBAR_APP_SWITCHER = \"toolbar.appSwitcher\";\n\nexport const TOOLBAR_FILEBROWSER_RENAME = \"toolbar.filebrowser.rename\";\nexport const TOOLBAR_FILEBROWSER_DELETE = \"toolbar.filebrowser.delete\";\n\nexport const CTXMENU_FILEBROWSER_RENAME = \"contextmenu.filebrowser.rename\";\nexport const CTXMENU_FILEBROWSER_DELETE = \"contextmenu.filebrowser.delete\";\n\n","import { html } from \"lit\";\nimport { contributionRegistry, type HTMLContribution } from \"../core/contributionregistry\";\nimport {\n PANEL_BOTTOM,\n SIDEBAR_MAIN,\n TOOLBAR_BOTTOM_END,\n TOOLBAR_MAIN_RIGHT\n} from \"../core/constants\";\nimport {\n VIEW_FILEBROWSER,\n VIEW_LOG_TERMINAL,\n TOOLBAR_APP_SWITCHER,\n TOOLBAR_FAST_VIEWS,\n TOOLBAR_INFO,\n TOOLBAR_LANGUAGE_SELECTOR\n} from \"../core/ui-ids\";\n\ncontributionRegistry.registerContribution(SIDEBAR_MAIN, {\n name: VIEW_FILEBROWSER,\n label: \"Workspace\",\n icon: \"folder-open\",\n component: (id: string) => html`<docks-filebrowser id=\"${id}\"></docks-filebrowser>`\n});\n\ncontributionRegistry.registerContribution(PANEL_BOTTOM, {\n name: VIEW_LOG_TERMINAL,\n label: \"Log Messages\",\n icon: \"list\",\n component: (id: string) => html`<docks-log-terminal id=\"${id}\"></docks-log-terminal>`\n});\n\ncontributionRegistry.registerContribution(TOOLBAR_BOTTOM_END, {\n name: TOOLBAR_INFO,\n label: \"Info\",\n icon: \"circle-info\",\n command: \"show_version_info\",\n showLabel: true,\n});\n\ncontributionRegistry.registerContribution(TOOLBAR_BOTTOM_END, {\n name: TOOLBAR_FAST_VIEWS,\n label: `Fast Views`,\n component: `<docks-fastviews target=\"system.fastviews-bottomend\" icon=\"bolt\" title=\"Fast Views\"></docks-fastviews>`\n});\n\ncontributionRegistry.registerContribution(TOOLBAR_BOTTOM_END, {\n name: TOOLBAR_LANGUAGE_SELECTOR,\n label: \"Language\",\n component: () => html`<docks-language-selector></docks-language-selector>`\n});\n\ncontributionRegistry.registerContribution(TOOLBAR_MAIN_RIGHT, {\n name: TOOLBAR_APP_SWITCHER,\n label: \"App Switcher\",\n component: () => html`<docks-layout-switcher></docks-layout-switcher>`\n} as HTMLContribution);\n\n","import {html, nothing} from \"lit\";\nimport {customElement, property} from \"lit/decorators.js\";\n\nimport {\n EDITOR_AREA_MAIN,\n SIDEBAR_MAIN,\n SIDEBAR_MAIN_BOTTOM,\n SIDEBAR_AUXILIARY,\n PANEL_BOTTOM,\n TOOLBAR_MAIN,\n TOOLBAR_MAIN_CENTER,\n TOOLBAR_MAIN_RIGHT,\n TOOLBAR_BOTTOM,\n TOOLBAR_BOTTOM_CENTER,\n TOOLBAR_BOTTOM_END\n} from \"../core/constants\";\nimport {DocksContainer} from \"../parts/container\";\n\n@customElement('docks-standard-layout')\nexport class DocksStandardLayout extends DocksContainer {\n @property({type: Boolean, attribute: 'show-bottom-sidebar'})\n showBottomSidebar: boolean = false;\n\n @property({type: Boolean, attribute: 'show-bottom-panel'})\n showBottomPanel: boolean = false;\n\n @property({type: Boolean, attribute: 'show-left-sidebar'})\n showLeftSidebar: boolean = true;\n\n @property({type: Boolean, attribute: 'show-aux-sidebar'})\n showAuxSidebar: boolean = true;\n\n createRenderRoot() {\n return this;\n }\n\n private getGridSizes(): string {\n if (this.showLeftSidebar && this.showAuxSidebar) {\n return \"20%, 60%, 20%\";\n }\n if (this.showLeftSidebar) {\n return \"20%, 80%\";\n }\n if (this.showAuxSidebar) {\n return \"80%, 20%\";\n }\n return \"100%\";\n }\n\n render() {\n return html`\n <style>\n *, *::before, *::after {\n box-sizing: border-box;\n }\n \n html {\n height: 100%;\n margin: 0;\n padding: 0;\n overflow: hidden;\n }\n \n body {\n height: 100%;\n width: 100%;\n margin: 0;\n padding: 0;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n \n docks-standard-layout {\n display: flex;\n flex-direction: column;\n height: 100vh;\n width: 100%;\n }\n \n docks-standard-layout .toolbar-top {\n width: 100%;\n display: grid;\n grid-template-columns: 1fr 2fr 1fr;\n align-items: center;\n border-bottom: solid var(--wa-border-width-s) var(--wa-color-neutral-border-loud);\n flex-shrink: 0;\n position: relative;\n z-index: 100;\n }\n\n docks-standard-layout .toolbar-top > :nth-child(1) {\n justify-self: start;\n }\n\n docks-standard-layout .toolbar-top > :nth-child(2) {\n justify-self: center;\n }\n \n docks-standard-layout .toolbar-bottom {\n width: 100%;\n border-top: solid var(--wa-border-width-s) var(--wa-color-neutral-border-loud);\n display: grid;\n grid-template-columns: 1fr 2fr auto;\n align-items: center;\n flex-shrink: 0;\n min-height: 32px;\n padding: 0 var(--wa-space-s);\n box-sizing: border-box;\n }\n \n docks-standard-layout .main-layout {\n flex: 1;\n min-height: 0;\n }\n \n docks-standard-layout .toolbar-end {\n justify-self: end;\n }\n </style>\n \n <div class=\"toolbar-top\">\n <docks-toolbar id=${TOOLBAR_MAIN}></docks-toolbar>\n <docks-toolbar id=${TOOLBAR_MAIN_CENTER}></docks-toolbar>\n <docks-toolbar class=\"toolbar-end\" id=${TOOLBAR_MAIN_RIGHT}></docks-toolbar>\n </div>\n \n <docks-resizable-grid \n class=\"main-layout\"\n id=\"main-layout\" \n orientation=\"horizontal\" \n sizes=${this.getGridSizes()}>\n \n ${this.showLeftSidebar\n ? html`\n ${this.showBottomSidebar\n ? html`\n <docks-resizable-grid \n id=\"left-sidebar-split\" \n orientation=\"vertical\" \n sizes=\"50%, 50%\">\n <docks-tabs id=\"${SIDEBAR_MAIN}\"></docks-tabs>\n <docks-tabs id=\"${SIDEBAR_MAIN_BOTTOM}\"></docks-tabs>\n </docks-resizable-grid>\n `\n : html`<docks-tabs id=\"${SIDEBAR_MAIN}\"></docks-tabs>`\n }\n `\n : nothing\n }\n \n ${this.showBottomPanel\n ? html`\n <docks-resizable-grid \n id=\"editor-area-split\" \n orientation=\"vertical\" \n sizes=\"70%, 30%\">\n <docks-tabs id=\"${EDITOR_AREA_MAIN}\"></docks-tabs>\n <docks-tabs id=\"${PANEL_BOTTOM}\"></docks-tabs>\n </docks-resizable-grid>\n `\n : html`<docks-tabs id=\"${EDITOR_AREA_MAIN}\"></docks-tabs>`\n }\n \n ${this.showAuxSidebar\n ? html`<docks-tabs id=\"${SIDEBAR_AUXILIARY}\"></docks-tabs>`\n : nothing\n }\n </docks-resizable-grid>\n \n <div class=\"toolbar-bottom\">\n <docks-toolbar id=${TOOLBAR_BOTTOM}></docks-toolbar>\n <docks-toolbar id=${TOOLBAR_BOTTOM_CENTER}></docks-toolbar>\n <docks-toolbar class=\"toolbar-end\" id=${TOOLBAR_BOTTOM_END}></docks-toolbar>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'docks-standard-layout': DocksStandardLayout;\n }\n}\n","import \"../layouts/standard-layout\";\nimport { contributionRegistry } from \"../core/contributionregistry\";\nimport { SYSTEM_LAYOUTS } from \"../core/constants\";\n\nconst standardLayouts: Array<{\n id: string;\n name: string;\n label: string;\n icon?: string;\n component: string | { tag: string; attributes?: Record<string, string> };\n}> = [\n {\n id: \"standard\",\n name: \"Standard\",\n label: \"Standard\",\n icon: \"docks layout-standard\",\n component: \"docks-standard-layout\",\n },\n {\n id: \"standard-bottom-panel\",\n name: \"Standard (bottom panel)\",\n label: \"Standard (bottom panel)\",\n icon: \"docks layout-standard-bottom-panel\",\n component: { tag: \"docks-standard-layout\", attributes: { \"show-bottom-panel\": \"true\" } },\n },\n {\n id: \"standard-bottom-sidebar\",\n name: \"Standard (bottom sidebar)\",\n label: \"Standard (bottom sidebar)\",\n icon: \"docks layout-standard-bottom-sidebar\",\n component: { tag: \"docks-standard-layout\", attributes: { \"show-bottom-sidebar\": \"true\" } },\n },\n {\n id: \"standard-full\",\n name: \"Standard (panel + sidebar)\",\n label: \"Standard (panel + sidebar)\",\n icon: \"docks layout-standard-full\",\n component: {\n tag: \"docks-standard-layout\",\n attributes: { \"show-bottom-panel\": \"true\", \"show-bottom-sidebar\": \"true\" },\n },\n },\n];\n\nfor (const layout of standardLayouts) {\n contributionRegistry.registerContribution(SYSTEM_LAYOUTS, layout);\n}\n","import { activeSelectionSignal } from \"../core/appstate\";\nimport { registerAll, type ExecutionContext } from \"../core/commandregistry\";\nimport { EditorContentProvider, editorRegistry } from \"../core/editorregistry\";\nimport { Directory, File, deleteIndexedDbWorkspaceData, workspaceService } from \"../core/filesys\";\nimport { toastError, toastInfo } from \"../core/toast\";\nimport { confirmDialog } from \"../dialogs\";\n\nasync function getWorkspaceAndPath(params: any, requirePath: boolean = true): Promise<{workspace: Directory, path: string} | null> {\n const workspace = await workspaceService.getWorkspace()\n if (!workspace) {\n return null\n }\n\n const path = params?.path\n if (requirePath && !path) {\n return null\n }\n\n return { workspace, path: path || '' }\n}\n\n/**\n * Type guard to check if an editor implements EditorContentProvider\n */\nfunction isEditorContentProvider(editor: any): editor is EditorContentProvider {\n return editor &&\n typeof editor.getContent === 'function' &&\n typeof editor.getSelection === 'function' &&\n typeof editor.getSnippet === 'function' &&\n typeof editor.getLanguage === 'function' &&\n typeof editor.getFilePath === 'function';\n}\n\n/**\n * Helper to get a resource from path or active selection\n */\nasync function getResourceFromContext(context: ExecutionContext, params?: any): Promise<any> {\n let resource = undefined\n const path = params?.path || context.params?.[\"path\"]\n \n if (path) {\n const workspaceDir = await workspaceService.getWorkspace()\n if (workspaceDir) {\n resource = await workspaceDir.getResource(path)\n }\n }\n\n if (!resource) {\n resource = activeSelectionSignal.get()\n }\n\n return resource\n}\n\n/**\n * Helper to read text file contents with error handling\n */\nasync function readTextFile(file: File): Promise<string | null> {\n try {\n const contents = await file.getContents()\n if (typeof contents !== 'string') {\n toastError(\"File is not a text file\")\n return null\n }\n return contents\n } catch (err: any) {\n toastError(`Failed to read file: ${err.message}`)\n return null\n }\n}\n\n/**\n * Helper to create null editor response\n */\nfunction createNullEditorResponse(includeCursorLine: boolean = false) {\n const base = {\n filePath: null,\n language: null\n }\n if (includeCursorLine) {\n return { ...base, snippet: null, cursorLine: null }\n }\n return base\n}\n\nasync function getWorkspaceAndFile(params: any, requirePath: boolean = true): Promise<{workspace: Directory, path: string, file: File} | null> {\n const result = await getWorkspaceAndPath(params, requirePath)\n if (!result) {\n return null\n }\n\n const { workspace, path } = result\n\n if (!path) {\n return null\n }\n\n try {\n const resource = await workspace.getResource(path)\n if (!resource || !(resource instanceof File)) {\n return null\n }\n\n return { workspace, path, file: resource }\n } catch (err: any) {\n return null\n }\n}\n\nregisterAll({\n command: {\n \"id\": \"disconnect_folder\",\n \"name\": \"Disconnect folder\",\n \"description\": \"Disconnects a folder from the workspace\"\n },\n handler: {\n execute: async () => {\n const selection = activeSelectionSignal.get()\n if (!(selection instanceof Directory && selection.getParent() === undefined)) {\n toastError(\"Select a folder root to disconnect.\")\n return\n }\n try {\n const folderInfo = await workspaceService.getFolderInfoForDirectory(selection);\n if (folderInfo?.type === 'indexeddb') {\n const deleteData = await confirmDialog(\n `Also delete \"${folderInfo.name}\" from browser storage?\\n\\nIf not deleted, the folder data and blobs remain in IndexedDB.`\n );\n if (!deleteData) {\n return;\n }\n await deleteIndexedDbWorkspaceData(selection);\n toastInfo(`Deleted IndexedDB data for ${folderInfo.name}.`);\n }\n await workspaceService.disconnectFolder(selection)\n } catch (err: any) {\n toastError(err.message)\n }\n }\n },\n contribution: {\n target: \"contextmenu:view.filebrowser\",\n label: \"Disconnect folder\",\n icon: \"folder-minus\",\n disabled: () => {\n const selection = activeSelectionSignal.get();\n return !(selection instanceof Directory && selection.getParent() === undefined);\n }\n }\n})\n\n// Register local filesystem workspace contribution\nregisterAll({\n command: {\n \"id\": \"load_workspace\",\n \"name\": \"Local Folder\",\n \"description\": \"Connect to a local folder using File System Access API\",\n \"parameters\": []\n },\n handler: {\n execute: async _context => {\n // @ts-ignore\n await window.showDirectoryPicker({\n mode: \"readwrite\"\n }).then((dirHandle: FileSystemDirectoryHandle) => {\n return workspaceService.connectWorkspace(dirHandle);\n }).catch((err: Error) => {\n toastError(err.message)\n });\n }\n },\n contribution: {\n target: \"filebrowser.connections\",\n label: \"Local Folder\",\n icon: \"folder-open\"\n }\n})\n\nregisterAll({\n command: {\n \"id\": \"connect_opfs\",\n \"name\": \"OPFS\",\n \"description\": \"Connect to Origin Private File System (browser storage)\",\n \"parameters\": []\n },\n handler: {\n execute: async () => {\n try {\n await workspaceService.connectFolder({ opfs: true });\n } catch (err: any) {\n toastError(err.message);\n }\n }\n },\n contribution: {\n target: \"filebrowser.connections\",\n label: \"OPFS (Browser Storage)\",\n icon: \"database\"\n }\n})\n\nregisterAll({\n command: {\n \"id\": \"connect_indexeddb\",\n \"name\": \"IndexedDB\",\n \"description\": \"Connect to IndexedDB-backed workspace (browser storage)\",\n \"parameters\": [\n {\n \"name\": \"name\",\n \"description\": \"Optional display name for this IndexedDB workspace root\",\n \"required\": false\n }\n ]\n },\n handler: {\n execute: async (context: ExecutionContext) => {\n const nameParam = context.params?.[\"name\"];\n try {\n await workspaceService.connectFolder({ indexeddb: true, name: nameParam });\n } catch (err: any) {\n toastError(err.message);\n }\n }\n },\n contribution: {\n target: \"filebrowser.connections\",\n label: \"IndexedDB (Browser Storage)\",\n icon: \"database\"\n }\n})\n\nregisterAll({\n command: {\n \"id\": \"refresh_resource\",\n \"name\": \"Refresh resource\",\n \"description\": \"Refreshes the connected folder of the selected resource, or the whole workspace if nothing is selected\",\n \"parameters\": []\n },\n handler: {\n execute: async () => {\n const selection = activeSelectionSignal.get()\n if (selection) {\n selection.getWorkspace().touch()\n return\n }\n const workspace = await workspaceService.getWorkspace()\n if (!workspace) {\n toastError(\"No workspace selected.\")\n return\n }\n workspace.touch()\n }\n }\n})\n\nregisterAll({\n command: {\n \"id\": \"open_editor\",\n \"name\": \"Open editor\",\n \"description\": \"Opens a file in an editor\",\n \"parameters\": [\n {\n \"name\": \"path\",\n \"description\": \"The path of the file to open within the workspace; if omitted, the active selection is opened\",\n \"required\": false\n },\n {\n \"name\": \"editorId\",\n \"description\": \"Open with this editor id; if omitted, use default editor\",\n \"required\": false\n }\n ]\n },\n handler: {\n execute: async context => {\n const path = context.params?.[\"path\"]\n const editorId = context.params?.[\"editorId\"]\n let file: File | null = null\n if (path) {\n const result = await getWorkspaceAndFile({ path })\n file = result?.file ?? null\n } else {\n const selection = activeSelectionSignal.get()\n file = selection instanceof File ? selection : null\n }\n if (!file) return\n await editorRegistry.loadEditor(file, editorId)\n }\n }\n})\n\nregisterAll({\n command: {\n \"id\": \"get_active_editor_content\",\n \"name\": \"Get active editor content\",\n \"description\": \"Gets the complete contents of the currently active editor. Returns null if no editor is active or if the editor is not a code editor.\",\n \"parameters\": [],\n \"output\": [\n {\n \"name\": \"content\",\n \"description\": \"the complete contents of the active editor, or null if no editor is active\"\n },\n {\n \"name\": \"filePath\",\n \"description\": \"the workspace path of the file in the active editor, or null if no editor is active\"\n },\n {\n \"name\": \"language\",\n \"description\": \"the programming language of the active editor, or null if no editor is active\"\n }\n ]\n },\n handler: {\n execute: async (context: ExecutionContext) => {\n const activeEditor = context.activeEditor as any\n if (!isEditorContentProvider(activeEditor)) {\n return { ...createNullEditorResponse(), content: null }\n }\n\n try {\n return {\n content: activeEditor.getContent(),\n filePath: activeEditor.getFilePath(),\n language: activeEditor.getLanguage()\n }\n } catch (err: any) {\n return { ...createNullEditorResponse(), content: null }\n }\n }\n }\n})\n\nregisterAll({\n command: {\n \"id\": \"get_active_editor_selection\",\n \"name\": \"Get active editor selection\",\n \"description\": \"Gets the currently selected text in the active editor. Returns null if no editor is active, no selection exists, or if the editor is not a code editor.\",\n \"parameters\": [],\n \"output\": [\n {\n \"name\": \"selection\",\n \"description\": \"the selected text in the active editor, or null if no selection exists or no editor is active\"\n },\n {\n \"name\": \"filePath\",\n \"description\": \"the workspace path of the file in the active editor, or null if no editor is active\"\n },\n {\n \"name\": \"language\",\n \"description\": \"the programming language of the active editor, or null if no editor is active\"\n }\n ]\n },\n handler: {\n execute: async (context: ExecutionContext) => {\n const activeEditor = context.activeEditor as any\n if (!isEditorContentProvider(activeEditor)) {\n return { ...createNullEditorResponse(), selection: null }\n }\n\n try {\n return {\n selection: activeEditor.getSelection(),\n filePath: activeEditor.getFilePath(),\n language: activeEditor.getLanguage()\n }\n } catch (err: any) {\n return { ...createNullEditorResponse(), selection: null }\n }\n }\n }\n})\n\nregisterAll({\n command: {\n \"id\": \"get_active_editor_snippet\",\n \"name\": \"Get active editor snippet around cursor\",\n \"description\": \"Gets a code snippet from the active editor with n lines before and n lines after the cursor position. Useful for getting context around the cursor without loading the entire file.\",\n \"parameters\": [\n {\n \"name\": \"lines\",\n \"description\": \"number of lines to include before and after the cursor position (default: 5)\",\n \"type\": \"number\",\n \"required\": false\n }\n ],\n \"output\": [\n {\n \"name\": \"snippet\",\n \"description\": \"the code snippet with n lines before and after the cursor, or null if no editor is active\"\n },\n {\n \"name\": \"filePath\",\n \"description\": \"the workspace path of the file in the active editor, or null if no editor is active\"\n },\n {\n \"name\": \"language\",\n \"description\": \"the programming language of the active editor, or null if no editor is active\"\n },\n {\n \"name\": \"cursorLine\",\n \"description\": \"the line number where the cursor is positioned (1-based), or null if no editor is active\"\n }\n ]\n },\n handler: {\n execute: async (context: ExecutionContext) => {\n const activeEditor = context.activeEditor as any\n if (!isEditorContentProvider(activeEditor)) {\n return createNullEditorResponse(true)\n }\n\n try {\n const numLines = context.params?.lines ? parseInt(context.params.lines, 10) : 5\n if (isNaN(numLines) || numLines < 0) {\n return createNullEditorResponse(true)\n }\n\n const snippetResult = activeEditor.getSnippet(numLines)\n if (!snippetResult) {\n return createNullEditorResponse(true)\n }\n\n return {\n snippet: snippetResult.snippet,\n filePath: activeEditor.getFilePath(),\n language: activeEditor.getLanguage(),\n cursorLine: snippetResult.cursorLine\n }\n } catch (err: any) {\n return createNullEditorResponse(true)\n }\n }\n }\n})\n\n","import { registerAll } from \"../core/commandregistry\";\nimport { html, render, type TemplateResult } from \"lit\";\nimport { unsafeHTML } from \"lit/directives/unsafe-html.js\";\nimport { marked } from \"marked\";\nimport { toastError } from \"../core/toast\";\nimport { appLoaderService, type ReleaseEntry } from \"../core/apploader\";\n\n/** Compare semver strings whether GitHub uses a leading \"v\" (e.g. v0.7.83) or package.json does not. */\nfunction semverEqual(a: string, b: string): boolean {\n return a.replace(/^v/i, '') === b.replace(/^v/i, '');\n}\n\nregisterAll({\n command: {\n \"id\": \"show_version_info\",\n \"name\": \"Show Version Info\",\n \"description\": \"Shows application version information\",\n \"parameters\": []\n },\n handler: {\n execute: async _context => {\n const app = appLoaderService.getCurrentApp();\n if (!app) {\n toastError(\"No app loaded\");\n return;\n }\n\n const deps = app.dependencies ?? {};\n const hasPackages = Object.keys(deps).length > 0;\n const packagesTree: TemplateResult = hasPackages\n ? html`\n <wa-tree style=\"--indent-guide-width: 1px;\">\n <wa-tree-item expanded>\n <span>${app.name ?? ''}</span>\n ${Object.entries(deps).map(([name, version]) => html`\n <wa-tree-item>\n <span>${name} <small>${version}</small></span>\n </wa-tree-item>\n `)}\n </wa-tree-item>\n </wa-tree>\n `\n : html``;\n\n let dialogContainer: HTMLElement | null = null;\n const getDialogContainer = (): HTMLElement => {\n if (!dialogContainer) {\n dialogContainer = document.getElementById('global-dialog-container') || document.createElement('div');\n if (!dialogContainer.id) {\n dialogContainer.id = 'global-dialog-container';\n document.body.appendChild(dialogContainer);\n }\n }\n return dialogContainer;\n };\n\n const cleanup = () => {\n if (dialogContainer) {\n render(html``, dialogContainer);\n }\n };\n\n const renderReleaseContent = (releaseContent: string) => {\n const htmlContent = marked.parse(releaseContent, { async: false }) as string;\n return html`${unsafeHTML(htmlContent)}`;\n };\n\n let releases: ReleaseEntry[] = [];\n if (app.releaseHistory) {\n if (typeof app.releaseHistory === 'function') {\n try {\n releases = await app.releaseHistory();\n } catch (error) {\n console.error('Failed to load release history from app:', error);\n releases = [];\n }\n } else {\n releases = app.releaseHistory;\n }\n }\n\n const appVersion = app.version ?? '0.0.0';\n const isDev = appVersion === '0.0.0';\n const currentIndex = releases.length > 0 ? releases.findIndex(r => semverEqual(r.tag_name, appVersion)) : -1;\n const startIndex = currentIndex >= 0 ? currentIndex : 0;\n let currentReleaseIndex = startIndex;\n\n const buildReleaseContent = (index: number) => {\n if (releases.length === 0) {\n return \"\";\n }\n\n const release = releases[index];\n const isCurrentVersion = semverEqual(release.tag_name, appVersion);\n\n let message = `**Version:** ${release.tag_name}`;\n if (isCurrentVersion) {\n message += ` (Current)`;\n }\n message += `\\n\\n`;\n\n const publishDate = new Date(release.published_at).toLocaleDateString();\n message += `**Released:** ${publishDate}\\n\\n`;\n\n if (!isCurrentVersion) {\n const cleanCurrent = appVersion.replace(/^v/, '');\n const cleanRelease = release.tag_name.replace(/^v/, '');\n const currentParts = cleanCurrent.split('.').map(Number);\n const releaseParts = cleanRelease.split('.').map(Number);\n let isNewer = false;\n for (let i = 0; i < Math.max(currentParts.length, releaseParts.length); i++) {\n const current = currentParts[i] || 0;\n const releasePart = releaseParts[i] || 0;\n if (releasePart > current) {\n isNewer = true;\n break;\n }\n if (releasePart < current) {\n break;\n }\n }\n if (isNewer) {\n message += `⚠️ **Update available - reload page to update**\\n\\n`;\n }\n }\n\n if (release.body) {\n message += `---\\n\\n${release.body}`;\n }\n\n return message;\n };\n\n const handleClose = () => {\n cleanup();\n };\n\n const handleAfterHide = () => {\n cleanup();\n };\n\n const updateDialog = (index: number) => {\n const releaseContent = buildReleaseContent(index);\n const hasNavigation = releases.length > 0;\n\n const template = html`\n <wa-dialog \n label=\"About ${app.name ?? ''} - ${appVersion}\"\n open \n light-dismiss\n style=\"--width: 600px;\"\n @wa-request-close=${handleClose}\n @wa-after-hide=${handleAfterHide}\n >\n <style>\n .dialog-content {\n height: 600px;\n }\n \n wa-tree-item > span small {\n color: var(--wa-color-neutral-60);\n font-size: 0.875em;\n margin-left: 0.5rem;\n }\n </style>\n <small>${app.description ?? ''}</small>\n <div class=\"dialog-content\">\n <wa-tab-group>\n ${releases.length > 0 ? html`\n <wa-tab slot=\"nav\" panel=\"release\">Release History</wa-tab>\n <wa-tab-panel name=\"release\">\n ${renderReleaseContent(releaseContent)}\n </wa-tab-panel>\n ` : ''}\n \n ${hasPackages ? html`\n <wa-tab slot=\"nav\" panel=\"packages\">NPM Packages</wa-tab>\n <wa-tab-panel name=\"packages\">\n ${packagesTree}\n </wa-tab-panel>\n ` : ''}\n </wa-tab-group>\n </div>\n <div slot=\"footer\">\n ${hasNavigation ? html`\n <wa-button \n variant=\"default\"\n ?disabled=${index === releases.length - 1}\n @click=${() => {\n if (index < releases.length - 1) {\n currentReleaseIndex = index + 1;\n updateDialog(currentReleaseIndex);\n }\n }}\n >\n ← Previous\n </wa-button>\n <wa-button \n variant=\"default\"\n ?disabled=${index === 0}\n @click=${() => {\n if (index > 0) {\n currentReleaseIndex = index - 1;\n updateDialog(currentReleaseIndex);\n }\n }}\n >\n Next →\n </wa-button>\n ` : ''}\n <wa-button variant=\"primary\" data-dialog=\"close\">Close</wa-button>\n </div>\n </wa-dialog>\n `;\n render(template, getDialogContainer());\n };\n\n updateDialog(startIndex);\n\n return new Promise<void>((resolve) => {\n const checkClosed = () => {\n if (!dialogContainer?.querySelector('wa-dialog[open]')) {\n resolve();\n } else {\n setTimeout(checkClosed, 100);\n }\n };\n checkClosed();\n });\n }\n }\n})\n\n","import { registerAll } from \"../core/commandregistry\";\nimport { CommandContribution } from \"../core/contributionregistry\";\nimport { TOOLBAR_MAIN_RIGHT } from \"../core/constants\";\nimport { EditorInput, editorRegistry } from \"../core/editorregistry\";\nimport { html } from \"lit\";\nimport { toastError, toastInfo } from \"../core/toast\";\nimport { activePartSignal } from \"../core/appstate\";\nimport { appSettings } from \"../core/settingsservice\";\nimport { extensionRegistry } from \"../core/extensionregistry\";\nimport type { Extension } from \"../core/extensionregistry\";\nimport { marketplaceRegistry } from \"../core/marketplaceregistry\";\nimport \"./files\";\nimport \"./version-info\";\n\nregisterAll({\n command: {\n \"id\": \"save\",\n \"name\": \"Save editor\",\n \"description\": \"Saves the active/focused editor\",\n \"keyBinding\": \"CTRL+S\",\n \"parameters\": []\n },\n handler: {\n execute: async _context => {\n const part = activePartSignal.get()\n if (part && part.isDirty()) {\n part.save()\n }\n }\n },\n contribution: {\n target: \"toolbar:.system.editors\",\n icon: \"floppy-disk\",\n label: \"Save active editor\",\n slot: \"start\",\n disabled: () => {\n const part = activePartSignal.get()\n return !part || !part.isDirty()\n }\n } as CommandContribution\n})\n\nconst THEME_SETTINGS_KEY = \"theme\"\n\nasync function applyTheme(themeClass: 'wa-dark' | 'wa-light'): Promise<void> {\n const root = document.documentElement\n root.classList.remove('wa-dark', 'wa-light')\n root.classList.add(themeClass)\n}\n\nasync function loadTheme(): Promise<void> {\n const theme = await appSettings.get(THEME_SETTINGS_KEY)\n await applyTheme(theme || 'wa-dark')\n}\n\nasync function saveTheme(themeClass: 'wa-dark' | 'wa-light'): Promise<void> {\n await appSettings.set(THEME_SETTINGS_KEY, themeClass)\n}\n\nregisterAll({\n command: {\n \"id\": \"switch_theme\",\n \"name\": \"Switch theme\",\n \"description\": \"Switches between dark and light theme\",\n \"parameters\": []\n },\n handler: {\n execute: async _context => {\n const isDark = document.documentElement.classList.contains(\"wa-dark\")\n const newTheme = isDark ? 'wa-light' : 'wa-dark'\n await applyTheme(newTheme)\n await saveTheme(newTheme)\n }\n },\n contribution: {\n target: TOOLBAR_MAIN_RIGHT,\n icon: \"circle-half-stroke\",\n label: \"Theme Switcher\",\n }\n})\n\n// Load theme on module initialization\nloadTheme().catch(err => {\n console.error('Failed to load theme preference:', err)\n})\n\nregisterAll({\n command: {\n \"id\": \"fullscreen\",\n \"name\": \"Toggle fullscreen\",\n \"description\": \"Toggles fullscreen mode\",\n \"parameters\": []\n },\n handler: {\n execute: async _context => {\n const root = document.documentElement\n if (document.fullscreenElement === root) {\n await document.exitFullscreen()\n } else {\n await root.requestFullscreen()\n }\n }\n },\n contribution: {\n target: TOOLBAR_MAIN_RIGHT,\n icon: \"expand\",\n label: \"Fullscreen\",\n }\n})\n\nregisterAll({\n command: {\n \"id\": \"open_extensions\",\n \"name\": \"Open Extensions\",\n \"description\": \"Opens the extensions registry\",\n \"parameters\": []\n },\n handler: {\n execute: _context => {\n const editorInput: EditorInput = {\n title: \"Extensions\",\n data: {},\n key: \"system.extensions\",\n icon: \"puzzle-piece\",\n state: {},\n component: (id: string) => html`<docks-extensions id=\"${id}\"></docks-extensions>`,\n }\n editorRegistry.loadEditor(editorInput, \"extensions-editor\").then()\n }\n },\n contribution: {\n target: TOOLBAR_MAIN_RIGHT,\n icon: \"puzzle-piece\",\n label: \"Open Extensions\",\n }\n})\n\nregisterAll({\n command: {\n \"id\": \"list_extensions\",\n \"name\": \"List extensions\",\n \"description\": \"Lists all available extensions with their status (enabled/disabled)\",\n \"parameters\": [],\n \"output\": [\n {\n \"name\": \"extensions\",\n \"description\": \"array of extension objects with id, name, description, experimental flag, and enabled status\"\n }\n ]\n },\n handler: {\n execute: async (_context: any) => {\n const extensions = extensionRegistry.getExtensions().map((e: Extension) => {\n return {\n id: e.id,\n name: e.name,\n description: e.description,\n experimental: e.experimental,\n enabled: extensionRegistry.isEnabled(e.id)\n }\n });\n return extensions;\n }\n }\n})\n\nregisterAll({\n command: {\n \"id\": \"toast_message\",\n \"name\": \"Toast message to user\",\n \"description\": \"Shows a toast message\",\n \"parameters\": [\n {\n \"name\": \"message\",\n \"description\": \"the message to toast\",\n \"required\": true\n },\n {\n \"name\": \"type\",\n \"description\": \"the toast type: info (default), or error\",\n \"required\": false\n }\n ]\n },\n handler: {\n execute: ({ params: { message, type } }: any) => {\n if (!message) {\n return\n }\n if (type === \"error\") {\n toastError(message)\n } else {\n toastInfo(message)\n }\n }\n }\n})\n\n","/**\n * Scoped JS execution: one worker runs code in its global scope so state persists across\n * execute() calls. Single source of truth for in-worker JS (e.g. notebook kernel, js command).\n */\nimport JsRuntimeWorker from './js-runtime-worker.js?worker&inline';\n\nexport interface JsRuntime {\n execute(code: string): Promise<unknown>;\n close(): void;\n}\n\nexport function createJsRuntime(): JsRuntime {\n let worker: Worker | null = null;\n let pending: { resolve: (v: unknown) => void; reject: (e: Error) => void } | null = null;\n\n function getWorker(): Worker {\n if (!worker) {\n worker = new JsRuntimeWorker();\n worker.onmessage = (e: MessageEvent<{ type: string; value?: unknown; message?: string }>) => {\n const p = pending;\n pending = null;\n if (!p) return;\n if (e.data.type === 'result') p.resolve(e.data.value);\n else p.reject(new Error(e.data.message ?? 'Unknown error'));\n };\n worker.onerror = (ev) => {\n const p = pending;\n pending = null;\n if (p) p.reject(new Error(ev.message ?? 'Worker error'));\n };\n }\n return worker;\n }\n\n return {\n execute(code: string): Promise<unknown> {\n return new Promise((resolve, reject) => {\n pending = { resolve, reject };\n getWorker().postMessage(code);\n });\n },\n\n close(): void {\n if (worker) {\n worker.terminate();\n worker = null;\n }\n pending = null;\n },\n };\n}\n","import { registerAll } from '../core/commandregistry';\nimport { File, workspaceService } from '../core/filesys';\nimport { toastError, toastInfo } from '../core/toast';\nimport { createJsRuntime } from '../core/js-runtime';\n\nexport function runJavaScriptCode(code: string): Promise<unknown> {\n const runtime = createJsRuntime();\n return runtime.execute(code).finally(() => runtime.close());\n}\n\nasync function getCode(params: {\n script?: string;\n code?: string;\n}): Promise<string | null> {\n if (params.code?.trim()) return params.code.trim();\n if (!params.script) {\n toastError(\"Provide 'script' (file path) or 'code'.\");\n return null;\n }\n const workspace = await workspaceService.getWorkspace();\n if (!workspace) {\n toastError('No workspace selected.');\n return null;\n }\n try {\n const resource = await workspace.getResource(params.script);\n if (!resource || !(resource instanceof File)) {\n toastError('File not found: ' + params.script);\n return null;\n }\n const contents = await resource.getContents();\n if (typeof contents !== 'string') {\n toastError('File is not a text file');\n return null;\n }\n return contents;\n } catch (err: unknown) {\n toastError(`Failed to access file: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n}\n\nregisterAll({\n command: {\n id: 'js',\n name: 'Run JavaScript file',\n description: 'Runs a script via JsRuntime (inline or file). Return value or self.postMessage(value) is shown.',\n parameters: [\n { name: 'script', description: 'workspace path to a .js file', required: false },\n { name: 'code', description: 'inline JavaScript', required: false },\n ],\n },\n handler: {\n execute: async (context: { params?: { script?: string; code?: string } }) => {\n const code = await getCode(context.params ?? {});\n if (!code) return;\n const runtime = createJsRuntime();\n try {\n const result = await runtime.execute(code);\n if (result !== undefined) toastInfo(String(result));\n return result;\n } catch (err: unknown) {\n toastError(err instanceof Error ? err.message : String(err));\n } finally {\n runtime.close();\n }\n },\n },\n});\n","import { registerAll } from \"../core/commandregistry\";\nimport { SYSTEM_VIEWS } from \"../core/constants\";\nimport type { TabContribution } from \"../core/contributionregistry\";\nimport { contributionRegistry } from \"../core/contributionregistry\";\nimport { editorRegistry } from \"../core/editorregistry\";\n\nregisterAll({\n command: {\n id: \"open_view_as_editor\",\n name: \"Open view as editor\",\n description: \"Opens a dashboard view in the editor area\",\n parameters: [\n { name: \"name\", description: \"View contribution name\", required: true },\n { name: \"sourceContributionSlot\", description: \"source contribution slot (default: SYSTEM_VIEWS)\", required: false }\n ]\n },\n handler: {\n execute: async ({ params }: { params?: { name?: string, sourceContributionSlot?: string } }) => {\n const name = params?.name;\n if (!name) return;\n const slot = params?.sourceContributionSlot ?? SYSTEM_VIEWS\n const contributions = contributionRegistry.getContributions(slot) as TabContribution[];\n const contribution = contributions.find(c => c.name === name);\n if (!contribution?.component) return;\n await editorRegistry.openTab(contribution as TabContribution);\n }\n }\n});\n","import { Directory, File } from \"../core/filesys\";\nimport { toastError } from \"../core/toast\";\nimport { workspaceService } from \"../core/filesys\";\n\nexport async function getTextFileFromPath(path: string): Promise<File | null> {\n const workspaceDir = await workspaceService.getWorkspace();\n if (!workspaceDir) {\n toastError(\"No workspace selected.\");\n return null;\n }\n\n try {\n const resource = await workspaceDir.getResource(path);\n if (!(resource instanceof File)) {\n toastError(\"File not found: \" + path);\n return null;\n }\n return resource;\n } catch (err: any) {\n toastError(`Failed to access file: ${err.message ?? err}`);\n return null;\n }\n}\n\nexport async function readTextFile(file: File): Promise<string | null> {\n try {\n const contents = await file.getContents();\n if (typeof contents !== \"string\") {\n toastError(\"File is not a text file\");\n return null;\n }\n return contents;\n } catch (err: any) {\n toastError(`Failed to read file: ${err.message ?? err}`);\n return null;\n }\n}\n\nexport async function collectFilesRecursive(directory: Directory): Promise<string[]> {\n const files: string[] = [];\n const children = await directory.listChildren(true);\n\n for (const child of children) {\n if (child instanceof File) {\n files.push(child.getWorkspacePath());\n continue;\n }\n if (child instanceof Directory) {\n files.push(...await collectFilesRecursive(child));\n }\n }\n\n return files;\n}\n","import { registerAll } from \"../core/commandregistry\";\nimport { toastError } from \"../core/toast\";\nimport { getTextFileFromPath, readTextFile } from \"./shared\";\n\nregisterAll({\n command: {\n id: \"cat\",\n name: \"Cat - Show file contents\",\n description: \"Shows the complete contents of a file\",\n parameters: [\n {\n name: \"path\",\n description: \"the path of the file to read\",\n required: true\n }\n ],\n output: [\n {\n name: \"content\",\n description: \"the complete contents of the file\"\n }\n ]\n },\n handler: {\n execute: async ({ params }: any) => {\n const path = params?.path;\n if (!path) {\n toastError(\"No file path provided.\");\n return;\n }\n\n const file = await getTextFileFromPath(path);\n if (!file) return;\n\n return readTextFile(file);\n }\n }\n});\n","import { registerAll } from \"../core/commandregistry\";\nimport { File, workspaceService } from \"../core/filesys\";\n\nregisterAll({\n command: {\n id: \"exists\",\n name: \"Exists\",\n description: \"Checks if a file exists at the given path (like bash test -f)\",\n parameters: [\n {\n name: \"path\",\n description: \"Path of the file to check, relative to the workspace\",\n required: true\n }\n ],\n output: [\n {\n name: \"exists\",\n description: \"true if the file exists, false otherwise\"\n }\n ]\n },\n handler: {\n execute: async ({ params }: any) => {\n const workspace = await workspaceService.getWorkspace();\n if (!workspace) return false;\n\n const path = params?.path;\n if (!path) return false;\n\n try {\n const resource = await workspace.getResource(path);\n return resource instanceof File;\n } catch {\n return false;\n }\n }\n }\n});\n","import { activeSelectionSignal } from \"../core/appstate\";\nimport { contributionRegistry } from \"../core/contributionregistry\";\nimport { Directory, File } from \"../core/filesys\";\n\nfunction isResource(obj: unknown): obj is File | Directory {\n return obj instanceof File || obj instanceof Directory;\n}\n\nconst disabled = () => !isResource(activeSelectionSignal.get());\nconst deleteDisabled = () => {\n const selection = activeSelectionSignal.get();\n if (!isResource(selection)) return true;\n if (selection instanceof Directory && selection.getParent() === undefined) return true;\n return false;\n};\n\ncontributionRegistry.registerContribution(\"filebrowser.create\", {\n name: \"filebrowser.create.file\",\n command: \"touch\",\n icon: \"docks file-plus\",\n label: \"Create File...\",\n params: { ask: true }\n});\n\ncontributionRegistry.registerContribution(\"filebrowser.create\", {\n name: \"filebrowser.create.folder\",\n command: \"mkdir\",\n icon: \"folder-plus\",\n label: \"Create Folder...\",\n params: { ask: true }\n});\n\ncontributionRegistry.registerContribution(\"toolbar:view.filebrowser\", {\n name: \"toolbar.filebrowser.rename\",\n command: \"mv\",\n icon: \"pen\",\n label: \"Rename\",\n disabled\n});\n\ncontributionRegistry.registerContribution(\"toolbar:view.filebrowser\", {\n name: \"toolbar.filebrowser.delete\",\n command: \"rm\",\n icon: \"trash\",\n label: \"Delete\",\n disabled: deleteDisabled\n});\n\ncontributionRegistry.registerContribution(\"contextmenu:view.filebrowser\", {\n name: \"contextmenu.filebrowser.create-folder\",\n command: \"mkdir\",\n icon: \"folder-plus\",\n label: \"Create Folder...\",\n params: { ask: true }\n});\n\ncontributionRegistry.registerContribution(\"contextmenu:view.filebrowser\", {\n name: \"contextmenu.filebrowser.rename\",\n command: \"mv\",\n icon: \"pen\",\n label: \"Rename\",\n disabled\n});\n\ncontributionRegistry.registerContribution(\"contextmenu:view.filebrowser\", {\n name: \"contextmenu.filebrowser.delete\",\n command: \"rm\",\n icon: \"trash\",\n label: \"Delete\",\n disabled: deleteDisabled\n});\n","import { registerAll } from \"../core/commandregistry\";\nimport { toastError } from \"../core/toast\";\nimport { getTextFileFromPath, readTextFile } from \"./shared\";\n\nregisterAll({\n command: {\n id: \"head\",\n name: \"Head - Show first lines\",\n description: \"Shows the first N lines of a file\",\n parameters: [\n {\n name: \"path\",\n description: \"the path of the file to read\",\n required: true\n },\n {\n name: \"lines\",\n description: \"number of lines to show from the beginning (default: 10)\",\n type: \"number\",\n required: false\n }\n ],\n output: [\n {\n name: \"content\",\n description: \"the first N lines of the file\"\n }\n ]\n },\n handler: {\n execute: async ({ params }: any) => {\n const path = params?.path;\n if (!path) {\n toastError(\"No file path provided.\");\n return;\n }\n\n const file = await getTextFileFromPath(path);\n if (!file) return;\n\n const numLines = params?.lines ? parseInt(params.lines, 10) : 10;\n if (Number.isNaN(numLines) || numLines < 1) {\n toastError(\"Number of lines must be a positive integer\");\n return;\n }\n\n const contents = await readTextFile(file);\n if (!contents) return;\n\n return contents.split(\"\\n\").slice(0, numLines).join(\"\\n\");\n }\n }\n});\n","import { registerAll } from \"../core/commandregistry\";\nimport { Directory, File, workspaceService } from \"../core/filesys\";\nimport { toastError } from \"../core/toast\";\nimport { collectFilesRecursive } from \"./shared\";\n\nregisterAll({\n command: {\n id: \"ls\",\n name: \"List files\",\n description: \"Lists files from a directory. If recursive is provided, it traverses from the provided directory down to all leaves. If no directory is provided, it will traverse from the workspace root.\",\n parameters: [\n {\n name: \"path\",\n description: \"the path of the directory to list, relative to the workspace. If not provided, uses workspace root\",\n required: false\n },\n {\n name: \"recursive\",\n description: \"whether to recursively traverse all subdirectories\",\n type: \"boolean\",\n required: false\n }\n ],\n output: [\n {\n name: \"files\",\n description: \"array of file objects with path and size information\"\n }\n ]\n },\n handler: {\n execute: async ({ params }: any) => {\n const workspace = await workspaceService.getWorkspace();\n if (!workspace) {\n toastError(\"No workspace available\");\n return [];\n }\n\n const path = params?.path as string | undefined;\n const recursive = params?.recursive === true || params?.recursive === \"true\";\n\n try {\n let targetDir: Directory = workspace;\n if (path) {\n const resource = await workspace.getResource(path);\n if (!resource) {\n toastError(`Path not found: ${path}`);\n return [];\n }\n if (!(resource instanceof Directory)) {\n toastError(`Path is not a directory: ${path}`);\n return [];\n }\n targetDir = resource;\n }\n\n if (recursive) {\n const files = await collectFilesRecursive(targetDir);\n const result: Array<{ path: string; size: number | null }> = [];\n for (const filePath of files) {\n const file = await workspace.getResource(filePath);\n if (!(file instanceof File)) continue;\n result.push({ path: filePath, size: await file.size() });\n }\n return result;\n }\n\n const children = await targetDir.listChildren(true);\n const result: Array<{ path: string; size: number | null }> = [];\n for (const child of children) {\n if (!(child instanceof File)) continue;\n result.push({ path: child.getWorkspacePath(), size: await child.size() });\n }\n return result;\n } catch (err: any) {\n toastError(`Failed to list files: ${err.message ?? err}`);\n return [];\n }\n }\n }\n});\n","import { registerAll } from \"../core/commandregistry\";\nimport { activeSelectionSignal } from \"../core/appstate\";\nimport { Directory, File, workspaceService } from \"../core/filesys\";\nimport { promptDialog } from \"../dialogs\";\nimport { toastError, toastInfo } from \"../core/toast\";\n\nfunction normalizeTargetPath(inputPath: string): string {\n return inputPath.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n}\n\nfunction resolveSelectionBasePath(): string | undefined {\n const selection = activeSelectionSignal.get();\n if (selection instanceof Directory) {\n return selection.getWorkspacePath();\n }\n if (selection instanceof File) {\n return selection.getParent()?.getWorkspacePath();\n }\n return undefined;\n}\n\nfunction joinPath(basePath: string | undefined, name: string): string {\n if (!basePath) return name;\n return `${basePath}/${name}`;\n}\n\nasync function getDefaultFolderPath(basePath: string | undefined): Promise<string | undefined> {\n const workspaceDir = await workspaceService.getWorkspace();\n if (!workspaceDir) {\n toastError(\"No workspace selected.\");\n return;\n }\n\n const baseName = \"New Folder\";\n let candidate = joinPath(basePath, baseName);\n let existing = await workspaceDir.getResource(candidate);\n if (!existing) {\n return candidate;\n }\n\n let suffix = 0;\n while (true) {\n candidate = joinPath(basePath, `${baseName} (${suffix})`);\n existing = await workspaceDir.getResource(candidate);\n if (!existing) {\n return candidate;\n }\n suffix++;\n }\n}\n\nregisterAll({\n command: {\n id: \"mkdir\",\n name: \"mkdir - Create new folder\",\n description: \"Creates a new folder within the workspace.\",\n parameters: [\n {\n name: \"path\",\n description: \"the folder path to create, relative to the workspace\",\n required: false\n },\n {\n name: \"ask\",\n description: \"whether to prompt the user for the folder path\",\n required: false\n }\n ],\n output: [\n {\n name: \"path\",\n description: \"the path of the created folder\"\n }\n ]\n },\n handler: {\n execute: async ({ params }: any) => {\n const ask = params?.ask;\n let path = params?.path as string | undefined | null;\n const defaultPath = await getDefaultFolderPath(resolveSelectionBasePath());\n if (!defaultPath) return;\n\n if (ask || !path) {\n path = await promptDialog(\"Enter path to new folder:\", path || defaultPath);\n if (!path) return;\n }\n\n const isAbsolute = path.startsWith(\"/\");\n let normalizedPath = normalizeTargetPath(path);\n if (!normalizedPath) {\n toastError(\"Folder path must not be empty.\");\n return;\n }\n\n if (!isAbsolute) {\n const basePath = resolveSelectionBasePath();\n if (basePath && !normalizedPath.startsWith(basePath + \"/\")) {\n normalizedPath = `${basePath}/${normalizedPath}`;\n }\n }\n\n const workspaceDir = await workspaceService.getWorkspace();\n if (!workspaceDir) {\n toastError(\"No workspace selected.\");\n return;\n }\n\n const existingResource = await workspaceDir.getResource(normalizedPath);\n if (existingResource instanceof Directory) {\n toastInfo(`Folder already exists: ${normalizedPath}`);\n return normalizedPath;\n }\n if (existingResource instanceof File) {\n toastError(`Cannot create folder. A file already exists at \"${normalizedPath}\".`);\n return;\n }\n\n const createdDirectory = await workspaceDir.getResource(`${normalizedPath}/`, { create: true });\n if (!(createdDirectory instanceof Directory)) {\n toastError(`Could not create folder: ${normalizedPath}`);\n return;\n }\n\n toastInfo(`Folder created: ${normalizedPath}`);\n return normalizedPath;\n }\n }\n});\n","import { registerAll } from \"../core/commandregistry\";\nimport { activeSelectionSignal } from \"../core/appstate\";\nimport { workspaceService } from \"../core/filesys\";\nimport { promptDialog } from \"../dialogs\";\nimport { toastError, toastInfo } from \"../core/toast\";\n\nregisterAll({\n command: {\n id: \"mv\",\n name: \"mv - Rename a resource (file or directory)\",\n description: \"Renames a resource (file or directory)\",\n keyBinding: \"F2\",\n parameters: [\n {\n name: \"path\",\n description: \"the path of the resource within the workspace to rename or the currently active selection\",\n required: false\n },\n {\n name: \"newName\",\n description: \"the new name for the resource\",\n required: false\n }\n ]\n },\n handler: {\n execute: async (context: any) => {\n const workspaceDir = await workspaceService.getWorkspace();\n if (!workspaceDir) {\n toastError(\"No workspace selected.\");\n return;\n }\n\n const path = context.params?.path as string | undefined;\n let resource: any = null;\n\n if (path) {\n resource = await workspaceDir.getResource(path);\n }\n if (!resource) {\n resource = activeSelectionSignal.get();\n }\n if (!resource) {\n toastError(\"No resource to rename provided!\");\n return;\n }\n\n const currentName = resource.getName();\n const newName = context.params?.newName ?? await promptDialog(`Enter new name for \"${currentName}\":`, currentName);\n if (!newName || newName === currentName) return;\n\n try {\n await resource.rename(newName);\n toastInfo(`Resource renamed to: ${newName}`);\n } catch (err: any) {\n toastError(`Failed to rename ${currentName}: ${err.message ?? err}`);\n }\n }\n }\n});\n","import { registerAll } from \"../core/commandregistry\";\nimport { activeSelectionSignal } from \"../core/appstate\";\nimport { Directory, workspaceService } from \"../core/filesys\";\nimport { confirmDialog } from \"../dialogs\";\nimport { toastError, toastInfo } from \"../core/toast\";\n\nregisterAll({\n command: {\n id: \"rm\",\n name: \"rm - Delete a resource (file or directory)\",\n description: \"Deletes a resource (file or directory)\",\n keyBinding: \"Delete\",\n parameters: [\n {\n name: \"path\",\n description: \"the path of the resource within the workspace to delete or the currently active selection\",\n required: false\n },\n {\n name: \"confirm\",\n description: \"whether to ask the user to confirm the deletion, true by default\",\n required: false\n }\n ]\n },\n handler: {\n execute: async (context: any) => {\n const workspaceDir = await workspaceService.getWorkspace();\n if (!workspaceDir) {\n toastError(\"No workspace selected.\");\n return;\n }\n\n const path = context.params?.path as string | undefined;\n let resource: any = null;\n\n if (path) {\n resource = await workspaceDir.getResource(path);\n }\n if (!resource) {\n resource = activeSelectionSignal.get();\n }\n if (!resource) {\n toastError(\"No resource to delete provided!\");\n return;\n }\n\n if (resource instanceof Directory && resource.getParent() === undefined) {\n toastError('Root folders cannot be deleted. Use \"Disconnect folder\" instead.');\n return;\n }\n\n const resourcePath = resource.getWorkspacePath();\n const confirmParam = context.params?.confirm;\n if (confirmParam === undefined || confirmParam === true) {\n const yes = await confirmDialog(`Are you sure you want to delete ${resourcePath}?`);\n if (!yes) return;\n }\n\n try {\n await resource.delete();\n toastInfo(\"Resource deleted: \" + resourcePath);\n } catch (err: any) {\n toastError(`Resource ${resourcePath} could not be deleted: ${err.message ?? err}`);\n }\n }\n }\n});\n","import { registerAll } from \"../core/commandregistry\";\nimport { toastError } from \"../core/toast\";\nimport { getTextFileFromPath, readTextFile } from \"./shared\";\n\nregisterAll({\n command: {\n id: \"tail\",\n name: \"Tail - Show last lines\",\n description: \"Shows the last N lines of a file\",\n parameters: [\n {\n name: \"path\",\n description: \"the path of the file to read\",\n required: true\n },\n {\n name: \"lines\",\n description: \"number of lines to show from the end (default: 10)\",\n type: \"number\",\n required: false\n }\n ],\n output: [\n {\n name: \"content\",\n description: \"the last N lines of the file\"\n }\n ]\n },\n handler: {\n execute: async ({ params }: any) => {\n const path = params?.path;\n if (!path) {\n toastError(\"No file path provided.\");\n return;\n }\n\n const file = await getTextFileFromPath(path);\n if (!file) return;\n\n const numLines = params?.lines ? parseInt(params.lines, 10) : 10;\n if (Number.isNaN(numLines) || numLines < 1) {\n toastError(\"Number of lines must be a positive integer\");\n return;\n }\n\n const contents = await readTextFile(file);\n if (!contents) return;\n\n return contents.split(\"\\n\").slice(-numLines).join(\"\\n\");\n }\n }\n});\n","import { registerAll } from \"../core/commandregistry\";\nimport { activeSelectionSignal } from \"../core/appstate\";\nimport { Directory, File, workspaceService } from \"../core/filesys\";\nimport { confirmDialog, promptDialog } from \"../dialogs\";\nimport { toastError, toastInfo } from \"../core/toast\";\n\nregisterAll({\n command: {\n id: \"touch\",\n name: \"Touch - Create new file\",\n description: \"Creates a new file within the workspace. For .docks map files, use create_map_file instead.\",\n parameters: [\n {\n name: \"path\",\n description: \"the path including name of the file to be created, must be relative to the workspace\",\n required: false\n },\n {\n name: \"contents\",\n description: \"the textual contents of the file\",\n required: false\n },\n {\n name: \"ask\",\n description: \"whether to prompt the user for the file path\",\n required: false\n },\n {\n name: \"extension\",\n description: \"required file extension (e.g., '.docks'), will be appended if missing\",\n required: false\n }\n ],\n output: [\n {\n name: \"path\",\n description: \"the path of the created file\"\n }\n ]\n },\n handler: {\n execute: async ({ params }: any) => {\n let path = params?.path as string | undefined | null;\n const contents = params?.contents as string | undefined;\n const ask = params?.ask;\n const extension = params?.extension as string | undefined;\n\n if (ask || !path) {\n path = await promptDialog(\"Enter path to new file (directories will be created if not exist):\", path || \"\");\n if (!path) return;\n }\n\n if (extension && !path.endsWith(extension)) {\n path += extension;\n }\n\n const isAbsolute = path.startsWith(\"/\");\n if (!isAbsolute) {\n const selection = activeSelectionSignal.get();\n const dirPath = selection instanceof Directory\n ? selection.getWorkspacePath()\n : selection instanceof File\n ? selection.getParent()?.getWorkspacePath()\n : undefined;\n if (dirPath && !path.startsWith(dirPath + \"/\")) {\n path = dirPath + \"/\" + path;\n }\n } else {\n path = path.slice(1);\n }\n\n const workspaceDir = await workspaceService.getWorkspace();\n if (!workspaceDir) {\n toastError(\"No workspace selected.\");\n return;\n }\n\n const existingResource = await workspaceDir.getResource(path);\n if (existingResource) {\n const overwrite = await confirmDialog(`File \"${path}\" already exists. Do you want to overwrite it?`);\n if (!overwrite) return;\n }\n\n const createdResource = await workspaceDir.getResource(path, { create: true });\n if (!(createdResource instanceof File)) {\n toastError(\"Could not create file: \" + path);\n return;\n }\n\n if (contents) {\n await createdResource.saveContents(contents);\n }\n\n toastInfo(`File created: ${path}`);\n return path;\n }\n }\n});\n","import JSZip from \"jszip\";\nimport { registerAll } from \"../core/commandregistry\";\nimport { activeSelectionSignal } from \"../core/appstate\";\nimport { File, FileContentType, workspaceService } from \"../core/filesys\";\nimport { taskService } from \"../core/taskservice\";\nimport { toastError, toastInfo } from \"../core/toast\";\n\nregisterAll({\n command: {\n id: \"unzip\",\n name: \"Unzip Archive\",\n description: \"Extract a zip archive from the workspace\",\n parameters: [\n {\n name: \"file\",\n description: \"the zip file to extract, if not provided, the current selection will be used\",\n required: false\n },\n {\n name: \"target\",\n description: \"target folder to extract into, defaults to the zip filename without extension\",\n required: false\n }\n ]\n },\n handler: {\n canExecute: (context: any) => {\n let filePath: string = context.params?.file;\n if (!filePath) {\n const selectedItem = activeSelectionSignal.get() as any;\n if (!selectedItem || !(\"path\" in selectedItem)) return false;\n filePath = selectedItem.path;\n }\n return filePath.toLowerCase().endsWith(\".zip\");\n },\n execute: async (context: any) => {\n let filePath: string = context.params?.file;\n if (!filePath) {\n const selectedItem = activeSelectionSignal.get() as any;\n filePath = selectedItem.path;\n }\n\n const workspaceDir = await workspaceService.getWorkspace();\n if (!workspaceDir) {\n toastError(\"No workspace selected.\");\n return;\n }\n\n await taskService.runAsync(\"Extracting archive\", async (progress: any) => {\n try {\n const fileResource = await workspaceDir.getResource(filePath);\n if (!fileResource) {\n toastError(\"File not found: \" + filePath);\n return;\n }\n\n let targetFolder = context.params?.target;\n if (!targetFolder) {\n const fileName = filePath.split(\"/\").pop() || \"extracted\";\n targetFolder = fileName.replace(/\\.zip$/i, \"\") + \"/\";\n }\n\n progress.message = \"Loading archive...\";\n progress.progress = 0;\n await workspaceDir.getResource(targetFolder, { create: true });\n\n const file = fileResource as File;\n const blob = await file.getContents({ blob: true });\n const zip = await JSZip.loadAsync(blob);\n const totalFiles = Object.values(zip.files).filter(entry => !entry.dir).length;\n let extractedCount = 0;\n\n progress.message = `Extracting to ${targetFolder.replace(/\\/$/, \"\")}...`;\n\n for (const [relativePath, zipEntry] of Object.entries(zip.files)) {\n if (zipEntry.dir) continue;\n\n const entryBlob = await zipEntry.async(\"blob\");\n const fullPath = `${targetFolder}${relativePath}`;\n const entryResource = await workspaceDir.getResource(fullPath, { create: true });\n const newFile = entryResource as File;\n await newFile.saveContents(entryBlob, { contentType: FileContentType.BINARY });\n\n extractedCount++;\n progress.progress = Math.round((extractedCount / totalFiles) * 100);\n progress.message = `Extracting ${extractedCount}/${totalFiles} files...`;\n }\n\n progress.progress = 100;\n toastInfo(`Archive extracted to ${targetFolder.replace(/\\/$/, \"\")}: ${extractedCount} file(s)`);\n } catch (err: any) {\n toastError(\"Failed to extract archive: \" + err);\n throw err;\n }\n });\n }\n }\n});\n","import { registerAll } from \"../core/commandregistry\";\nimport { toastError } from \"../core/toast\";\nimport { getTextFileFromPath, readTextFile } from \"./shared\";\n\nregisterAll({\n command: {\n id: \"wc\",\n name: \"Word count\",\n description: \"Counts lines, words, and characters in a file\",\n parameters: [\n {\n name: \"path\",\n description: \"the path of the file to analyze\",\n required: true\n }\n ],\n output: [\n {\n name: \"lines\",\n description: \"number of lines in the file\"\n },\n {\n name: \"words\",\n description: \"number of words in the file\"\n },\n {\n name: \"characters\",\n description: \"number of characters in the file\"\n }\n ]\n },\n handler: {\n execute: async ({ params }: any) => {\n const path = params?.path;\n if (!path) {\n toastError(\"No file path provided.\");\n return;\n }\n\n const file = await getTextFileFromPath(path);\n if (!file) return;\n\n const contents = await readTextFile(file);\n if (!contents) return;\n\n const lines = contents.split(\"\\n\");\n const trimmed = contents.trim();\n const wordCount = trimmed === \"\" ? 0 : trimmed.split(/\\s+/).filter(w => w.length > 0).length;\n\n return {\n lines: lines.length,\n words: wordCount,\n characters: contents.length\n };\n }\n }\n});\n","import { registerAll } from \"../core/commandregistry\";\nimport { File, FileContentType, workspaceService } from \"../core/filesys\";\nimport { taskService } from \"../core/taskservice\";\nimport { toastError, toastInfo } from \"../core/toast\";\nimport { filebrowserDialog } from \"../dialogs/filebrowser-dialog\";\n\nfunction fallbackFileName(): string {\n return `downloaded-file-${new Date().toISOString().replace(/[:.]/g, \"-\").replace(\"T\", \"_\").slice(0, -5)}`;\n}\n\nfunction fileNameFromUrl(url: string): string {\n if (url.startsWith(\"data:\")) {\n return fallbackFileName();\n }\n try {\n const segs = new URL(url).pathname.split(\"/\").filter((s) => s.length > 0);\n const last = segs[segs.length - 1];\n if (last?.includes(\".\") && !last.includes(\";\")) return last;\n } catch {\n // ignore invalid URL parsing details\n }\n return fallbackFileName();\n}\n\nfunction isSupportedWgetUrl(url: string): boolean {\n try {\n const { protocol } = new URL(url);\n return protocol === \"http:\" || protocol === \"https:\" || protocol === \"data:\" || protocol === \"blob:\";\n } catch {\n return false;\n }\n}\n\nregisterAll({\n command: {\n id: \"wget\",\n name: \"wget\",\n description: \"Download a file from a URL to the workspace\",\n parameters: [\n { name: \"url\", description: \"the URL of the file to download\", required: true },\n { name: \"filename\", description: \"optional filename to save as (will be auto-detected if not provided)\", required: false },\n {\n name: \"targetPath\",\n description: \"workspace path where to save; if not provided, a file browser dialog is shown to pick a directory\",\n required: false\n }\n ]\n },\n handler: {\n canExecute: (context: any) => {\n const url = context.params?.url;\n return Boolean(url && isSupportedWgetUrl(url));\n },\n execute: async (context: any) => {\n const url = context.params?.url;\n if (!url) {\n toastError(\"No URL provided.\");\n return;\n }\n\n const workspaceDir = await workspaceService.getWorkspace();\n if (!workspaceDir) {\n toastError(\"No workspace selected.\");\n return;\n }\n\n const explicitName =\n typeof context.params?.filename === \"string\" ? context.params.filename.trim() : \"\";\n const defaultFileName = explicitName || fileNameFromUrl(url);\n let savePath: string;\n const targetPath = context.params?.targetPath;\n\n if (targetPath) {\n const folders = await workspaceService.getFolders();\n const firstFolder = folders.length > 0 ? folders[0].name : null;\n const resolved = targetPath.includes(\"/\") ? targetPath : (firstFolder ? `${firstFolder}/${targetPath}` : targetPath);\n const lastSegment = resolved.split(\"/\").pop() ?? \"\";\n savePath = lastSegment.includes(\".\") && lastSegment !== resolved\n ? resolved\n : `${resolved.replace(/\\/$/, \"\")}/${defaultFileName}`;\n } else {\n const chosenDir = await filebrowserDialog(\"directory\");\n if (chosenDir == null) return;\n savePath = `${chosenDir}/${defaultFileName}`;\n }\n\n await taskService.runAsync(\"Downloading file\", async (progress: any) => {\n progress.message = \"Starting download...\";\n progress.progress = 0;\n\n try {\n const response = await fetch(url, { mode: \"cors\", credentials: \"omit\" });\n if (!response.ok) {\n toastError(\"Failed to download file: \" + response.statusText);\n return;\n }\n\n let fileName = context.params?.filename;\n if (!fileName) {\n const contentDisposition = response.headers.get(\"content-disposition\");\n if (contentDisposition) {\n const match = contentDisposition.match(/filename=\"?([^\";\\n]+)\"?/);\n if (match?.[1]) fileName = match[1].trim();\n }\n }\n if (!fileName) fileName = defaultFileName;\n\n const pathToUse = savePath.includes(\"/\") ? savePath.replace(/\\/[^/]+$/, `/${fileName}`) : fileName;\n progress.message = `Downloading ${fileName}...`;\n progress.progress = 50;\n\n const downloadedFile = await workspaceDir.getResource(pathToUse, { create: true }) as File;\n await downloadedFile.saveContents(response.body, { contentType: FileContentType.BINARY });\n\n progress.progress = 100;\n toastInfo(`File downloaded: ${fileName}`);\n } catch (err) {\n toastError(\"Failed to download file: \" + String(err));\n throw err;\n }\n });\n }\n }\n});\n","// 0. Context seed (lit, constants, toast) – di only provides empty contexts\nimport { rootContext, uiContext } from './di';\nimport { html, render } from 'lit';\nimport * as constants from './constants';\nimport { toastInfo, toastError, toastWarning } from './toast';\nimport { publish, subscribe } from './events';\n\nrootContext.put('constants', constants);\nuiContext.put('html', html);\nuiContext.put('render', render);\nuiContext.put('toastInfo', toastInfo);\nuiContext.put('toastError', toastError);\nuiContext.put('toastWarning', toastWarning);\nuiContext.put('publish', publish);\nuiContext.put('subscribe', subscribe);\n\n// 1. Foundation: logging, persistence, settings\nimport './logger';\nimport './persistenceservice';\nimport './settingsservice';\n\n// 2. Registries and task service (contribution first – others depend on it)\nimport './contributionregistry';\nimport './taskservice';\n\n// 3. i18n and ESM\nimport './i18n';\nimport './esmsh-service';\n\n// 4. Command and extension registries\nimport './commandregistry';\nimport './extensionregistry';\n\n// 5. UI and workspace services\nimport './keybindings';\nimport './dialogservice';\nimport './editorregistry';\nimport './filesys';\n\n// 6. App loader and marketplace\nimport './apploader';\nimport './marketplaceregistry';\n\n// 7. Language bundles and dialogs (use contributionRegistry / dialogService)\nimport '../i18n';\nimport '../dialogs';\n\n// 8. Parts, components, widgets, contributions, commands (extensions registered by app host)\nimport '../parts';\nimport '../components';\nimport '../widgets';\nimport '../contributions';\nimport '../commands';\n","// Framework Configuration\n// \n// This module provides frameworwide configuration that can be customized\n// by applications built on the framework.\n\nexport interface FrameworkConfig {\n // Logger configuration\n logger?: {\n level?: 'debug' | 'info' | 'warning' | 'error';\n };\n}\n\nlet frameworkConfig: FrameworkConfig = {};\n\n/**\n * Initialize framework configuration\n * This should be called before framework bootstrap (if custom config is needed)\n */\nexport function configureFramework(config: FrameworkConfig): void {\n frameworkConfig = { ...frameworkConfig, ...config };\n}\n\n/**\n * Get current framework configuration\n */\nexport function getFrameworkConfig(): Readonly<FrameworkConfig> {\n return { ...frameworkConfig };\n}\n\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwBA,IAAa,wBAAwB;AAIrC,SAAS,kBAAkB,MAAc,QAAyC;AAC9E,KAAI,CAAC,OAAQ,QAAO;AACpB,QAAO,KAAK,QAAQ,eAAe,OAAO,aACtC,OAAO,cAAc,KAAA,IAAY,OAAO,YAAY,MACvD;;AAGL,IAAM,mBAAmB,IAAI,IAAY,CAAA,KAAkB,CAAC;AAC5D,IAAa,yBAAoD,OAAO,iBAAiB;AAEzF,IAAI,uBAAsC;AAE1C,SAAS,oBAAoB,SAAyB;CAClD,IAAI,UAAU;AACd,MAAK,MAAM,OAAO,SAAS;EACvB,MAAM,aAAa,IAAI,aAAa,CAAC,QAAQ,KAAK,IAAI;AACtD,MAAI,CAAC,iBAAiB,IAAI,WAAW,EAAE;AACnC,oBAAiB,IAAI,WAAW;AAChC,aAAU;;;AAGlB,KAAI,SAAS;AACT,yBAAuB,IAAI,IAAI,IAAI,iBAAiB,CAAC;AACrD,MAAI,yBAAyB,MAAM;GAC/B,MAAM,YAAY,6BAA6B;AAC/C,OAAI,cAAc,sBAAsB,KAAK,CAAE,uBAAsB,IAAI,UAAU;;;;AAK/F,SAAS,8BAAsC;CAC3C,MAAM,OAAO,UAAU,WAAW,SAAS,UAAU,YAAY,CAAC,UAAU,YAAA,KAA6B;CACzG,MAAM,YAAY,uBAAuB,KAAK;AAC9C,MAAK,MAAM,OAAO,MAAM;EACpB,MAAM,UAAU,IAAI,MAAM,IAAI,CAAC,GAAG,aAAa;AAC/C,MAAI,UAAU,IAAI,QAAQ,CAAE,QAAO;;AAEvC,QAAA;;AAGJ,IAAa,wBAA8C,OAAO,6BAA6B,CAAC;AAEhG,eAAe,6BAA4C;CACvD,MAAM,mBAAmB,MAAM,YAAY,IAAI,sBAAsB;AACrE,wBAAuB,oBAAoB;AAC3C,uBAAsB,IAAI,oBAAoB,6BAA6B,CAAC;;AAGhF,UAAU,yBAAyB,aAAkB;AACjD,wBAAuB,WAAA,eAAqC;AAC5D,uBAAsB,IAAI,WAAA,eAAqC,6BAA6B,CAAC;EAC/F;AAEF,4BAA4B;AAW5B,SAAgB,gBAAgB,QAAiC;AAC7D,QAAO;EACH,gBAAgB,QAAQ;EACxB,eAAe,QAAQ;GACtB,OAAO,oBAAoB,QAAQ;EACpC,cAAc,QAAQ;EACzB;;AASL,eAAsB,KAAmD,OAAU,WAAW,OAAO;CACjG,MAAM,WAAqC,EAAE;AAE7C,OAAM,QAAQ,IACV,OAAO,QAAQ,MAAM,CAAC,IAAI,OAAO,CAAC,MAAM,YAAY;EAChD,MAAM,MAAM,MAAM,QAAQ;EAC1B,MAAM,WAAsB,OAAO,aAAa,MAAO,IAAY,UAAU;EAG7E,MAAM,oBAFQ,KAAK,MAAM,yBAAyB,GACxB,MAAA,MACS,aAAa,CAAC,QAAQ,KAAK,IAAI;AAClE,WAAS,oBAAoB;GAC/B,CACL;AAED,qBAAoB,OAAO,KAAK,SAAS,CAAC;CAK1C,MAAM,cAAc,QAAwB;EAGxC,MAAM,CAAC,MAAM,UAFG,sBAAsB,KAAK,CAChB,aAAa,CAAC,QAAQ,KAAK,IAAI,CACxB,MAAM,IAAI;EAC5C,MAAM,aAAuB,SAAS,CAAC,GAAG,KAAK,GAAG,UAAU,KAAK,GAAG,CAAC,KAAK;AAC1E,aAAW,KAAA,KAAsB;AACjC,OAAK,MAAM,OAAO,YAAY;GAC1B,MAAM,OAAO,SAAS;AACtB,OAAI,QAAQ,OAAO,KAAM,QAAO,KAAK;;AAEzC,SAAO;;CAGX,MAAM,SAAS,OAAO,OAAO,EAAE,EAAY;EAAE,MAAM,KAAA;EAAW,OAAO,KAAA;EAAW,SAAS,KAAA;EAAW,CAAC;AAgBrG,QAAO,IAAI,MAAM,QAdqB,EAClC,IAAI,GAAG,KAAa;AAChB,MAAI,OAAO,EAAG,QAAQ,EAA8B;EACpD,MAAM,OAAO,WAAW,IAAI;EAC5B,MAAM,OAAO,WACT,kBAAkB,WAAW,IAAI,EAAE,OAAO;AAC7C,KAAW,iBAAkB,WAAW,WAAW,IAAI,GAAG;AAC1D,KAAW,gBAAiB,WAAW,WAAW,IAAI,GAAG;AACzD,KAAW,OAAO,qBAAsB,WAAW,WAAW,IAAI,GAAG;AACtE,MAAI,SAAW,IAAW,eAAe,WAAW,IAAI;AACxD,SAAO;IAEd,CAEgC;;;;AC9ErC,IAAM,iBAAN,MAAqB;CAIjB,cAAc;6BAHgD,EAAE;iCACH;AAGzD,YAAU,iCAAiC,GAEzC;AAEF,YAAU,+BAA+B,UAAe;AACpD,OAAI,MAAM,WAAW,eACjB,MAAK,0BAA0B;IAErC;;CAGN,6BAAyD;AACrD,MAAI,KAAK,4BAA4B,KACjC,QAAO,KAAK;AAMhB,OAAK,0BAA0B,CAAC,GAHV,qBAAqB,iBAAiB,eAAe,CAG1B,CAAC,MAAM,GAAG,MAAM;GAC7D,MAAM,YAAY,EAAE,YAAY;GAChC,MAAM,YAAY,EAAE,YAAY;AAChC,OAAI,cAAc,UAEd,QAAO,YAAY;AAEvB,UAAO,EAAE,MAAM,cAAc,EAAE,MAAM;IACvC;AAEF,SAAO,KAAK;;CAGhB,2BAA2B,oBAAwC;AAC/D,OAAK,oBAAoB,KAAK;GAC1B,YAAY;GACZ,aAAa;GAChB,CAAC;AAEF,OAAK,oBAAoB,MAAM,GAAG,MAAM;GACpC,MAAM,QAAQ,EAAE,WAAW,WAAW;AAEtC,WADc,EAAE,WAAW,WAAW,KACvB;IACjB;;CAGN,MAAc,yBAAyB,OAAoD;EACvF,MAAM,UAAU,MAAM;AACtB,MAAI,CAAC,QAAQ,YAAY,MAAM,YAC3B;AAGJ,MAAI,CAAC,MAAM,gBACP,OAAM,kBAAkB,QAAQ,QAAQ,QAAQ,UAAU,CAAC,CAAC,WAAW;AACnE,SAAM,cAAc;AACpB,SAAM,kBAAkB,KAAA;IAC1B,CAAC,OAAM,UAAS;AACd,SAAM,kBAAkB,KAAA;AACxB,SAAM;IACR;AAGN,QAAM,MAAM;;CAGhB,yBAAyB,OAAuE;EAC5F,MAAM,uBAAO,IAAI,KAAa;EAC9B,MAAM,UAAqE,EAAE;AAC7E,OAAK,MAAM,SAAS,KAAK,qBAAqB;GAC1C,MAAM,UAAU,MAAM;AACtB,OAAI,CAAC,QAAQ,UAAU,MAAM,IAAI,KAAK,IAAI,QAAQ,SAAS,CAAE;AAC7D,QAAK,IAAI,QAAQ,SAAS;AAC1B,WAAQ,KAAK;IACT,UAAU,QAAQ;IAClB,OAAO,QAAQ;IACf,MAAM,QAAQ;IACjB,CAAC;;AAEN,SAAO;;CAGX,MAAM,YAAY,OAAY,mBAA4B;AACtD,MAAI,sBAAsB,KAAA,GAAW;GACjC,MAAM,QAAQ,KAAK,oBAAoB,MACnC,MAAK,EAAE,WAAW,aAAa,kBAClC;AACD,OAAI,OAAO;AACP,UAAM,KAAK,yBAAyB,MAAM;IAC1C,MAAM,SAAS,MAAM,MAAM,WAAW,OAAO,MAAM;AACnD,QAAI,OAAS,QAA8C,WAAW,MAAM,WAAW;AACvF,WAAO;;AAEX;;AAEJ,OAAK,IAAI,IAAI,GAAG,IAAI,KAAK,oBAAoB,QAAQ,KAAK;GACtD,MAAM,QAAQ,KAAK,oBAAoB;GACvC,MAAM,qBAAqB,MAAM;AACjC,OAAI,mBAAmB,UAAU,MAAM,EAAE;AACrC,UAAM,KAAK,yBAAyB,MAAM;IAC1C,MAAM,SAAS,MAAM,mBAAmB,OAAO,MAAM;AACrD,QAAI,OAAS,QAA8C,WAAW,mBAAmB;AACzF,WAAO;;;;CAKnB,gBAAkC;AAC9B,SAAO,SAAS,cAAc,cAAc,mBAAmB;;;;;;CAOnE,uBAA+B,aAAkC;AAC7D,MAAI,YAAY,gBAAgB,KAC5B,QAAO,YAAY,KAAK,SAAS;AAErC,SAAO,YAAY;;CAGvB,MAAM,WAAW,aAAgC,mBAA4B;AACzE,MAAI,CAAC,YACD;AAGJ,MAAI,EAAE,eAAe,aACjB,eAAc,MAAM,KAAK,YAAY,aAAa,kBAAkB;AAGxE,MAAI,CAAC,eAAe,EAAE,eAAe,aACjC;EAGJ,MAAM,WAAY,YAAwC,YAAkC;AAC5F,MAAI,SAAW,aAAwC,WAAW;AAElE,QAAM,KAAK,QAAQ;GACf,MAAM,YAAY;GAClB;GACA,OAAO,KAAK,uBAAuB,YAA2B;GAC9D,MAAM,YAAY;GAClB,UAAU;GACV,WAAW,YAAY;GAC1B,CAAoB;;CAGzB,MAAM,QAAQ,iBAAkC;EAC5C,MAAM,aAAa,KAAK,eAAe;AAEvC,MAAI,CAAC,YAAY;AACb,WAAQ,MAAM,2EAA2E;AACzF;;AAGJ,MAAI,WAAW,IAAI,gBAAgB,KAAK,EAAE;AACtC,cAAW,SAAS,gBAAgB,KAAK;AACzC;;AAGJ,aAAW,KAAK,gBAAgB;;CAGpC,YAAY,gBAAgC;EACxC,MAAM,YAAY,eAAe,SAAS,IAAI,GACxC,eAAe,MAAM,IAAI,CAAC,KAAK,EAAE,aAAa,IAAI,KAClD,eAAe,aAAa;EAElC,MAAM,sBAAsB,KAAK,4BAA4B;AAE7D,MAAI,oBAAoB,WAAW,EAC/B,QAAO;AAGX,OAAK,MAAM,gBAAgB,oBACvB,KAAI,aAAa,YAAY,aAAa,SAAS,WAC/C,QAAO,aAAa,SAAS;AAIrC,SAAO;;;AAIf,IAAa,iBAAiB,IAAI,gBAAgB;AAClD,YAAY,IAAI,kBAAkB,eAAe;AAEjD,qBAAqB,qBAAuC,gBAAgB;CACxE,OAAO;CACP,UAAU;EACN,OAAO;EACP,MAAM;EACN,OAAO;EACP,MAAM;EACN,OAAO;EACP,MAAM;EACN,OAAO;EACP,QAAQ;EACR,WAAW;EACX,MAAM;EACN,SAAS;EACT,QAAQ;EACR,OAAO;EACP,OAAO;EACP,QAAQ;EACR,QAAQ;EACR,OAAO;EACP,QAAQ;EACR,OAAO;EACP,OAAO;EACP,OAAO;EACP,OAAO;EACP,OAAO;EACP,QAAQ;EACR,OAAO;EACP,OAAO;EACP,OAAO;EACP,QAAQ;EACR,OAAO;EACP,OAAO;EACV;CACD,UAAU;CACb,CAAC;;;ACvRF,IAAa,sBAAsB,IAAc,OAAiB;AAC9D,KAAI,CAAC,GAAG,QAAQ,GAAG,KACf,QAAO;AAEX,KAAI,GAAG,QAAQ,CAAC,GAAG,KACf,QAAO;AAEX,QAAO,GAAG,MAAM,cAAc,GAAG,MAAM;;;;;ACJ3C,IAAM,WAAS,aAAa,mBAAmB;AAC/C,IAAM,MAAI,MAAM,KAAK,uBAAA,OAAA;CAAA,+BAAA,OAAA;CAAA,+BAAA,OAAA;CAAA,CAAuC,CAAC;AAE7D,IAAM,gCAAgC;AAM/B,IAAA,mBAAA,MAAM,yBAAyB,UAAU;;;;;;wBAInB;2BAK8D,EAAE;iBAEvE,WAAwB;sCACnB,IAAI,KAAe;6BAEZ;;;0BAZa;;;oCACU;;CAerD,aAAuB;AACnB,OAAK,qBAAqB;AAE1B,YAAU,+BAA+B,UAAmC;AACxE,OAAI,MAAM,WAAW,eACjB,MAAK,eAAe;IAE1B;AAEF,OAAK,UAAU,0BAA0B,iBAAwC,KAAK,mBAAmB,aAAa,CAAC;AACvH,OAAK,UAAU,4BAA4B,iBAAwC,KAAK,qBAAqB,aAAa,CAAC;;CAG/H,uBAAuB;AACnB,MAAI,KAAK,+BAA+B,KAAA,GAAW;AAC/C,gBAAa,KAAK,2BAA2B;AAC7C,QAAK,6BAA6B,KAAA;;AAEtC,OAAK,sBAAsB,KAAA;AAC3B,QAAM,sBAAsB;;CAGhC,aAAuB,mBAAqC;AACxD,QAAM,aAAa,kBAAkB;AACrC,OAAK,kBAAkB;;CAG3B,QAAkB,mBAAqC;AACnD,QAAM,QAAQ,kBAAkB;AAChC,MAAI,kBAAkB,IAAI,eAAe,IAAI,KAAK,aAC9C,MAAK,kBAAkB;;CAI/B,MAAc,sBAAsB;EAChC,MAAM,eAAe,MAAM,iBAAiB,cAAc;AAC1D,QAAM,KAAK,cAAc,gBAAgB,KAAA,EAAU;;CAGvD,gBAA0B;AACtB,SAAO,IAAI;uDACoC,IAAE,kBAAkB;yEACF,IAAE,iBAAiB;2DACjC,IAAE,WAAW;;;CAIpE,oBAA8B;EAC1B,MAAM,YAAY,sBAAsB,KAAK;EAC7C,MAAM,OAAO,qBAAqB,OAAO,YAAY;EACrD,MAAM,cAAc,QAAQ,KAAK,kBAAkB,SAAS;AAC5D,SAAO,IAAI;kEAC+C,IAAE,KAAK;cAC3D,cAAc,IAAI;;sBAEV,KAAK,eAAe,EAAE,MAAM,QAAQ,CAAC,CAAA;sBACrC,IAAE,UAAA;sBACF,KAAK,kBAAkB,KAAI,QAAO,IAAI;;;;oCAIxB,IAAI,QAAQ,OAAO;sCACjB;GAAE,MAAM,KAAM,kBAAkB;GAAE,UAAU,IAAI;GAAU,CAAC;8BACnE,IAAI,MAAA;;sBAEZ,CAAA;;gBAEN,QAAA;kFACkE,IAAE,WAAW;;;CAI3F,mBAAmB,cAAqC;AACpD,OAAK,sBAAsB;AAC3B,MAAI,KAAK,+BAA+B,KAAA,EACpC,cAAa,KAAK,2BAA2B;AAEjD,OAAK,6BAA6B,iBAAiB;AAC/C,QAAK,6BAA6B,KAAA;GAClC,MAAM,MAAM,KAAK;AACjB,QAAK,sBAAsB,KAAA;AAC3B,OAAI,IAAK,MAAK,qBAAqB,IAAI;OAClC,MAAK,cAAc,KAAA,GAAW,KAAK;KACzC,8BAA8B;;CAGrC,MAAc,qBAAqB,cAAyB;AACxD,wBAAsB,IAAI,KAAA,EAAU;AACpC,QAAM,KAAK,cAAc,cAAc,KAAK;AAC5C,QAAM,KAAK,mBAAmB;;CAGlC,MAAM,qBAAqB,cAAqC;AAC5D,wBAAsB,IAAI,KAAA,EAAU;AACpC,QAAM,KAAK,cAAc,cAAc,KAAK;;CAGhD,MAAM,cAAc,cAA0B,eAAe,OAAO;AAChE,OAAK,uBAAuB;EAC5B,MAAM,WAAW,KAAK;AACtB,OAAK,aAAa,OAAO;AACzB,OAAK,eAAe;AACpB,MAAI,CAAC,cAAc;AACf,QAAK,OAAO,KAAA;AACZ,OAAI,KAAK,eACL,OAAM,KAAK,oBAAoB,KAAK;AAExC;;EAEJ,MAAM,OAAO,MAAM,KAAK,mBAAmB,cAAc,MAAM,aAAa;AAC5E,MAAI,aAAa,KAAK,oBAClB;AAEJ,OAAK,OAAO;AACZ,QAAM,KAAK,8BAA8B;AACzC,MAAI,aAAa,KAAK,oBAClB;;CAIR,MAAc,oBAAoB,MAAqB;AACnD,QAAM,KAAK,iBAAiB;GACxB,GAAA,kBAAoB;sBACF,6BAA6B;GAClD,CAAC;;CAGN,MAAc,+BAA+B;AACzC,MAAI,KAAK,eACL;AAEJ,OAAK,iBAAiB;EAGtB,MAAM,gBADY,MAAM,KAAK,kBAAkB,IAC1B,kBAA6B;AAClD,MAAI,OAAO,iBAAiB,YAAY,aAAa,WAAW,EAC5D;AAGJ,QAAM,KAAK;EAEX,MAAM,OAAO,KAAK,QAAQ,OAAO,cAAc,UAAU;AACzD,MAAI,CAAC,KAAM;AAEX,MAAI,OAAO,iBAAiB,YAAY,aAAa,SAAS,GAAG;GAE7D,MAAM,QADQ,MAAM,KAAK,KAAK,iBAAiB,eAAe,CAAC,CAC3C,MAAM,SAAS;IAE/B,MAAM,QADO,MAAM,OAAO,OACP,oBAAoB;AACvC,WAAO,OAAO,SAAS,YAAY,SAAS;KAC9C;AACF,OAAI,OAAO;AACP,UAAM,KAAK,eAAe,MAAM;AAChC;;;AAIR,QAAM,KAAK,2BAA2B,KAAK;;CAG/C,MAAc,eAAe,MAAW;EACpC,IAAI,SAAU,KAAK,eAAsC,UAAU,eAAe;AAClF,SAAO,QAAQ;AACX,UAAO,WAAW;AAClB,YAAU,OAAO,eAAsC,UAAU,eAAe;;AAGpF,OAAK,WAAW;AAChB,QAAM,KAAK,mBAAmB;;CAGlC,MAAc,2BAA2B,MAAW;EAChD,MAAM,gBAAgB,MAAM,KAAK,KAAK,SAAS,CAAC,QAC3C,UAAU,iBAAiB,eAAe,MAAM,QAAQ,aAAa,KAAK,eAC9E;AACD,MAAI,cAAc,WAAW,EAAG;EAGhC,MAAM,eADkB,cAAc,MAAM,SAAS,MAAM,OAAO,gBAAgB,UAAU,IACpD,cAAc;AACtD,QAAM,KAAK,eAAe,aAAa;;CAG3C,MAAc,oBAAoB;AAC9B,QAAM,KAAK;EAGX,MAAM,iBAFS,KAAK,QAAQ,OAAO,cAAc,UAAU,GAE7B,iBAAiB,EAAE;AACjD,MAAI,cAAc,SAAS,EAEvB,uBAAsB,IAAI,cAAc,GAAG,OAAO,KAAK;;CAI/D,MAAM,mBAAmB,UAAoB,eAAe,OAAO,uBAAuB,OAA0B;EAChH,MAAM,WAAW,KAAK;EACtB,MAAM,SAAS,oBAAoB;EACnC,MAAM,OAAiB;GACnB,MAAM;GACN,OAAO,SAAS,SAAS;GACzB,MAAM;GACN,UAAU,EAAA;GACb;AAED,MAAI,oBAAoB,aAAa,CAAC,SAAS,WAAW,CAItD,KAAI;GACA,MAAM,OAAO,MAAM,iBAAiB,0BAA0B,SAAS;AACvE,OAAI,aAAa,KAAK,qBAAqB;AACvC,SAAK,SAAS,CAAC,KAAK;AACpB,WAAO;;AAEX,OAAI,MAAM,YACN,MAAK,eAAe,KAAK;WAExB,GAAG;AACR,YAAO,MAAM,8CAA8C,EAAE;;AAIrE,MAAI,oBAAoB,aAAa,cAAc;AAC/C,OAAI;IACA,MAAM,WAAW,MAAM,SAAS,aAAa,qBAAqB;AAClE,QAAI,aAAa,KAAK,qBAAqB;AACvC,UAAK,SAAS;AACd,YAAO;;AAEX,SAAK,MAAM,iBAAiB,UAAU;KAIlC,MAAM,QAAQ,MAAM,KAAK,mBAAmB,eAAe,MAAM,qBAAqB;AACtF,SAAI,aAAa,KAAK,qBAAqB;AACvC,WAAK,SAAS;AACd,aAAO;;AAEX,UAAK,SAAS,KAAK,MAAM;;AAE7B,SAAK,SAAS,KAAK,mBAAmB;YACjC,OAAO;AACZ,QAAI,aAAa,KAAK,qBAAqB;AACvC,UAAK,SAAS;AACd,YAAO;;AAEX,QAAI,CAAE,MAAM,iBAAiB,6BAA6B,SAAS,EAAG;AAClE,UAAK,SAAS;AACd,YAAO;;AAGX,SAAK,YADU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAErE,aAAO,MAAM,sCAAsC,MAAM;;AAI7D,QAAK,SAAS;;AAGlB,MAAI,oBAAoB,oCACpB,MAAK,oBAAoB,SAAS,kBAAkB;AAGxD,SAAO;;CAGX,gBAAgB,MAAgB,WAAW,OAAuB;AAC9D,MAAI,CAAC,KACD,QAAO,IAAI;EAMf,MAAM,SAAS,CAAC,KAAK,QAAQ,CAAC,KAAK;EACnC,MAAM,WAAW,KAAK;EACtB,MAAM,SAAS,oBAAoB;EACnC,MAAM,cAAc,CAAC,CAAC,SAAS,WAAW;EAC1C,MAAM,WAAW,SACX,eAAe,YAAY,SAAS,SAAS,CAAC,GAC7C,KAAK,QAAQ;EACpB,MAAM,eAAe,KAAK;EAC1B,MAAM,YAAY,KAAK;EACvB,MAAM,oBAAoB,KAAK;EAC/B,MAAM,YAAY,YACZ,IAAE,mBAAmB,EAAE,QAAQ,WAAW,CAAC,GAC3C,oBACE,IAAE,mBAAmB,EAAE,QAAQ,mBAAmB,CAAC,GACnD;AAER,SAAO,IAAI;;4BAES,YAAA;6BACC,cAAc,KAAK,UAAU,MAAa,KAAK,YAAY,GAAgB,SAAS,CAAC,GAAG,KAAA,EAAA;4BACzF,KAAK,SAAS,KAAK,oBAAoB,CAAA;gCACnC,KAAK,UAAU,MAAa,KAAK,WAAW,GAAG,KAAK,CAAC,CAAA;yBAC5D,KAAK;4BACF,SAAA;wBACJ,OAAO;;;;8BAID,KAAK,UAAU,EAAE,OAAO,KAAK,OAAO,IAAE,OAAO,IAAE,QAAQ,CAAC,CAAA;4DAC1B,KAAK,MAAM;8BACzC,CAAC,KAAK,QAAQ,eACV,IAAI,gGAAgG,aAAa,eACjH,KAAA;;;sBAGZ,YACI,IAAI,0DAA0D,UAAU,UACxE,QAAA;;kBAER,KAAK,SAAS,KAAI,UAAS,KAAK,gBAAgB,OAAO,MAAM,CAAC,CAAA;;;CAI5E,YAAoB,GAAc,UAAoB;AAClD,MAAI,CAAC,EAAE,aAAc;AAGrB,MAAI,CAAC,SAAS,WAAW,CAAE;EAG3B,MAAM,OADgB,EAAE,eACI,QAAQ,UAAU;EAE9C,MAAM,gBAA6C,MAAM,QAAQ,MAAM,cAAc,GAC/E,KAAK,gBACL,EAAE;EAER,MAAM,YAAwB,EAAE;AAEhC,MAAI,cAAc,SAAS,EACvB,MAAK,MAAM,QAAQ,eAAe;GAE9B,MAAM,OADO,KAAK,OACC;AACnB,OAAI,QAAQ,KAAK,WAAW,CACxB,WAAU,KAAK,KAAK;;AAKhC,MAAI,UAAU,WAAW,EACrB,WAAU,KAAK,SAAS;EAG5B,MAAM,iBAAiB,UAAU,KAAI,MAAK,EAAE,kBAAkB,CAAC;EAC/D,MAAM,cAAc,UAAU,WAAW,IAAI,UAAU,GAAG,SAAS,GAAG,GAAG,UAAU,OAAO;AAE1F,IAAE,aAAa,gBAAgB;EAC/B,MAAM,UAAU,eAAe,KAAK,KAAK;AAEzC,IAAE,aAAa,QAAQ,cAAc,QAAQ;AAC7C,IAAE,aAAa,QAAQ,gCAAgC,QAAQ;AAC/D,IAAE,aAAa,QAAQ,iBAAiB,QAAQ;AAEhD,MAAI,EAAE,aAAa,cAAc;GAC7B,MAAM,YAAY,SAAS,cAAc,MAAM;AAC/C,aAAU,cAAc;AACxB,aAAU,MAAM,WAAW;AAC3B,aAAU,MAAM,MAAM;AACtB,aAAU,MAAM,UAAU;AAC1B,aAAU,MAAM,aAAa;AAC7B,aAAU,MAAM,SAAS;AACzB,aAAU,MAAM,eAAe;AAC/B,YAAS,KAAK,YAAY,UAAU;AACpC,KAAE,aAAa,aAAa,WAAW,GAAG,EAAE;AAC5C,oBAAiB,SAAS,KAAK,YAAY,UAAU,EAAE,EAAE;;;CAIjE,MAAc,WAAW,OAAc,MAAgB;EACnD,MAAM,WAAW,KAAK;AACtB,MAAI,oBAAoB,aAAa,KAAK,SAAS,WAAW,EAC1D,OAAM,KAAK,iBAAiB,MAAM,SAAS;;CAInD,MAAc,iBAAiB,MAAgB,UAAqB;AAChE,MAAI,KAAK,aAAa,IAAI,KAAK,CAC3B;EAGJ,MAAM,WAAW,KAAK;AACtB,OAAK,aAAa,IAAI,KAAK;AAC3B,MAAI;GACA,MAAM,WAAW,MAAM,SAAS,aAAa,MAAM;AACnD,OAAI,aAAa,KAAK,oBAClB;AAEJ,QAAK,MAAM,iBAAiB,UAAU;IAIlC,MAAM,QAAQ,MAAM,KAAK,mBAAmB,eAAe,MAAM;AACjE,QAAI,aAAa,KAAK,oBAClB;AAEJ,SAAK,SAAS,KAAK,MAAM;;AAE7B,QAAK,SAAS,KAAK,mBAAmB;AAGtC,QAAK,SAAS;AACd,QAAK,eAAe;WACf,OAAO;AACZ,OAAI,aAAa,KAAK,oBAClB;AAEJ,OAAI,CAAE,MAAM,iBAAiB,6BAA6B,SAAS,EAAG;AAClE,SAAK,SAAS;AACd,SAAK,eAAe;AACpB;;AAGJ,QAAK,YADU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAErE,YAAO,MAAM,sCAAsC,MAAM;AACzD,QAAK,eAAe;YACd;AACN,QAAK,aAAa,OAAO,KAAK;;;CAItC,MAAM,oBAAoB,OAAc;EACpC,MAAM,OAAO,MAAM;EACnB,MAAM,OAAO,KAAK;AAClB,MAAI,CAAC,KACD;EAGJ,MAAM,WAAW,KAAK;AACtB,MAAI,oBAAoB,MAAM;AAC1B,yBAAsB,IAAI,SAAS;AAC9B,QAAK,eAAe,eAAe,EAAE,CAAC;AAC3C;;AAGJ,MAAI,CAAC,KAAK,QAAQ,cAAc,KAC5B,MAAK,WAAW,CAAC,KAAK;;CAI9B,mBAAmB,OAAc;EAE7B,MAAM,YAAY,MAAM,OAAO;AAC/B,MAAI,aAAa,UAAU,SAAS,GAAG;GAEnC,MAAM,OADiB,UAAU,GAAG,MAClB;AAClB,yBAAsB,IAAI,KAAK;GAE/B,MAAM,OADW,MACM,oBAAoB;AAC3C,OAAI,OAAO,SAAS,SAChB,MAAK,oBAAoB,KAAK;OAE9B,MAAK,oBAAoB,KAAK;AAElC,OAAI,gBAAgB,KAChB,MAAK,oBAAoB,eAAe,yBAAyB,KAAK;OAEtE,MAAK,oBAAoB,EAAE;SAE5B;AACH,yBAAsB,IAAI,KAAA,EAAU;AACpC,QAAK,oBAAoB,KAAK;AAC9B,QAAK,oBAAoB,EAAE;;;CAMnC,gCAAwC,GAAqC;AACzE,MAAI,CAAC,KAAK,aAAc,QAAO,KAAA;EAG/B,MAAM,WADS,EAAE,OACO,QAAQ,eAAe;AAC/C,MAAI,CAAC,UAAU;GACX,MAAM,iBAAiB,KAAK,MAAM,YAAY,EAAE;AAChD,OAAI,eAAe,WAAW,EAC1B;GAEJ,MAAM,qBAAqB,eAAe,IAAI;AAC9C,UAAO,8BAA8B,YAAY,qBAAqB,KAAA;;EAI1E,MAAM,WAD8B,SAA+B,OAC5C;AACvB,MAAI,oBAAoB,UACpB,QAAO;;CAKf,mBAA2B;EACvB,MAAM,cAAc,KAAK,QAAQ;AACjC,MAAI,CAAC,YAAa;EAElB,MAAM,mBAAmB,MAAiB;GACtC,MAAM,QAAQ,EAAE,cAAc;AAC9B,OAAI,CAAC,MAAO;GAEZ,MAAM,eAAe,MAAM,SAAS,QAAQ;GAC5C,MAAM,kBAAkB,MAAM,SAAS,+BAA+B;AACtE,OAAI,CAAC,gBAAgB,CAAC,gBAAiB;AAGvC,OAAI,CADc,KAAK,gCAAgC,EAAE,EACzC;AACZ,SAAK,mBAAmB,UAAU,OAAO,cAAc;AACvD,SAAK,oBAAoB,KAAA;AACzB,gBAAY,UAAU,OAAO,YAAY;AACzC;;AAGJ,KAAE,gBAAgB;AAClB,OAAI,EAAE,aACF,KAAI,gBACA,GAAE,aAAa,aAAc,EAAE,WAAW,EAAE,UAAW,SAAS;OAEhE,GAAE,aAAa,aAAa;AAIpC,eAAY,UAAU,IAAI,YAAY;GAGtC,MAAM,WADS,EAAE,OACO,QAAQ,eAAe;AAE/C,OAAI,CAAC,UAAU;AACX,SAAK,mBAAmB,UAAU,OAAO,cAAc;AACvD,SAAK,oBAAoB,KAAA;AACzB;;AAGJ,OAAI,aAAa,KAAK,mBAAmB;AACrC,SAAK,mBAAmB,UAAU,OAAO,cAAc;AACvD,SAAK,oBAAoB;AACzB,aAAS,UAAU,IAAI,cAAc;;;EAI7C,MAAM,oBAAoB,MAAiB;GACvC,MAAM,QAAQ,EAAE,cAAc;AAC9B,OAAI,CAAC,MAAO;GAEZ,MAAM,eAAe,MAAM,SAAS,QAAQ;GAC5C,MAAM,kBAAkB,MAAM,SAAS,+BAA+B;AACtE,OAAI,CAAC,gBAAgB,CAAC,gBAAiB;AAGvC,OAAI,CADc,KAAK,gCAAgC,EAAE,CACzC;AAEhB,KAAE,gBAAgB;AAClB,eAAY,UAAU,IAAI,YAAY;;EAG1C,MAAM,oBAAoB,MAAiB;GACvC,MAAM,OAAO,YAAY,uBAAuB;GAChD,MAAM,IAAI,EAAE;GACZ,MAAM,IAAI,EAAE;AAEZ,OAAI,KAAK,KAAK,QAAQ,KAAK,KAAK,SAAS,KAAK,KAAK,OAAO,KAAK,KAAK,QAAQ;AACxE,gBAAY,UAAU,OAAO,YAAY;AACzC,SAAK,mBAAmB,UAAU,OAAO,cAAc;AACvD,SAAK,oBAAoB,KAAA;;;EAIjC,MAAM,cAAc,OAAO,MAAiB;AACxC,KAAE,gBAAgB;AAClB,eAAY,UAAU,OAAO,YAAY;AACzC,QAAK,mBAAmB,UAAU,OAAO,cAAc;AACvD,QAAK,oBAAoB,KAAA;AAEzB,OAAI,CAAC,EAAE,gBAAgB,CAAC,KAAK,aAAc;GAE3C,MAAM,YAAY,KAAK,gCAAgC,EAAE;AACzD,OAAI,CAAC,UAAW;GAChB,MAAM,QAAQ,EAAE,aAAa;AAE7B,OAAI,MAAM,SAAS,QAAQ,EAAE;IACzB,MAAM,QAAQ,MAAM,KAAK,EAAE,aAAa,MAAM;AAC9C,QAAI,MAAM,WAAW,EAAG;AACxB,UAAM,KAAK,gBAAgB,OAAO,UAAU;AAC5C;;AAGJ,OAAI,MAAM,SAAS,+BAA+B,EAAE;AAChD,UAAM,KAAK,oBAAoB,GAAG,UAAU;AAC5C;;;AAIR,cAAY,oBAAoB,YAAY,gBAAuB;AACnE,cAAY,oBAAoB,aAAa,iBAAwB;AACrE,cAAY,oBAAoB,aAAa,iBAAwB;AACrE,cAAY,oBAAoB,QAAQ,YAAmB;AAE3D,cAAY,iBAAiB,YAAY,gBAAgB;AACzD,cAAY,iBAAiB,aAAa,iBAAiB;AAC3D,cAAY,iBAAiB,aAAa,iBAAiB;AAC3D,cAAY,iBAAiB,QAAQ,YAAY;;CAGrD,MAAc,oBAAoB,GAAc,WAAsB;AAClE,MAAI,CAAC,EAAE,aAAc;EAErB,MAAM,UAAU,EAAE,aAAa,QAAQ,+BAA+B;AACtE,MAAI,CAAC,QAAS;EAEd,MAAM,QAAQ,QACT,MAAM,QAAQ,CACd,KAAI,MAAK,EAAE,MAAM,CAAC,CAClB,QAAO,MAAK,CAAC,CAAC,EAAE;AAErB,MAAI,MAAM,WAAW,EAAG;EAExB,MAAM,YAAY,MAAM,iBAAiB,cAAc;AACvD,MAAI,CAAC,WAAW;AACZ,YAAO,KAAK,2DAA2D;AACvE;;EAGJ,MAAM,wBAAwB,OAAO,QAAoC;GACrE,MAAM,UAAU,IAAI,cAAc;GAClC,MAAM,WAAW,UAAU,cAAc;AACzC,OAAI,CAAC,WAAW,CAAC,SAAU,QAAO;AAGlC,UAAO,YAAY,YAAY,EAAE,EAAE,WAAW,EAAE;;EAGpD,MAAM,2BAAW,IAAI,KAAgB;EACrC,MAAM,WAAW,UAAU,cAAc;EAEzC,IAAI,YAAY;EAChB,IAAI,SAAS;EAEb,MAAM,UAAkD,EAAE;AAE1D,OAAK,MAAM,QAAQ,MACf,KAAI;GACA,MAAM,MAAM,MAAM,UAAU,YAAY,KAAK;AAC7C,OAAI,CAAC,KAAK;AACN,aAAO,KAAK,8CAA8C,KAAK,GAAG;AAClE;AACA;;AAGJ,WAAQ,KAAK;IAAE;IAAM,UAAU;IAAK,CAAC;GACrC,MAAM,OAAO,IAAI,cAAc;AAC/B,OAAI,KACA,UAAS,IAAI,KAAK;WAEjB,OAAO;AACZ,YAAO,MAAM,wCAAwC,KAAK,KAAK,MAAM;AACrE;;AAIR,MAAI,QAAQ,WAAW,GAAG;AACtB,OAAI,SAAS,EACT,UAAO,KAAK,6BAA6B,OAAO,UAAU;AAE9D;;EAGJ,IAAI,oBAAoB;AACxB,MAAI;QACK,MAAM,QAAQ,SACf,KAAI,SAAS,UAAU;AACnB,wBAAoB;AACpB;;;AAKZ,MAAI,qBAAqB,SACrB,KAAI;GACA,MAAM,gBAAgB,MAAM,KAAK,SAAS;GAC1C,MAAM,UAAU,MAAM,iBAAiB,0BACnC,cAAc,GACjB;GACD,MAAM,WAAW,MAAM,iBAAiB,0BAA0B,SAAS;GAC3E,MAAM,aAAa,SAAS,eAAe,IAAE;GAC7C,MAAM,cAAc,UAAU,eAAe,IAAE;AAO/C,OAAI,CALc,MAAM,cAAc,IAAE,6BAA6B;IACjE,OAAO,OAAO,QAAQ,OAAO;IAC7B;IACA;IACH,CAAC,CAAC,CAEC;WAEC,KAAK;AACV,YAAO,MAAM,mDAAmD,IAAI;;AAI5E,OAAK,MAAM,EAAE,MAAM,cAAc,QAC7B,KAAI;GACA,MAAM,OAAO,MAAM,sBAAsB,SAAS;AAClD,SAAM,iBAAiB,aAAa,UAAU,WAAW,EAAE,MAAM,CAAC;AAClE;WACK,OAAO;AACZ,YAAO,MAAM,wCAAwC,KAAK,KAAK,MAAM;AACrE;;AAIR,WAAO,KACH,6BAA6B,UAAU,GAAG,QAAQ,OAAO,SAAS,SAAS,IAAI,KAAK,OAAO,WAAW,KACzG;AAED,QAAM,KAAK,cAAc,KAAK,cAAc,KAAK;;CAGrD,MAAc,gBAAgB,OAA0B,WAAsB;EAC1E,MAAM,QAAQ,MAAM;EACpB,IAAI,YAAY;EAChB,IAAI,SAAS;EACb,IAAI,UAAU;AAEV,OAAK,MAAM,QAAQ,MACnB,KAAI;GACA,MAAM,aAAa,KAAK,gBAAgB,WAAW,KAAK,KAAK;AAG7D,OADqB,MAAM,KAAK,aAAc,YAAY,WAAW;QAG7D,CADc,MAAM,cAAc,IAAE,sBAAsB,EAAE,UAAU,KAAK,MAAM,CAAC,CAAC,EACvE;AACZ;AACA;;;AASR,UALsB,MAAM,KAAK,aAAc,YAC3C,YACA,EAAE,QAAQ,MAAM,CACnB,EAEmB,aAAa,KAAK;AAEtC;WACK,OAAO;AACZ,YAAO,MAAM,oBAAoB,KAAK,KAAK,IAAI,MAAM;AACrD;;AAIR,WAAO,KAAK,YAAY,UAAU,GAAG,MAAM,QAAQ,UAAU,IAAI,KAAK,QAAQ,YAAY,KAAK,SAAS,IAAI,KAAK,OAAO,WAAW,KAAK;AAExI,QAAM,KAAK,cAAc,KAAK,aAAa;;CAG/C,gBAAwB,WAAsB,UAA0B;EACpE,MAAM,UAAU,UAAU,kBAAkB;AAC5C,SAAO,UAAU,GAAG,QAAQ,GAAG,aAAa;;CAGhD,gBAA0B;AACtB,SAAO,IAAI;gCACa,IAAI,KAAK,QAAQ,CAAC,8BAA8B,IAAE,gBAAgB;kBAChF,KAAK,CAAC,KAAK,oBAAoB,IAAI;iDACJ,IAAE,iBAAiB,8BAA8B,KAAK,KAAK,YAAY,IAAI;gDAC5E,KAAK,SAAS,KAAK,mBAAmB,CAAA;;sBAEhE,KAAK,KAAM,SAAS,KAAI,UAAS,KAAK,gBAAgB,OAAO,KAAK,CAAC,CAAA;mCACtD,IAAI,GAAG,CAAC,CAAA;;;;;gBAKvB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WA/wBlB,OAAO,CAAA,EAAA,iBAAA,WAAA,QAAA,KAAA,EAAA;WAEP,OAAO,CAAA,EAAA,iBAAA,WAAA,qBAAA,KAAA,EAAA;kDATX,cAAc,oBAAoB,CAAA,EAAA,iBAAA;;;AC1BnC,IAAM,MAAI,MAAM,KAAK,uBAAA,OAAA;CAAA,yBAAA,OAAA;CAAA,yBAAA,OAAA;CAAA,CAAiC,CAAC;AAEvD,qBAAqB,qBAAqB,uBAAuB,EAC7D,WAAW,+BACd,CAAqB;AAGtB,IAAI,0BAA8C;AAElD,SAAS,6BAA0C;AAC/C,KAAI,CAAC,yBAAyB;AAC1B,4BAA0B,SAAS,cAAc,MAAM;AACvD,0BAAwB,KAAK;AAC7B,WAAS,KAAK,YAAY,wBAAwB;;AAEtD,QAAO;;AAGX,SAAS,mBAAwB;AAE7B,QADkB,4BAA4B,CAC7B,cAAc,YAAY;;AAG/C,SAAS,qBAAqB;AAC1B,sBAAqB,KAAK;;AAG9B,SAAS,qBAAqB,YAAY,OAAO;CAC7C,MAAM,YAAY,4BAA4B;CAC9C,MAAM,QAAQ,YAAY,gBAAgB;AAG1C,KAFyB,MAAM,WAEN,GAAG;AACxB,SAAO,IAAI,IAAI,UAAU;AACzB;;CAIJ,MAAM,iBAAiB,kBAAkB;AAKzC,KAAI,EAJW,aAAc,gBAAgB,SAAS,MAKlD;CAGJ,MAAM,oBAAoB;EAEtB,MAAM,SAAS,kBAAkB;AACjC,MAAI,OACA,QAAO,OAAO;;CAItB,MAAM,wBAAwB;AAE1B,SAAO,IAAI,IAAI,UAAU;;AA2H7B,QAxHiB,IAAI;;qBAEJ,IAAE,aAAa;;;;gCAIJ,YAAA;6BACH,gBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA4EX,MAAM,KAAK,iBAAkC;EAC3C,MAAM,cAAc,aAAa,YAAY,KAAK,aAAa,aAAa;EAC5E,MAAM,WAAW,aAAa,YAAY,IACpC,aAAa,WACZ,aAAa,aAAa,IACvB,KAAK,MAAO,aAAa,cAAc,aAAa,aAAc,IAAI,GACtE;EAEV,MAAM,YAAY,aAAa,WAAW,KAAK,aAAa,aAAa;AAEzE,SAAO,IAAI;;;;;2DAK4B,aAAa,KAAK;sCACvC,aAAa,UAAU,IAAI;kEACC,aAAa,QAAQ;wCAC/C,GAAA;;;;kCAIN,cAAc,IAAI;8DACU,SAAS;0CAC7B,YAAY,GAAG,aAAa,YAAY,GAAG,aAAa,WAAW,OAAO,KAAK,SAAS;;oCAE9F,IAAI;;;;;;GAMtB,CAAA;;;OAKG,UAAU;;AAIxB,IAAA,aAAA,MAAM,mBAAmB,aAAa;;gBACzB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0CnB,aAAuB;AACnB,OAAK,MAAM,yBAAyB;AAEhC,yBAAsB;AACtB,QAAK,eAAe;IACtB;;CAGN,uBAA+B;AAC3B,sBAAoB;;CAGxB,SAAmB;AACf,oBAAkB,KAAK;EAEvB,MAAM,YADQ,YAAY,gBAAgB,CAClB;AAExB,MAAI,cAAc,EACd,QAAO,IAAI;AAGf,SAAO,IAAI;+CAC4B,KAAK,qBAAqB,UAAU,IAAE,mBAAmB,EAAE,WAAW,UAAU,UAAU,EAAE,CAAC,CAAC;;;6BAGhH,IAAE,aAAa;;yEAE6B,UAAU;;;;;;wBAvElF,cAAc,cAAc,CAAA,EAAA,WAAA;;;AC3L7B,IAAM,MAAI,MAAM,KAAK,uBAAA,OAAA;CAAA,4BAAA,OAAA;CAAA,4BAAA,OAAA;CAAA,CAAoC,CAAC;;;;AAK1D,SAAgB,2BAAmC;CACjD,MAAM,aAAa,iBAAiB,KAAK;AACzC,KAAI,CAAC,WACH,QAAO,IAAE;AAEX,QAAO,WAAW,iBAAiB,SAAS,WAAW,aAAa,KAAK,IAAI,IAAE;;;AAIjF,IAAM,oBAAoB;AAE1B,IAAI,qBAA2D;AAE/D,SAAS,qBAA2B;CAClC,MAAM,UAAU,iBAAiB,eAAe,EAAE,QAAQ;CAC1D,MAAM,aAAa,iBAAiB,KAAK;AACzC,KAAI,CAAC,YAAY;AACf,WAAS,QAAQ;AACjB;;CAEF,MAAM,OACJ,WAAW,iBAAiB,SAAS,WAAW,aAAa,KAAK,IAAI,IAAE;AAE1E,KAAI,QACF,UAAS,QAAQ,GAAG,QAAQ,KAAK;KAEjC,UAAS,QAAQ;;AAIrB,SAAS,6BAAmC;AAC1C,KAAI,uBAAuB,KACzB,cAAa,mBAAmB;AAElC,sBAAqB,iBAAiB;AACpC,uBAAqB;AACrB,sBAAoB;IACnB,kBAAkB;;AAGvB,YAAY,wBAAwB,4BAA4B,CAAC;AAEjE,OAAO,iBAAiB,oBAAoB;AAC1C,KAAI,uBAAuB,MAAM;AAC/B,eAAa,mBAAmB;AAChC,uBAAqB;;AAEvB,qBAAoB;EACpB;;;AChDF,IAAM,MAAI,MAAM,KAAK,uBAAA,OAAA;CAAA,4BAAA,OAAA;CAAA,4BAAA,OAAA;CAAA,CAAoC,CAAC;AAE1D,qBAAqB,qBAAqB,uBAAuB,EAC7D,WAAW,uCACd,CAAqB;AAGf,IAAA,gBAAA,MAAM,sBAAsB,aAAa;CAC5C,aAAuB;AACnB,OAAK,MAAM,wBAAwB;AAC/B,QAAK,eAAe;IACtB;;CAGN,SAAmB;EAEf,MAAM,WADa,iBAAiB,KAAK,EACZ,iBAAiB,QAAQ;AAEtD,SAAO,IAAI;;;;yBAIM,IAAE,YAAY;kBACrB,KAAK,UAAU;GAAE,OAAO;GAAQ,MAAM;GAAS,CAAC,CAAA;kBAChD,0BAA0B,CAAA;;;;;2BAlB3C,cAAc,kBAAkB,CAAA,EAAA,cAAA;;;ACDjC,IAAM,SAAS,aAAa,kBAAkB;AAE9C,IAAM,MAAI,MAAM,KAAK,uBAAA,OAAA;CAAA,8BAAA,OAAA;CAAA,8BAAA,OAAA;CAAA,CAAsC,CAAC;AAIrD,IAAA,kBAAA,MAAM,wBAAwB,UAAU;;;oBAKd;4BAGS;+BAGc,EAAE;;CAItD,WAAqB;AACjB,YAAU,gCAAgC;AACtC,QAAK,eAAe;IACtB;;CAGN,sBAAsB;CAItB,OAAO,WAAsB;AACzB,oBAAkB,OAAO,UAAU,IAAI,KAAK;AAC5C,OAAK,eAAe;;CAGxB,QAAQ,WAAsB;AAC1B,oBAAkB,QAAQ,UAAU,IAAI,KAAK;AAC7C,OAAK,eAAe;;CAIxB,oBAA4B,aAA8B;EACtD,MAAM,aAAa,iBAAiB,eAAe;AACnD,MAAI,CAAC,cAAc,CAAC,WAAW,WAC3B,QAAO;AAEX,SAAO,WAAW,WAAW,SAAS,YAAY;;CAGtD,iBAAiB,GAAgB;EAC7B,MAAM,YAAY,EAAE,OAAO,aAAa,EAAE;AAC1C,MAAI,UAAU,SAAS,KAAK,UAAU,GAAG,MAErC,MAAK,oBAAoB,UAAU,GAAG;MAEtC,MAAK,oBAAoB,KAAA;;CAIjC,wBAA6C;AACzC,MAAI,CAAC,KAAK,WAAW,MAAM,CACvB,QAAO,kBAAkB,eAAe;EAE5C,MAAM,SAAS,KAAK,WAAW,aAAa;AAC5C,SAAO,kBAAkB,eAAe,CAAC,QAAO,QAAO;AACnD,UAAO,OAAO,IAAI,KAAK,CAAC,aAAa,CAAC,SAAS,OAAO,KAC9C,IAAI,cAAc,OAAO,IAAI,YAAY,CAAC,aAAa,CAAC,SAAS,OAAO,GAAG,UAC5E,IAAI,GAAG,aAAa,CAAC,SAAS,OAAO;IAC9C;;CAIN,uBAAiF;EAC7E,MAAM,WAAW,KAAK,uBAAuB;EAC7C,MAAM,UAAuB,EAAE;EAC/B,MAAM,YAAyB,EAAE;AAEjC,WAAS,SAAQ,QAAO;AACpB,OAAI,kBAAkB,UAAU,IAAI,GAAG,CACnC,SAAQ,KAAK,IAAI;OAEjB,WAAU,KAAK,IAAI;IAEzB;AAEF,UAAQ,MAAM,GAAG,MAAM,OAAO,EAAE,KAAK,CAAC,cAAc,OAAO,EAAE,KAAK,CAAC,CAAC;AACpE,YAAU,MAAM,GAAG,MAAM,OAAO,EAAE,KAAK,CAAC,cAAc,OAAO,EAAE,KAAK,CAAC,CAAC;AAEtE,SAAO;GAAE;GAAS;GAAW;;CAGjC,oBAA4B,WAA+B;AACvD,SAAO,UAAU,aAAa;;CAIlC,kBAA0B,GAAU;AAChC,OAAK,aAAc,EAAE,OAA4B;AACjD,OAAK,eAAe;;CAGxB,cAAsB;AAClB,OAAK,aAAa;AAClB,OAAK,eAAe;;CAGxB,MAAc,0BAA0B;AACpC,MAAI;GACA,MAAM,MAAM,MAAM,aAAa,6CAA6C,IAAI,MAAM;AACtF,OAAI,CAAC,IACD;AAGJ,SAAM,YAAY,SAAS,yBAAyB,YAAY;IAC5D,IAAI,WAAW;AAEf,QAAI,aAAa,YAAY,IAAI,CAC7B,YAAW,aAAa,yBAAyB,IAAI;IAGzD,MAAM,SAAS,aAAa,YAAY,SAAS;AAEjD,QAAI,QAAQ,SAAS,SACjB,OAAM,KAAK,oBAAoB,QAAQ,SAAS;SAC7C;AACH,UAAK,wBAAwB;MACzB,KAAK;MACL,IAAI;MACJ,MAAM;MACN,aAAa;MAChB;AACD,UAAK,qBAAqB;AAC1B,UAAK,eAAe;;KAE1B;WACG,OAAO;AACZ,cAAW,iCAAiC,QAAQ;;;CAI5D,MAAc,oBAAoB,QAAqB,KAAa;AAChE,MAAI;GACA,MAAM,cAAc,MAAM,aAAa,uBAAuB,OAAO;GAErE,MAAM,QAAQ,OAAO;GACrB,MAAM,OAAO,OAAO;AAOpB,QAAK,wBAAwB;IACzB,IAPgB,YAAY,QAAQ,OAAO,MAAM,GAAG;IAQpD,MAPkB,YAAY,QAAQ,GAAG,MAAM,GAAG;IAQrC,aAPG,YAAY,eAAe;IAQtC;IACI,SARG,YAAY,WAAW;IAS3B,QARG,YAAY,WAAW,OAAO,YAAY,WAAW,WAAW,YAAY,SAAS,YAAY,QAAQ,SAAS;IAS7H,MAAM;IACN,UAAU;IACb;AAED,QAAK,qBAAqB;AAC1B,QAAK,eAAe;WACf,OAAO;AACZ,UAAO,KAAK,iDAAiD,QAAQ;AACrE,QAAK,wBAAwB;IACpB;IACL,IAAI;IACJ,MAAM;IACN,aAAa;IAChB;AACD,QAAK,qBAAqB;AAC1B,QAAK,eAAe;;;CAI5B,MAAc,2BAA2B;AACrC,MAAI,CAAC,KAAK,sBAAsB,KAAK;AACjC,cAAW,kBAAkB;AAC7B;;AAGJ,MAAI,CAAC,KAAK,sBAAsB,IAAI;AAChC,cAAW,2BAA2B;AACtC;;AAGJ,MAAI,CAAC,KAAK,sBAAsB,MAAM;AAClC,cAAW,6BAA6B;AACxC;;AAGJ,MAAI;AACA,SAAM,YAAY,SAAS,yBAAyB,YAAY;IAC5D,MAAM,YAAuB;KACzB,IAAI,KAAK,sBAAsB;KAC/B,MAAM,KAAK,sBAAsB;KACjC,aAAa,KAAK,sBAAsB;KACxC,KAAK,KAAK,sBAAsB;KAChC,SAAS,KAAK,sBAAsB;KACpC,QAAQ,KAAK,sBAAsB;KACnC,MAAM,KAAK,sBAAsB,QAAQ;KACzC,UAAU;KACb;AAED,sBAAkB,kBAAkB,UAAU;AAC9C,UAAM,kBAAkB,qBAAqB,KAAK,sBAAsB,KAAM,UAAU,GAAG;AAE3F,cAAU,aAAa,UAAU,KAAK,0BAA0B;AAChE,SAAK,qBAAqB;AAC1B,SAAK,wBAAwB,EAAE;AAC/B,SAAK,eAAe;KACtB;WACG,OAAO;AACZ,cAAW,iCAAiC,QAAQ;;;CAI5D,0BAAkC;AAC9B,OAAK,qBAAqB;AAC1B,OAAK,wBAAwB,EAAE;AAC/B,OAAK,eAAe;;CAGxB,gBAA0B;AACtB,SAAO,IAAI;;+BAEY,IAAE,mBAAmB;yBAC3B,KAAK,WAAA;0BACJ,MAAa,KAAK,kBAAkB,EAAE,CAAA;kCAC9B,KAAK,aAAa,CAAA;;;;;;;;;+BASrB,KAAK,yBAAyB,CAAA;;;;;;;CAQzD,gBAA0B;EACtB,MAAM,UAAU,KAAK,sBAAsB;EAC3C,MAAM,mBAAmB,QAAQ,QAAQ,SAAS,KAAK,QAAQ,UAAU,SAAS;AAElF,SAAO,IAAI;cACL,KAAK,KAAK,0BAA0B,IAAI;;;;8CAIR,KAAK,yBAAyB,CAAA;;;;;qCAKvC,KAAK,sBAAsB,MAAM,GAAA;sCAChC,MAAa;AACnB,QAAK,sBAAsB,KAAM,EAAE,OAA4B;AAC/D,QAAK,eAAe;;;;;;;;qCAQf,KAAK,sBAAsB,QAAQ,GAAA;sCAClC,MAAa;AACnB,QAAK,sBAAsB,OAAQ,EAAE,OAA4B;AACjE,QAAK,eAAe;;;;;;;;qCAQf,KAAK,sBAAsB,eAAe,GAAA;sCACzC,MAAa;AACnB,QAAK,sBAAsB,cAAe,EAAE,OAA4B;AACxE,QAAK,eAAe;;;;;;;qCAOf,KAAK,sBAAsB,OAAO,GAAA;sCACjC,MAAa;AACnB,QAAK,sBAAsB,MAAO,EAAE,OAA4B;AAChE,QAAK,eAAe;;;;;;;;;;yCAUX,KAAK,sBAAsB,WAAW,GAAA;0CACrC,MAAa;AACnB,QAAK,sBAAsB,UAAW,EAAE,OAA4B;AACpE,QAAK,eAAe;;;;;;;;yCAQf,KAAK,sBAAsB,UAAU,GAAA;0CACpC,MAAa;AACnB,QAAK,sBAAsB,SAAU,EAAE,OAA4B;AACnE,QAAK,eAAe;;;;;;;;;qCASnB,KAAK,sBAAsB,QAAQ,eAAA;sCAClC,MAAa;AACnB,QAAK,sBAAsB,OAAQ,EAAE,OAA4B;AACjE,QAAK,eAAe;;;;;;;;+CAQL,KAAK,yBAAyB,CAAC;;;;;+CAK/B,KAAK,0BAA0B,CAAA;4CAClC,CAAC,KAAK,sBAAsB,MAAM,CAAC,KAAK,sBAAsB,QAAQ,CAAC,KAAK,sBAAsB,IAAI;;;;;;cAMpI,CAAA;;;;;;;oDAOsC,KAAK,iBAAiB;8BAC5C,mBAAmB,IAAI;kCACnB,QAAQ,QAAQ,SAAS,IAAI,IAAI;;;;8CAIrB,IAAE,UAAU,IAAI,QAAQ,QAAQ,OAAO;;0CAE3C,QAAQ,QAAQ,KAAI,MAAK;GACvB,MAAM,aAAa,KAAK,oBAAoB,EAAE;AAC9C,UAAO,IAAI;0EACmB,KAAK,SAAS,KAAK,oBAAoB,CAAC,UAAU,EAAE;4DAClE,KAAK,EAAE,KAAK,CAAC,UAAU,EAAE,OAAO,aAAa,IAAI,0FAA0F,GAAA;;;IAG7J,CAAA;;oCAEN,GAAA;kCACF,QAAQ,UAAU,SAAS,IAAI,IAAI;;;;8CAIvB,IAAE,UAAU,IAAI,QAAQ,UAAU,OAAO;;0CAE7C,QAAQ,UAAU,KAAI,MAAK;GACzB,MAAM,aAAa,KAAK,oBAAoB,EAAE;AAC9C,UAAO,IAAI;0EACmB,KAAK,SAAS,KAAK,oBAAoB,CAAC,UAAU,EAAE;4DAClE,KAAK,EAAE,KAAK,CAAC,UAAU,EAAE,OAAO,aAAa,IAAI,0FAA0F,GAAA;;;IAG7J,CAAA;;oCAEN,GAAA;gCACJ,GAAA;8BACF,CAAC,mBAAmB,IAAI;;sCAEhB,IAAE,WAAW,EAAE,YAAY,KAAK,YAAY,CAAC,CAAA;;gCAEnD,GAAA;;;;;;sBAMV,KAAK,KAAK,oBAAoB,MAAM;GAC9B,MAAM,aAAa,KAAK,oBAAoB,EAAE;GAC9C,MAAM,YAAY,kBAAkB,UAAU,EAAE,GAAG;AAEnD,UAAO,IAAI;sCACD,KAAK,EAAE,KAAK,CAAC,GAAG,EAAE,OAAO,aAAa,gBAAgB,GAAG;kCAC7D,KAAK,kBAAkB,IAAI;;;gDAGb,IAAE,mBAAmB;;kCAEnC,CAAA;;;sCAGI,KAAK,iBAAiB,IAAI;;qDAEX,KAAK,oBAAoB,EAAE,GAAG,GAAG,IAAE,gBAAgB,IAAE,cAAc;4DAC5D,KAAK,QAAQ,EAAE,CAAC;;;wDAGpB,KAAK,oBAAoB,EAAE,GAAG,CAAC;sGACe,IAAE,UAAA;;0CAE9D,KAAK,KAAK,oBAAoB,EAAE,GAAG,QAAQ,IAAI;;;wDAGjC,IAAE,cAAc;;0CAE9B,CAAA;6CACG,IAAI;;qDAEI,IAAE,aAAa;4DACR,KAAK,OAAO,EAAE,CAAC;;;uGAG4B,IAAE,QAAA;;sCAEnE,CAAA;;;kCAGJ,KAAK,EAAE,oBAAoB,IAAI;;;;;oDAKb,IAAE,aAAa;;kCAEjC,CAAA;;kCAEA,KAAK,EAAE,WAAW,EAAE,cAAc,IAAI;;0CAE9B,KAAK,EAAE,eAAe,IAAI;;;gGAG4B,IAAE,QAAQ,WAAW,EAAE,QAAQ;;0CAErF,CAAA;0CACA,KAAK,EAAE,cAAc,IAAI;;;gGAG6B,IAAE,OAAO,WAAW,EAAE,OAAO;;0CAEnF,CAAA;;kCAER,CAAA;;8DAE4B,EAAE,YAAY;;kCAE1C,KAAK,EAAE,gBAAgB,EAAE,aAAa,SAAS,SAAS,IAAI;;;;8CAIhD,IAAE,aAAA;;;8CAGF,EAAE,aAAc,KAAI,UAAS;IAC3B,MAAM,SAAS,kBAAkB,eAAe,CAAC,MAAK,OAAM,GAAG,OAAO,MAAM;IAC5E,MAAM,YAAY,kBAAkB,UAAU,MAAM;AACpD,WAAO,IAAI;;;oEAGS,YAAY,iBAAiB,SAAS;4EAC9B,YAAY,+BAA+B,6BAA6B;;0DAE1F,KAAK,QAAQ,QAAQ,eAAe,CAAA;gEAC9B,QAAQ,QAAQ,MAAM;0DAC5B,CAAC,YAAY,IAAI;6FACkB,IAAE,cAAc;4DACjD,GAAA;;;KAGd,CAAA;;;;8CAIA,IAAE,kBAAA;;;kCAGd,CAAA;;IAER,CAAA;;;;;;;gBAON,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WA3flB,OAAO,CAAA,EAAA,gBAAA,WAAA,qBAAA,KAAA,EAAA;WAGP,OAAO,CAAA,EAAA,gBAAA,WAAA,cAAA,KAAA,EAAA;WAGP,OAAO,CAAA,EAAA,gBAAA,WAAA,sBAAA,KAAA,EAAA;WAGP,OAAO,CAAA,EAAA,gBAAA,WAAA,yBAAA,KAAA,EAAA;6BAXX,cAAc,mBAAmB,CAAA,EAAA,gBAAA;;;ACblC,IAAM,MAAI,MAAM,KAAK,uBAAA,OAAA;CAAA,+BAAA,OAAA;CAAA,+BAAA,OAAA;CAAA,CAAuC,CAAC;AAUtD,IAAA,mBAAA,MAAM,yBAAyB,UAAU;;;kBAEX,EAAE;oBAGL;gBAGK;sBAES,WAAW;;CAEvD,oBAAoB;AAChB,QAAM,mBAAmB;AAEzB,OAAK,cAAc;AAEnB,qBAAmB,KAAK,IAAI,KAAK,KAAK,CAAC;;CAG3C,uBAAuB;AACnB,QAAM,sBAAsB;AAE5B,wBAAsB;;CAG1B,IAAW,QAAgB,SAAiB,QAAkB,QAAQ;EAClE,MAAM,aAAyB;GAC3B,2BAAW,IAAI,MAAM;GACrB;GACA;GACA;GACH;AAED,OAAK,WAAW,CAAC,GAAG,KAAK,UAAU,WAAW;AAE9C,MAAI,KAAK,WACL,MAAK,eAAe,WAAW;GAC3B,MAAM,YAAY,KAAK,aAAa;AACpC,OAAI,UACA,WAAU,YAAY,UAAU;IAEtC;;CAIV,QAAe;AACX,OAAK,WAAW,EAAE;;CAGtB,sBAA8B;AAC1B,MAAI,KAAK,WAAW,MAChB,QAAO,KAAK;AAEhB,SAAO,KAAK,SAAS,QAAO,MAAK,EAAE,UAAU,KAAK,OAAO;;CAG7D,gBAAwB,MAAoB;AACxC,SAAO,KAAK,mBAAmB,SAAS;GACpC,QAAQ;GACR,MAAM;GACN,QAAQ;GACR,QAAQ;GACX,CAAC;;CAGN,aAAqB,OAAyB;AAC1C,UAAQ,OAAR;GACI,KAAK,OAAQ,QAAO;GACpB,KAAK,UAAW,QAAO;GACvB,KAAK,QAAS,QAAO;GACrB,KAAK,QAAS,QAAO;;;CAI7B,cAAsB,OAAyB;AAC3C,UAAQ,OAAR;GACI,KAAK,OAAQ,QAAO;GACpB,KAAK,UAAW,QAAO;GACvB,KAAK,QAAS,QAAO;GACrB,KAAK,QAAS,QAAO;;;CAI7B,gBAA0B;EACtB,MAAM,YAAY,KAAK,SAAS,QAAO,MAAK,EAAE,UAAU,OAAO,CAAC;EAChE,MAAM,eAAe,KAAK,SAAS,QAAO,MAAK,EAAE,UAAU,UAAU,CAAC;EACtE,MAAM,aAAa,KAAK,SAAS,QAAO,MAAK,EAAE,UAAU,QAAQ,CAAC;EAClE,MAAM,aAAa,KAAK,SAAS,QAAO,MAAK,EAAE,UAAU,QAAQ,CAAC;AAElE,SAAO,IAAI;;;yBAGM,IAAE,SAAS;8BACN,KAAK,WAAW,QAAQ,WAAW,QAAQ;2BAC9C,KAAK,WAAW,QAAQ,UAAU,UAAU;gCACvC;AACZ,QAAK,SAAS;AACd,QAAK,cAAc;IACrB;kBACA,IAAE,IAAI,IAAI,KAAK,SAAS,OAAO;;;;;yBAKxB,IAAE,UAAU;8BACP,KAAK,WAAW,SAAS,WAAW,QAAQ;2BAC/C,KAAK,WAAW,SAAS,UAAU,UAAU;gCACxC;AACZ,QAAK,SAAS;AACd,QAAK,cAAc;IACrB;kBACA,IAAE,OAAO,YAAY,IAAI,KAAK,UAAU,KAAK,GAAA;;;;;yBAKtC,IAAE,aAAa;8BACV,KAAK,WAAW,YAAY,WAAW,QAAQ;2BAClD,KAAK,WAAW,YAAY,UAAU,UAAU;gCAC3C;AACZ,QAAK,SAAS;AACd,QAAK,cAAc;IACrB;kBACA,IAAE,WAAW,eAAe,IAAI,KAAK,aAAa,KAAK,GAAA;;;;;yBAKhD,IAAE,WAAW;8BACR,KAAK,WAAW,UAAU,WAAW,QAAQ;2BAChD,KAAK,WAAW,UAAU,UAAU,UAAU;gCACzC;AACZ,QAAK,SAAS;AACd,QAAK,cAAc;IACrB;kBACA,IAAE,SAAS,aAAa,IAAI,KAAK,WAAW,KAAK,GAAA;;;;;yBAK1C,IAAE,WAAW;8BACR,KAAK,WAAW,UAAU,WAAW,QAAQ;2BAChD,KAAK,WAAW,UAAU,UAAU,UAAU;gCACzC;AACZ,QAAK,SAAS;AACd,QAAK,cAAc;IACrB;kBACA,IAAE,QAAQ,aAAa,IAAI,KAAK,WAAW,KAAK,GAAA;;;;;;;yBAOzC,KAAK,aAAa,IAAE,sBAAsB,IAAE,qBAAqB;8BAC5D,KAAK,aAAa,WAAW,QAAQ;2BACxC,KAAK,aAAa,UAAU,UAAU;gCACjC;AACZ,QAAK,aAAa,CAAC,KAAK;AACxB,QAAK,cAAc;IACrB;kBACA,KAAK,aAAa,IAAE,cAAc,IAAE,OAAA;;;;;yBAK7B,IAAE,WAAW;gCACN,KAAK,OAAO,CAAC;kBAC3B,IAAE,MAAA;;;;CAKhB,gBAA0B;EACtB,MAAM,mBAAmB,KAAK,qBAAqB;AAEnD,SAAO,IAAI;;wCAEqB,IAAI,KAAK,aAAa,CAAC;sBACzC,iBAAiB,WAAW,IACxB,IAAI,4BAA4B,IAAE,gBAAgB,UAClD,iBAAiB,KAAI,QAAO,IAAI;+DACK,IAAI,MAAM;0DACf,KAAK,gBAAgB,IAAI,UAAU,CAAC;;4CAElD,KAAK,aAAa,IAAI,MAAM,CAAC;6CAC5B,IAAI,MAAM;oDACH,KAAK,cAAc,IAAI,MAAM,CAAC;;wDAE1B,IAAI,OAAO;qDACd,IAAI,QAAQ;;0BAEvC,CAAA;;;;;;gBAON,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+EnB,MAAc,eAAe;EACzB,MAAM,YAAY,MAAM,KAAK,kBAAkB;AAE/C,MAAI,WAAW;AACX,OAAI,OAAO,UAAU,WAAW,aAC3B,UAAU,WAAW,SAAS;IAAC;IAAQ;IAAW;IAAS;IAAQ,CAAC,SAAS,UAAU,OAAO,EAC/F,MAAK,SAAS,UAAU;AAE5B,OAAI,OAAO,UAAU,eAAe,UAChC,MAAK,aAAa,UAAU;;;CAKxC,MAAc,eAAe;AACzB,QAAM,KAAK,iBAAiB;GACxB,QAAQ,KAAK;GACb,YAAY,KAAK;GACpB,CAAC;;;WAxSL,OAAO,CAAA,EAAA,iBAAA,WAAA,YAAA,KAAA,EAAA;WAGP,OAAO,CAAA,EAAA,iBAAA,WAAA,cAAA,KAAA,EAAA;WAGP,OAAO,CAAA,EAAA,iBAAA,WAAA,UAAA,KAAA,EAAA;8BARX,cAAc,qBAAqB,CAAA,EAAA,iBAAA;;;ACLpC,IAAM,IAAI,MAAM,KAAK,uBAAA,OAAA;CAAA,6BAAA,OAAA;CAAA,6BAAA,OAAA;CAAA,CAAqC,CAAC;AAGpD,IAAA,iBAAA,MAAM,uBAAuB,YAAY;;;gBAE3B;eAGD;kBAMI;oBAG0B;cAGT;mBAGgI;0BAMvH,EAAE;oBAGlB;oBAGD;mBAES,WAAW;iBACf,WAAW;yBACD,WAAW;kBAQ5C;;CAEX,kBAAkC;AAC9B,SAAO,yBAAyB,KAAK;;CAGzC,eAAuB,cAA+B;AAClD,MAAI,KAAK,SAAU;AAEnB,MAAI,KAAK,aAAa;GAClB,MAAM,eAAe,SAAS,cAAc,cAAc,KAAK,cAAc;AAC7E,OAAI,CAAC,cAAc;AACf,YAAQ,MAAM,qCAAqC,KAAK,YAAY,aAAa;AACjF;;AAEJ,gBAAa,KAAK,aAAa;SAC5B;AACH,QAAK,aAAa;AAElB,QAAK,eAAe,WAAW;IAC3B,MAAM,gBAAgB,KAAK,QAAQ;AACnC,QAAI,cACA,eAAc,KAAK,aAAa;KAEtC;;;CAIV,mBAA2B;AACvB,OAAK,aAAa;;CAGtB,YAAoB,GAAe;AAC/B,IAAE,gBAAgB;AAClB,IAAE,iBAAiB;EAEnB,MAAM,SAAS,KAAK,UAAU;AAC9B,MAAI,CAAC,OAAQ;EAEb,MAAM,sBAA8B;GAChC,MAAM,cAAc,OAAO,YAAY,cAAc,mBAAiB;AACtE,OAAI,eAAe,YAAY,cAAc,EACzC,QAAO,YAAY;GAIvB,MAAM,SAFgB,OAAO,iBAAiB,OAAO,CACrB,iBAAiB,SAAS,IAAI,KAAK,YAC3C,MAAM,gCAAgC;AAC9D,OAAI,OAAO;IACP,MAAM,QAAQ,WAAW,MAAM,GAAG;IAClC,MAAM,OAAO,MAAM;AACnB,QAAI,SAAS,KAAM,QAAO;AAC1B,QAAI,SAAS,KAAM,QAAQ,QAAQ,MAAO,OAAO;AACjD,QAAI,SAAS,KAAM,QAAQ,QAAQ,MAAO,OAAO;AACjD,QAAI,SAAS,IAAK,QAAQ,QAAQ,MAAO,OAAO;;AAEpD,UAAO;;EAGX,IAAI,cAAc,eAAe;AACjC,MAAI,gBAAgB,EAChB,eAAc,OAAO,aAAa;EAGtC,MAAM,mBAAmB,cAA0B;AAC/C,OAAI,CAAC,KAAK,SAAU;AAEpB,aAAU,gBAAgB;AAC1B,aAAU,iBAAiB;AAE3B,OAAI,KAAK,SAAS,UAAU,KACxB,sBAAqB,KAAK,SAAS,MAAM;AAG7C,QAAK,SAAS,QAAQ,4BAA4B;AAC9C,QAAI,CAAC,KAAK,SAAU;IAEpB,MAAM,QAAQ,KAAK,SAAS,SAAS,UAAU;IAC/C,MAAM,UAAU,KAAK,MAAM,KAAK,SAAS,YAAY,MAAM;IAC3D,MAAM,UAAU;IAChB,MAAM,UAAU,KAAK,MAAM,OAAO,aAAa,GAAI;AAEnD,QAAI,WAAW,WAAW,WAAW,SAAS;AAC1C,UAAK,aAAa,GAAG,QAAQ;KAE7B,MAAM,SAAS,KAAK,UAAU;AAC9B,SAAI,QAAQ;AACR,aAAO,MAAM,YAAY,UAAU,KAAK,WAAW;AACnD,aAAO,MAAM,YAAY,cAAc,OAAO;;;AAGtD,SAAK,SAAS,QAAQ;KACxB;;EAGN,MAAM,sBAAsB;AACxB,OAAI,KAAK,UAAU;AACf,QAAI,KAAK,SAAS,UAAU,MAAM;AAC9B,0BAAqB,KAAK,SAAS,MAAM;AACzC,UAAK,SAAS,QAAQ;;AAG1B,aAAS,oBAAoB,aAAa,KAAK,SAAS,gBAAgB;AACxE,aAAS,oBAAoB,WAAW,KAAK,SAAS,cAAc;AACpE,aAAS,KAAK,MAAM,SAAS;AAC7B,aAAS,KAAK,MAAM,aAAa;IAEjC,MAAM,SAAS,KAAK,UAAU;AAC9B,QAAI,OACA,QAAO,MAAM,eAAe,aAAa;AAG7C,SAAK,WAAW;;;AAIxB,OAAK,WAAW;GACZ,QAAQ,EAAE;GACV,WAAW;GACX;GACA;GACA,OAAO;GACV;AAED,WAAS,iBAAiB,aAAa,iBAAiB,EAAE,SAAS,OAAO,CAAC;AAC3E,WAAS,iBAAiB,WAAW,eAAe,EAAE,SAAS,OAAO,CAAC;AACvE,WAAS,KAAK,MAAM,SAAS;AAC7B,WAAS,KAAK,MAAM,aAAa;;CAGrC,aAAuB;AACnB,MAAI,KAAK,QAAQ;AACb,QAAK,sBAAsB;AAE3B,aAAU,+BAA+B,UAAmC;AACxE,QAAI,KAAK,UAAU,MAAM,WAAW,KAAK,OACrC,MAAK,sBAAsB;KAEjC;;;CAIV,uBAA+B;AAC3B,MAAI,CAAC,KAAK,OAAQ;AAGlB,OAAK,mBADoB,qBAAqB,iBAAiB,KAAK,OAAO,CAClC,QAAQ,MAA4B,UAAU,EAAE;AACzF,OAAK,eAAe;;CAGxB,sBAA8B,cAA+B;AACzD,SAAO,IAAI;;+BAEY,KAAK,eAAe,aAAa,CAAC;kBAC/C,KAAK,aAAa,MAAM;GAAE,OAAO,aAAa;GAAO,MAAM;GAAQ,CAAC,CAAA;kBACpE,aAAa,MAAA;;;;CAK3B,SAAS;AACL,MAAI,CAAC,KAAK,OACN,QAAO;AAGX,MAAI,KAAK,iBAAiB,WAAW,EACjC,QAAO;AAGX,SAAO,IAAI;qCACkB,KAAK,UAAU;;;iCAGnB,KAAK,WAAA;2BACX,KAAK,KAAA;gCACA,KAAK,SAAA;;4BAET,KAAK,MAAM;sBACjB,KAAK,KAAK,MAAM;GAAE,OAAO,KAAK;GAAO,MAAM;GAAS,CAAC,CAAA;;;;kBAIzD,KAAK,QAAQ,IAAI;;0BAET,KAAK,MAAA;;oBAEX,QAAA;;kBAEF,KAAK,iBAAiB,KAAI,MAAK,KAAK,sBAAsB,EAAE,CAAC,CAAA;;;cAGjE,CAAC,KAAK,cAAc,IAAI;;sBAEhB,IAAI,KAAK,UAAU,CAAA;6BACZ,KAAK,SAAS,EAAE,WAAW;;4BAE5B,KAAK,WAAA;+BACF,KAAK,iBAAA;qCACC,KAAK,WAAW;;0BAE3B,IAAI,KAAK,gBAAgB,CAAA;;qCAEd,KAAK,YAAY;;;0BAG5B,IAAI,KAAK,QAAQ,CAAA;8BACb,KAAK,iBAAiB,CAAC;;;;gBAIrC,QAAA;;;;gBAII,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAhQlB,UAAU,CAAA,EAAA,eAAA,WAAA,UAAA,KAAA,EAAA;WAGV,UAAU,CAAA,EAAA,eAAA,WAAA,SAAA,KAAA,EAAA;WAGV,UAAU,CAAA,EAAA,eAAA,WAAA,QAAA,KAAA,EAAA;WAGV,SAAS,EAAE,MAAM,SAAS,CAAC,CAAA,EAAA,eAAA,WAAA,YAAA,KAAA,EAAA;WAG3B,UAAU,CAAA,EAAA,eAAA,WAAA,cAAA,KAAA,EAAA;WAGV,UAAU,CAAA,EAAA,eAAA,WAAA,QAAA,KAAA,EAAA;WAGV,UAAU,CAAA,EAAA,eAAA,WAAA,aAAA,KAAA,EAAA;WAGV,UAAU,CAAA,EAAA,eAAA,WAAA,eAAA,KAAA,EAAA;WAGV,OAAO,CAAA,EAAA,eAAA,WAAA,oBAAA,KAAA,EAAA;WAGP,OAAO,CAAA,EAAA,eAAA,WAAA,cAAA,KAAA,EAAA;WAGP,OAAO,CAAA,EAAA,eAAA,WAAA,cAAA,KAAA,EAAA;4BAhCX,cAAc,kBAAkB,CAAA,EAAA,eAAA;;;ACPjC,SAAS,qBAAkC;CACvC,IAAI,YAAY,SAAS,eAAe,0BAA0B;AAClE,KAAI,CAAC,WAAW;AACZ,cAAY,SAAS,cAAc,MAAM;AACzC,YAAU,KAAK;AACf,WAAS,KAAK,YAAY,UAAU;;AAExC,QAAO;;AAGX,IAAM,mBAAmB,SAAyB;AAC9C,KAAI;AACA,SAAO,IAAI,KAAK,aAAa,CAAC,KAAK,EAAE,EAAE,MAAM,YAAY,CAAC,CAAC,GAAG,KAAK,IAAI,KAAK,aAAa;SACrF;AACJ,SAAO,KAAK,aAAa;;;AAIjC,IAAM,8BAAwC,CAAC,GAAG,uBAAuB,KAAK,CAAC,CAAC,MAAM;AAEtF,IAAa,6BAA6B,YAA2B;CACjE,MAAM,qBAAqB,uBAAuB;CAClD,MAAM,kBAAkB,sBAAsB,KAAK;AAEnD,QAAO,IAAI,SAAS,YAAY;EAC5B,MAAM,YAAY,oBAAoB;EAEtC,IAAI,aAAa;EAEjB,MAAM,oBAAoB;GACtB,MAAM,SAAS,UAAU,cAAc,YAAY;AACnD,OAAI,UAAU,CAAC,WACX,QAAO,OAAO;;EAItB,MAAM,wBAAwB;AAC1B,OAAI,WAAY;AAChB,gBAAa;AACb,UAAO,IAAI,IAAI,UAAU;AACzB,YAAS;;EAGb,MAAM,iBAAiB,OAAO,aAAqB;AAC/C,SAAM,YAAY,IAAI,uBAAuB,SAAS;AACtD,gBAAa;;AAgEjB,SA7DiB,IAAI;;;;;oCAKO,YAAY;iCACf,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBA2C3B,mBAAmB,KAAI,SAAQ,IAAI;;mDAEN,SAAS,kBAAkB,WAAW,GAAG;2CACjD,eAAe,KAAK,CAAC;0DACN,KAAK,aAAa,CAAC;0DACnB,gBAAgB,KAAK,CAAC;;sBAE1D,CAAC;;;WAKE,UAAU;GAC7B;;AAIC,IAAA,wBAAA,MAAM,8BAA8B,aAAa;;gBACpC,GAAG;;;;;;CAMnB,SAAmB;EACf,MAAM,kBAAkB,sBAAsB,KAAK;EACnD,MAAM,eAAe,gBAAgB,gBAAgB;AAGrD,SAAO,IAAI;;;;2CAIwB,aAAa;+BACzB,4BAA4B,CAAC;kBAPhC,GAAG,gBAAgB,aAAa,CAAC,GAAG,eAQlC;;;;;mCAnB7B,cAAc,0BAA0B,CAAA,EAAA,sBAAA;;;AChHlC,IAAA,sBAAA,MAAM,4BAA4B,aAAa;;;yBAExB;;CAE1B,aAAuB;AACnB,OAAK,kBAAkB,iBAAiB,oBAAoB;EAC5D,MAAM,qBAAqB;AACvB,QAAK,kBAAkB,iBAAiB,oBAAoB;AAC5D,QAAK,eAAe;;AAExB,SAAO,iBAAiB,cAAc,aAAa;AACnD,SAAO,iBAAiB,kBAAkB,aAAa;AACvD,eAAa;AACT,UAAO,oBAAoB,cAAc,aAAa;AACtD,UAAO,oBAAoB,kBAAkB,aAAa;;;CAIlE,MAAc,aAAa,GAAgB;EACvC,MAAM,WAAW,EAAE,QAAQ,MAAM;AACjC,MAAI,CAAC,YAAY,aAAa,KAAK,gBAAiB;AACpD,MAAI;AACA,SAAM,iBAAiB,qBAAqB,SAAS;WAChD,KAAK;AACV,WAAQ,MAAM,4BAA4B,IAAI;;;CAItD,SAAmB;EACf,MAAM,UAAU,iBAAiB,sBAAsB;AACvD,MAAI,QAAQ,UAAU,EAClB,QAAO,IAAI;EAIf,MAAM,aADgB,QAAQ,MAAM,MAAM,EAAE,OAAO,KAAK,gBAAgB,EACtC,QAAQ,KAAK;AAE/C,SAAO,IAAI;;;;;6BAKU,KAAK,aAAa;;;;;;qDAMM,WAAW;;;kBAG9C,QAAQ,KACL,WAAW,IAAI;;qCAEC,OAAO,GAAG;;uCAER,OAAO,OAAO,KAAK,gBAAgB;8BAC5C,KAAK,OAAO,MAAM;GAAE,OAAO,OAAO;GAAM,MAAM;GAAQ,CAAC,CAAC;8BACxD,OAAO,KAAK;;sBAGzB,CAAC;;;;;gBAKE,GAAG;;;;;;;WAjElB,OAAO,CAAA,EAAA,oBAAA,WAAA,mBAAA,KAAA,EAAA;iCAFX,cAAc,wBAAwB,CAAA,EAAA,oBAAA;;;ACNvC,IAAa,mBAAmB;AAChC,IAAa,oBAAoB;AAEjC,IAAa,eAAe;AAC5B,IAAa,qBAAqB;AAClC,IAAa,4BAA4B;AACzC,IAAa,uBAAuB;;;ACWpC,qBAAqB,qBAAqB,cAAc;CACpD,MAAM;CACN,OAAO;CACP,MAAM;CACN,YAAY,OAAe,IAAI,0BAA0B,GAAG;CAC/D,CAAC;AAEF,qBAAqB,qBAAqB,cAAc;CACpD,MAAM;CACN,OAAO;CACP,MAAM;CACN,YAAY,OAAe,IAAI,2BAA2B,GAAG;CAChE,CAAC;AAEF,qBAAqB,qBAAqB,oBAAoB;CAC1D,MAAM;CACN,OAAO;CACP,MAAM;CACN,SAAS;CACT,WAAW;CACd,CAAC;AAEF,qBAAqB,qBAAqB,oBAAoB;CAC1D,MAAM;CACN,OAAO;CACP,WAAW;CACd,CAAC;AAEF,qBAAqB,qBAAqB,oBAAoB;CAC1D,MAAM;CACN,OAAO;CACP,iBAAiB,IAAI;CACxB,CAAC;AAEF,qBAAqB,qBAAqB,oBAAoB;CAC1D,MAAM;CACN,OAAO;CACP,iBAAiB,IAAI;CACxB,CAAqB;;;ACpCf,IAAA,sBAAA,MAAM,4BAA4B,eAAe;;;2BAEvB;yBAGF;yBAGA;wBAGD;;CAE1B,mBAAmB;AACf,SAAO;;CAGX,eAA+B;AAC3B,MAAI,KAAK,mBAAmB,KAAK,eAC7B,QAAO;AAEX,MAAI,KAAK,gBACL,QAAO;AAEX,MAAI,KAAK,eACL,QAAO;AAEX,SAAO;;CAGX,SAAS;AACL,SAAO,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oCAwEiB,aAAa;oCACb,oBAAoB;wDACA,mBAAmB;;;;;;;wBAOnD,KAAK,cAAc,CAAC;;kBAE1B,KAAK,kBACD,IAAI;0BACA,KAAK,oBACD,IAAI;;;;;sDAKoB,aAAa;sDACb,oBAAoB;;gCAG5C,IAAI,mBAAmB,aAAa,iBACzC;wBAEH,QACL;;kBAEC,KAAK,kBACD,IAAI;;;;;8CAKoB,iBAAiB;8CACjB,aAAa;;wBAGrC,IAAI,mBAAmB,iBAAiB,iBAC7C;;kBAEC,KAAK,iBACD,IAAI,mBAAmB,kBAAkB,mBACzC,QACL;;;;oCAImB,eAAe;oCACf,sBAAsB;wDACF,mBAAmB;;;;;WAzJtE,SAAS;CAAC,MAAM;CAAS,WAAW;CAAsB,CAAC,CAAA,EAAA,oBAAA,WAAA,qBAAA,KAAA,EAAA;WAG3D,SAAS;CAAC,MAAM;CAAS,WAAW;CAAoB,CAAC,CAAA,EAAA,oBAAA,WAAA,mBAAA,KAAA,EAAA;WAGzD,SAAS;CAAC,MAAM;CAAS,WAAW;CAAoB,CAAC,CAAA,EAAA,oBAAA,WAAA,mBAAA,KAAA,EAAA;WAGzD,SAAS;CAAC,MAAM;CAAS,WAAW;CAAmB,CAAC,CAAA,EAAA,oBAAA,WAAA,kBAAA,KAAA,EAAA;iCAX5D,cAAc,wBAAwB,CAAA,EAAA,oBAAA;;;AC0BvC,KAAK,MAAM,UAlCN;CACD;EACI,IAAI;EACJ,MAAM;EACN,OAAO;EACP,MAAM;EACN,WAAW;EACd;CACD;EACI,IAAI;EACJ,MAAM;EACN,OAAO;EACP,MAAM;EACN,WAAW;GAAE,KAAK;GAAyB,YAAY,EAAE,qBAAqB,QAAQ;GAAE;EAC3F;CACD;EACI,IAAI;EACJ,MAAM;EACN,OAAO;EACP,MAAM;EACN,WAAW;GAAE,KAAK;GAAyB,YAAY,EAAE,uBAAuB,QAAQ;GAAE;EAC7F;CACD;EACI,IAAI;EACJ,MAAM;EACN,OAAO;EACP,MAAM;EACN,WAAW;GACP,KAAK;GACL,YAAY;IAAE,qBAAqB;IAAQ,uBAAuB;IAAQ;GAC7E;EACJ;CACJ,CAGG,sBAAqB,qBAAqB,gBAAgB,OAAO;;;ACtCrE,eAAe,oBAAoB,QAAa,cAAuB,MAA4D;CAC/H,MAAM,YAAY,MAAM,iBAAiB,cAAc;AACvD,KAAI,CAAC,UACD,QAAO;CAGX,MAAM,OAAO,QAAQ;AACrB,KAAI,eAAe,CAAC,KAChB,QAAO;AAGX,QAAO;EAAE;EAAW,MAAM,QAAQ;EAAI;;;;;AAM1C,SAAS,wBAAwB,QAA8C;AAC3E,QAAO,UACH,OAAO,OAAO,eAAe,cAC7B,OAAO,OAAO,iBAAiB,cAC/B,OAAO,OAAO,eAAe,cAC7B,OAAO,OAAO,gBAAgB,cAC9B,OAAO,OAAO,gBAAgB;;;;;AA4CtC,SAAS,yBAAyB,oBAA6B,OAAO;CAClE,MAAM,OAAO;EACT,UAAU;EACV,UAAU;EACb;AACD,KAAI,kBACA,QAAO;EAAE,GAAG;EAAM,SAAS;EAAM,YAAY;EAAM;AAEvD,QAAO;;AAGX,eAAe,oBAAoB,QAAa,cAAuB,MAAwE;CAC3I,MAAM,SAAS,MAAM,oBAAoB,QAAQ,YAAY;AAC7D,KAAI,CAAC,OACD,QAAO;CAGX,MAAM,EAAE,WAAW,SAAS;AAE5B,KAAI,CAAC,KACD,QAAO;AAGX,KAAI;EACA,MAAM,WAAW,MAAM,UAAU,YAAY,KAAK;AAClD,MAAI,CAAC,YAAY,EAAE,oBAAoB,MACnC,QAAO;AAGX,SAAO;GAAE;GAAW;GAAM,MAAM;GAAU;UACrC,KAAU;AACf,SAAO;;;AAIf,YAAY;CACR,SAAS;EACL,MAAM;EACN,QAAQ;EACR,eAAe;EAClB;CACD,SAAS,EACL,SAAS,YAAY;EACjB,MAAM,YAAY,sBAAsB,KAAK;AAC7C,MAAI,EAAE,qBAAqB,aAAa,UAAU,WAAW,KAAK,KAAA,IAAY;AAC1E,cAAW,sCAAsC;AACjD;;AAEJ,MAAI;GACA,MAAM,aAAa,MAAM,iBAAiB,0BAA0B,UAAU;AAC9E,OAAI,YAAY,SAAS,aAAa;AAIlC,QAAI,CAHe,MAAM,cACrB,gBAAgB,WAAW,KAAK,2FACnC,CAEG;AAEJ,UAAM,6BAA6B,UAAU;AAC7C,cAAU,8BAA8B,WAAW,KAAK,GAAG;;AAE/D,SAAM,iBAAiB,iBAAiB,UAAU;WAC7C,KAAU;AACf,cAAW,IAAI,QAAQ;;IAGlC;CACD,cAAc;EACV,QAAQ;EACR,OAAO;EACP,MAAM;EACN,gBAAgB;GACZ,MAAM,YAAY,sBAAsB,KAAK;AAC7C,UAAO,EAAE,qBAAqB,aAAa,UAAU,WAAW,KAAK,KAAA;;EAE5E;CACJ,CAAC;AAGF,YAAY;CACR,SAAS;EACL,MAAM;EACN,QAAQ;EACR,eAAe;EACf,cAAc,EAAE;EACnB;CACD,SAAS,EACL,SAAS,OAAM,aAAY;AAEvB,QAAM,OAAO,oBAAoB,EAC7B,MAAM,aACT,CAAC,CAAC,MAAM,cAAyC;AAC9C,UAAO,iBAAiB,iBAAiB,UAAU;IACrD,CAAC,OAAO,QAAe;AACrB,cAAW,IAAI,QAAQ;IACzB;IAET;CACD,cAAc;EACV,QAAQ;EACR,OAAO;EACP,MAAM;EACT;CACJ,CAAC;AAEF,YAAY;CACR,SAAS;EACL,MAAM;EACN,QAAQ;EACR,eAAe;EACf,cAAc,EAAE;EACnB;CACD,SAAS,EACL,SAAS,YAAY;AACjB,MAAI;AACA,SAAM,iBAAiB,cAAc,EAAE,MAAM,MAAM,CAAC;WAC/C,KAAU;AACf,cAAW,IAAI,QAAQ;;IAGlC;CACD,cAAc;EACV,QAAQ;EACR,OAAO;EACP,MAAM;EACT;CACJ,CAAC;AAEF,YAAY;CACR,SAAS;EACL,MAAM;EACN,QAAQ;EACR,eAAe;EACf,cAAc,CACV;GACI,QAAQ;GACR,eAAe;GACf,YAAY;GACf,CACJ;EACJ;CACD,SAAS,EACL,SAAS,OAAO,YAA8B;EAC1C,MAAM,YAAY,QAAQ,SAAS;AACnC,MAAI;AACA,SAAM,iBAAiB,cAAc;IAAE,WAAW;IAAM,MAAM;IAAW,CAAC;WACrE,KAAU;AACf,cAAW,IAAI,QAAQ;;IAGlC;CACD,cAAc;EACV,QAAQ;EACR,OAAO;EACP,MAAM;EACT;CACJ,CAAC;AAEF,YAAY;CACR,SAAS;EACL,MAAM;EACN,QAAQ;EACR,eAAe;EACf,cAAc,EAAE;EACnB;CACD,SAAS,EACL,SAAS,YAAY;EACjB,MAAM,YAAY,sBAAsB,KAAK;AAC7C,MAAI,WAAW;AACX,aAAU,cAAc,CAAC,OAAO;AAChC;;EAEJ,MAAM,YAAY,MAAM,iBAAiB,cAAc;AACvD,MAAI,CAAC,WAAW;AACZ,cAAW,yBAAyB;AACpC;;AAEJ,YAAU,OAAO;IAExB;CACJ,CAAC;AAEF,YAAY;CACR,SAAS;EACL,MAAM;EACN,QAAQ;EACR,eAAe;EACf,cAAc,CACV;GACI,QAAQ;GACR,eAAe;GACf,YAAY;GACf,EACD;GACI,QAAQ;GACR,eAAe;GACf,YAAY;GACf,CACJ;EACJ;CACD,SAAS,EACL,SAAS,OAAM,YAAW;EACtB,MAAM,OAAO,QAAQ,SAAS;EAC9B,MAAM,WAAW,QAAQ,SAAS;EAClC,IAAI,OAAoB;AACxB,MAAI,KAEA,SADe,MAAM,oBAAoB,EAAE,MAAM,CAAC,GACnC,QAAQ;OACpB;GACH,MAAM,YAAY,sBAAsB,KAAK;AAC7C,UAAO,qBAAqB,OAAO,YAAY;;AAEnD,MAAI,CAAC,KAAM;AACX,QAAM,eAAe,WAAW,MAAM,SAAS;IAEtD;CACJ,CAAC;AAEF,YAAY;CACR,SAAS;EACL,MAAM;EACN,QAAQ;EACR,eAAe;EACf,cAAc,EAAE;EAChB,UAAU;GACN;IACI,QAAQ;IACR,eAAe;IAClB;GACD;IACI,QAAQ;IACR,eAAe;IAClB;GACD;IACI,QAAQ;IACR,eAAe;IAClB;GACJ;EACJ;CACD,SAAS,EACL,SAAS,OAAO,YAA8B;EAC1C,MAAM,eAAe,QAAQ;AAC7B,MAAI,CAAC,wBAAwB,aAAa,CACtC,QAAO;GAAE,GAAG,0BAA0B;GAAE,SAAS;GAAM;AAG3D,MAAI;AACA,UAAO;IACH,SAAS,aAAa,YAAY;IAClC,UAAU,aAAa,aAAa;IACpC,UAAU,aAAa,aAAa;IACvC;WACI,KAAU;AACf,UAAO;IAAE,GAAG,0BAA0B;IAAE,SAAS;IAAM;;IAGlE;CACJ,CAAC;AAEF,YAAY;CACR,SAAS;EACL,MAAM;EACN,QAAQ;EACR,eAAe;EACf,cAAc,EAAE;EAChB,UAAU;GACN;IACI,QAAQ;IACR,eAAe;IAClB;GACD;IACI,QAAQ;IACR,eAAe;IAClB;GACD;IACI,QAAQ;IACR,eAAe;IAClB;GACJ;EACJ;CACD,SAAS,EACL,SAAS,OAAO,YAA8B;EAC1C,MAAM,eAAe,QAAQ;AAC7B,MAAI,CAAC,wBAAwB,aAAa,CACtC,QAAO;GAAE,GAAG,0BAA0B;GAAE,WAAW;GAAM;AAG7D,MAAI;AACA,UAAO;IACH,WAAW,aAAa,cAAc;IACtC,UAAU,aAAa,aAAa;IACpC,UAAU,aAAa,aAAa;IACvC;WACI,KAAU;AACf,UAAO;IAAE,GAAG,0BAA0B;IAAE,WAAW;IAAM;;IAGpE;CACJ,CAAC;AAEF,YAAY;CACR,SAAS;EACL,MAAM;EACN,QAAQ;EACR,eAAe;EACf,cAAc,CACV;GACI,QAAQ;GACR,eAAe;GACf,QAAQ;GACR,YAAY;GACf,CACJ;EACD,UAAU;GACN;IACI,QAAQ;IACR,eAAe;IAClB;GACD;IACI,QAAQ;IACR,eAAe;IAClB;GACD;IACI,QAAQ;IACR,eAAe;IAClB;GACD;IACI,QAAQ;IACR,eAAe;IAClB;GACJ;EACJ;CACD,SAAS,EACL,SAAS,OAAO,YAA8B;EAC1C,MAAM,eAAe,QAAQ;AAC7B,MAAI,CAAC,wBAAwB,aAAa,CACtC,QAAO,yBAAyB,KAAK;AAGzC,MAAI;GACA,MAAM,WAAW,QAAQ,QAAQ,QAAQ,SAAS,QAAQ,OAAO,OAAO,GAAG,GAAG;AAC9E,OAAI,MAAM,SAAS,IAAI,WAAW,EAC9B,QAAO,yBAAyB,KAAK;GAGzC,MAAM,gBAAgB,aAAa,WAAW,SAAS;AACvD,OAAI,CAAC,cACD,QAAO,yBAAyB,KAAK;AAGzC,UAAO;IACH,SAAS,cAAc;IACvB,UAAU,aAAa,aAAa;IACpC,UAAU,aAAa,aAAa;IACpC,YAAY,cAAc;IAC7B;WACI,KAAU;AACf,UAAO,yBAAyB,KAAK;;IAGhD;CACJ,CAAC;;;;AC1aF,SAAS,YAAY,GAAW,GAAoB;AAChD,QAAO,EAAE,QAAQ,OAAO,GAAG,KAAK,EAAE,QAAQ,OAAO,GAAG;;AAGxD,YAAY;CACR,SAAS;EACL,MAAM;EACN,QAAQ;EACR,eAAe;EACf,cAAc,EAAE;EACnB;CACD,SAAS,EACL,SAAS,OAAM,aAAY;EACvB,MAAM,MAAM,iBAAiB,eAAe;AAC5C,MAAI,CAAC,KAAK;AACN,cAAW,gBAAgB;AAC3B;;EAGJ,MAAM,OAAO,IAAI,gBAAgB,EAAE;EACnC,MAAM,cAAc,OAAO,KAAK,KAAK,CAAC,SAAS;EAC/C,MAAM,eAA+B,cAC/B,IAAI;;;oCAGc,IAAI,QAAQ,GAAG;8BACrB,OAAO,QAAQ,KAAK,CAAC,KAAK,CAAC,MAAM,aAAa,IAAI;;4CAEpC,KAAK,UAAU,QAAQ;;8BAErC,CAAC;;;oBAIb,IAAI;EAEV,IAAI,kBAAsC;EAC1C,MAAM,2BAAwC;AAC1C,OAAI,CAAC,iBAAiB;AAClB,sBAAkB,SAAS,eAAe,0BAA0B,IAAI,SAAS,cAAc,MAAM;AACrG,QAAI,CAAC,gBAAgB,IAAI;AACrB,qBAAgB,KAAK;AACrB,cAAS,KAAK,YAAY,gBAAgB;;;AAGlD,UAAO;;EAGX,MAAM,gBAAgB;AAClB,OAAI,gBACA,QAAO,IAAI,IAAI,gBAAgB;;EAIvC,MAAM,wBAAwB,mBAA2B;AAErD,UAAO,IAAI,GAAG,WADM,OAAO,MAAM,gBAAgB,EAAE,OAAO,OAAO,CAAC,CAC7B;;EAGzC,IAAI,WAA2B,EAAE;AACjC,MAAI,IAAI,eACJ,KAAI,OAAO,IAAI,mBAAmB,WAC9B,KAAI;AACA,cAAW,MAAM,IAAI,gBAAgB;WAChC,OAAO;AACZ,WAAQ,MAAM,4CAA4C,MAAM;AAChE,cAAW,EAAE;;MAGjB,YAAW,IAAI;EAIvB,MAAM,aAAa,IAAI,WAAW;EAElC,MAAM,eAAe,SAAS,SAAS,IAAI,SAAS,WAAU,MAAK,YAAY,EAAE,UAAU,WAAW,CAAC,GAAG;EAC1G,MAAM,aAAa,gBAAgB,IAAI,eAAe;EACtD,IAAI,sBAAsB;EAE1B,MAAM,uBAAuB,UAAkB;AAC3C,OAAI,SAAS,WAAW,EACpB,QAAO;GAGX,MAAM,UAAU,SAAS;GACzB,MAAM,mBAAmB,YAAY,QAAQ,UAAU,WAAW;GAElE,IAAI,UAAU,gBAAgB,QAAQ;AACtC,OAAI,iBACA,YAAW;AAEf,cAAW;GAEX,MAAM,cAAc,IAAI,KAAK,QAAQ,aAAa,CAAC,oBAAoB;AACvE,cAAW,iBAAiB,YAAY;AAExC,OAAI,CAAC,kBAAkB;IACnB,MAAM,eAAe,WAAW,QAAQ,MAAM,GAAG;IACjD,MAAM,eAAe,QAAQ,SAAS,QAAQ,MAAM,GAAG;IACvD,MAAM,eAAe,aAAa,MAAM,IAAI,CAAC,IAAI,OAAO;IACxD,MAAM,eAAe,aAAa,MAAM,IAAI,CAAC,IAAI,OAAO;IACxD,IAAI,UAAU;AACd,SAAK,IAAI,IAAI,GAAG,IAAI,KAAK,IAAI,aAAa,QAAQ,aAAa,OAAO,EAAE,KAAK;KACzE,MAAM,UAAU,aAAa,MAAM;KACnC,MAAM,cAAc,aAAa,MAAM;AACvC,SAAI,cAAc,SAAS;AACvB,gBAAU;AACV;;AAEJ,SAAI,cAAc,QACd;;AAGR,QAAI,QACA,YAAW;;AAInB,OAAI,QAAQ,KACR,YAAW,UAAU,QAAQ;AAGjC,UAAO;;EAGX,MAAM,oBAAoB;AACtB,YAAS;;EAGb,MAAM,wBAAwB;AAC1B,YAAS;;EAGb,MAAM,gBAAgB,UAAkB;GACpC,MAAM,iBAAiB,oBAAoB,MAAM;GACjD,MAAM,gBAAgB,SAAS,SAAS;AAuExC,UArEiB,IAAI;;uCAEE,IAAI,QAAQ,GAAG,KAAK,WAAW;;;;4CAI1B,YAAY;yCACf,gBAAgB;;;;;;;;;;;;;iCAaxB,IAAI,eAAe,GAAG;;;kCAGrB,SAAS,SAAS,IAAI,IAAI;;;0CAGlB,qBAAqB,eAAe,CAAC;;oCAE3C,GAAG;;kCAEL,cAAc,IAAI;;;0CAGV,aAAa;;oCAEnB,GAAG;;;;8BAIT,gBAAgB,IAAI;;;gDAGF,UAAU,SAAS,SAAS,EAAE;mDAC3B;AACvB,QAAI,QAAQ,SAAS,SAAS,GAAG;AAC7B,2BAAsB,QAAQ;AAC9B,kBAAa,oBAAoB;;KAEvC;;;;;;gDAMsB,UAAU,EAAE;mDACT;AACvB,QAAI,QAAQ,GAAG;AACX,2BAAsB,QAAQ;AAC9B,kBAAa,oBAAoB;;KAEvC;;;;gCAIM,GAAG;;;;mBAKF,oBAAoB,CAAC;;AAG1C,eAAa,WAAW;AAExB,SAAO,IAAI,SAAe,YAAY;GAClC,MAAM,oBAAoB;AACtB,QAAI,CAAC,iBAAiB,cAAc,kBAAkB,CAClD,UAAS;QAET,YAAW,aAAa,IAAI;;AAGpC,gBAAa;IACf;IAET;CACJ,CAAC;;;ACzNF,YAAY;CACR,SAAS;EACL,MAAM;EACN,QAAQ;EACR,eAAe;EACf,cAAc;EACd,cAAc,EAAE;EACnB;CACD,SAAS,EACL,SAAS,OAAM,aAAY;EACvB,MAAM,OAAO,iBAAiB,KAAK;AACnC,MAAI,QAAQ,KAAK,SAAS,CACtB,MAAK,MAAM;IAGtB;CACD,cAAc;EACV,QAAQ;EACR,MAAM;EACN,OAAO;EACP,MAAM;EACN,gBAAgB;GACZ,MAAM,OAAO,iBAAiB,KAAK;AACnC,UAAO,CAAC,QAAQ,CAAC,KAAK,SAAS;;EAEtC;CACJ,CAAC;AAEF,IAAM,qBAAqB;AAE3B,eAAe,WAAW,YAAmD;CACzE,MAAM,OAAO,SAAS;AACtB,MAAK,UAAU,OAAO,WAAW,WAAW;AAC5C,MAAK,UAAU,IAAI,WAAW;;AAGlC,eAAe,YAA2B;AAEtC,OAAM,WADQ,MAAM,YAAY,IAAI,mBAAmB,IAC7B,UAAU;;AAGxC,eAAe,UAAU,YAAmD;AACxE,OAAM,YAAY,IAAI,oBAAoB,WAAW;;AAGzD,YAAY;CACR,SAAS;EACL,MAAM;EACN,QAAQ;EACR,eAAe;EACf,cAAc,EAAE;EACnB;CACD,SAAS,EACL,SAAS,OAAM,aAAY;EAEvB,MAAM,WADS,SAAS,gBAAgB,UAAU,SAAS,UAAU,GAC3C,aAAa;AACvC,QAAM,WAAW,SAAS;AAC1B,QAAM,UAAU,SAAS;IAEhC;CACD,cAAc;EACV,QAAQ;EACR,MAAM;EACN,OAAO;EACV;CACJ,CAAC;AAGF,WAAW,CAAC,OAAM,QAAO;AACrB,SAAQ,MAAM,oCAAoC,IAAI;EACxD;AAEF,YAAY;CACR,SAAS;EACL,MAAM;EACN,QAAQ;EACR,eAAe;EACf,cAAc,EAAE;EACnB;CACD,SAAS,EACL,SAAS,OAAM,aAAY;EACvB,MAAM,OAAO,SAAS;AACtB,MAAI,SAAS,sBAAsB,KAC/B,OAAM,SAAS,gBAAgB;MAE/B,OAAM,KAAK,mBAAmB;IAGzC;CACD,cAAc;EACV,QAAQ;EACR,MAAM;EACN,OAAO;EACV;CACJ,CAAC;AAEF,YAAY;CACR,SAAS;EACL,MAAM;EACN,QAAQ;EACR,eAAe;EACf,cAAc,EAAE;EACnB;CACD,SAAS,EACL,UAAS,aAAY;AASjB,iBAAe,WARkB;GAC7B,OAAO;GACP,MAAM,EAAE;GACR,KAAK;GACL,MAAM;GACN,OAAO,EAAE;GACT,YAAY,OAAe,IAAI,yBAAyB,GAAG;GAC9D,EACsC,oBAAoB,CAAC,MAAM;IAEzE;CACD,cAAc;EACV,QAAQ;EACR,MAAM;EACN,OAAO;EACV;CACJ,CAAC;AAEF,YAAY;CACR,SAAS;EACL,MAAM;EACN,QAAQ;EACR,eAAe;EACf,cAAc,EAAE;EAChB,UAAU,CACN;GACI,QAAQ;GACR,eAAe;GAClB,CACJ;EACJ;CACD,SAAS,EACL,SAAS,OAAO,aAAkB;AAU9B,SATmB,kBAAkB,eAAe,CAAC,KAAK,MAAiB;AACvE,UAAO;IACH,IAAI,EAAE;IACN,MAAM,EAAE;IACR,aAAa,EAAE;IACf,cAAc,EAAE;IAChB,SAAS,kBAAkB,UAAU,EAAE,GAAG;IAC7C;IACH;IAGT;CACJ,CAAC;AAEF,YAAY;CACR,SAAS;EACL,MAAM;EACN,QAAQ;EACR,eAAe;EACf,cAAc,CACV;GACI,QAAQ;GACR,eAAe;GACf,YAAY;GACf,EACD;GACI,QAAQ;GACR,eAAe;GACf,YAAY;GACf,CACJ;EACJ;CACD,SAAS,EACL,UAAU,EAAE,QAAQ,EAAE,SAAS,aAAkB;AAC7C,MAAI,CAAC,QACD;AAEJ,MAAI,SAAS,QACT,YAAW,QAAQ;MAEnB,WAAU,QAAQ;IAG7B;CACJ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACzLF,SAAgB,kBAA6B;CAC3C,IAAI,SAAwB;CAC5B,IAAI,UAAgF;CAEpF,SAAS,YAAoB;AAC3B,MAAI,CAAC,QAAQ;AACX,YAAS,IAAI,eAAiB;AAC9B,UAAO,aAAa,MAAyE;IAC3F,MAAM,IAAI;AACV,cAAU;AACV,QAAI,CAAC,EAAG;AACR,QAAI,EAAE,KAAK,SAAS,SAAU,GAAE,QAAQ,EAAE,KAAK,MAAM;QAChD,GAAE,OAAO,IAAI,MAAM,EAAE,KAAK,WAAW,gBAAgB,CAAC;;AAE7D,UAAO,WAAW,OAAO;IACvB,MAAM,IAAI;AACV,cAAU;AACV,QAAI,EAAG,GAAE,OAAO,IAAI,MAAM,GAAG,WAAW,eAAe,CAAC;;;AAG5D,SAAO;;AAGT,QAAO;EACL,QAAQ,MAAgC;AACtC,UAAO,IAAI,SAAS,SAAS,WAAW;AACtC,cAAU;KAAE;KAAS;KAAQ;AAC7B,eAAW,CAAC,YAAY,KAAK;KAC7B;;EAGJ,QAAc;AACZ,OAAI,QAAQ;AACV,WAAO,WAAW;AAClB,aAAS;;AAEX,aAAU;;EAEb;;;;AC5CH,SAAgB,kBAAkB,MAAgC;CAChE,MAAM,UAAU,iBAAiB;AACjC,QAAO,QAAQ,QAAQ,KAAK,CAAC,cAAc,QAAQ,OAAO,CAAC;;AAG7D,eAAe,QAAQ,QAGI;AACzB,KAAI,OAAO,MAAM,MAAM,CAAE,QAAO,OAAO,KAAK,MAAM;AAClD,KAAI,CAAC,OAAO,QAAQ;AAClB,aAAW,0CAA0C;AACrD,SAAO;;CAET,MAAM,YAAY,MAAM,iBAAiB,cAAc;AACvD,KAAI,CAAC,WAAW;AACd,aAAW,yBAAyB;AACpC,SAAO;;AAET,KAAI;EACF,MAAM,WAAW,MAAM,UAAU,YAAY,OAAO,OAAO;AAC3D,MAAI,CAAC,YAAY,EAAE,oBAAoB,OAAO;AAC5C,cAAW,qBAAqB,OAAO,OAAO;AAC9C,UAAO;;EAET,MAAM,WAAW,MAAM,SAAS,aAAa;AAC7C,MAAI,OAAO,aAAa,UAAU;AAChC,cAAW,0BAA0B;AACrC,UAAO;;AAET,SAAO;UACA,KAAc;AACrB,aAAW,0BAA0B,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GAAG;AACxF,SAAO;;;AAIX,YAAY;CACV,SAAS;EACP,IAAI;EACJ,MAAM;EACN,aAAa;EACb,YAAY,CACV;GAAE,MAAM;GAAU,aAAa;GAAgC,UAAU;GAAO,EAChF;GAAE,MAAM;GAAQ,aAAa;GAAqB,UAAU;GAAO,CACpE;EACF;CACD,SAAS,EACP,SAAS,OAAO,YAA6D;EAC3E,MAAM,OAAO,MAAM,QAAQ,QAAQ,UAAU,EAAE,CAAC;AAChD,MAAI,CAAC,KAAM;EACX,MAAM,UAAU,iBAAiB;AACjC,MAAI;GACF,MAAM,SAAS,MAAM,QAAQ,QAAQ,KAAK;AAC1C,OAAI,WAAW,KAAA,EAAW,WAAU,OAAO,OAAO,CAAC;AACnD,UAAO;WACA,KAAc;AACrB,cAAW,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;YACpD;AACR,WAAQ,OAAO;;IAGpB;CACF,CAAC;;;AC9DF,YAAY;CACR,SAAS;EACL,IAAI;EACJ,MAAM;EACN,aAAa;EACb,YAAY,CACR;GAAE,MAAM;GAAQ,aAAa;GAA0B,UAAU;GAAM,EACvE;GAAE,MAAM;GAA0B,aAAa;GAAoD,UAAU;GAAO,CACvH;EACJ;CACD,SAAS,EACL,SAAS,OAAO,EAAE,aAA8E;EAC5F,MAAM,OAAO,QAAQ;AACrB,MAAI,CAAC,KAAM;EACX,MAAM,OAAO,QAAQ,0BAAA;EAErB,MAAM,eADgB,qBAAqB,iBAAiB,KAAK,CAC9B,MAAK,MAAK,EAAE,SAAS,KAAK;AAC7D,MAAI,CAAC,cAAc,UAAW;AAC9B,QAAM,eAAe,QAAQ,aAAgC;IAEpE;CACJ,CAAC;;;ACvBF,eAAsB,oBAAoB,MAAoC;CAC1E,MAAM,eAAe,MAAM,iBAAiB,cAAc;AAC1D,KAAI,CAAC,cAAc;AACf,aAAW,yBAAyB;AACpC,SAAO;;AAGX,KAAI;EACA,MAAM,WAAW,MAAM,aAAa,YAAY,KAAK;AACrD,MAAI,EAAE,oBAAoB,OAAO;AAC7B,cAAW,qBAAqB,KAAK;AACrC,UAAO;;AAEX,SAAO;UACF,KAAU;AACf,aAAW,0BAA0B,IAAI,WAAW,MAAM;AAC1D,SAAO;;;AAIf,eAAsB,aAAa,MAAoC;AACnE,KAAI;EACA,MAAM,WAAW,MAAM,KAAK,aAAa;AACzC,MAAI,OAAO,aAAa,UAAU;AAC9B,cAAW,0BAA0B;AACrC,UAAO;;AAEX,SAAO;UACF,KAAU;AACf,aAAW,wBAAwB,IAAI,WAAW,MAAM;AACxD,SAAO;;;AAIf,eAAsB,sBAAsB,WAAyC;CACjF,MAAM,QAAkB,EAAE;CAC1B,MAAM,WAAW,MAAM,UAAU,aAAa,KAAK;AAEnD,MAAK,MAAM,SAAS,UAAU;AAC1B,MAAI,iBAAiB,MAAM;AACvB,SAAM,KAAK,MAAM,kBAAkB,CAAC;AACpC;;AAEJ,MAAI,iBAAiB,UACjB,OAAM,KAAK,GAAG,MAAM,sBAAsB,MAAM,CAAC;;AAIzD,QAAO;;;;AChDX,YAAY;CACR,SAAS;EACL,IAAI;EACJ,MAAM;EACN,aAAa;EACb,YAAY,CACR;GACI,MAAM;GACN,aAAa;GACb,UAAU;GACb,CACJ;EACD,QAAQ,CACJ;GACI,MAAM;GACN,aAAa;GAChB,CACJ;EACJ;CACD,SAAS,EACL,SAAS,OAAO,EAAE,aAAkB;EAChC,MAAM,OAAO,QAAQ;AACrB,MAAI,CAAC,MAAM;AACP,cAAW,yBAAyB;AACpC;;EAGJ,MAAM,OAAO,MAAM,oBAAoB,KAAK;AAC5C,MAAI,CAAC,KAAM;AAEX,SAAO,aAAa,KAAK;IAEhC;CACJ,CAAC;;;AClCF,YAAY;CACR,SAAS;EACL,IAAI;EACJ,MAAM;EACN,aAAa;EACb,YAAY,CACR;GACI,MAAM;GACN,aAAa;GACb,UAAU;GACb,CACJ;EACD,QAAQ,CACJ;GACI,MAAM;GACN,aAAa;GAChB,CACJ;EACJ;CACD,SAAS,EACL,SAAS,OAAO,EAAE,aAAkB;EAChC,MAAM,YAAY,MAAM,iBAAiB,cAAc;AACvD,MAAI,CAAC,UAAW,QAAO;EAEvB,MAAM,OAAO,QAAQ;AACrB,MAAI,CAAC,KAAM,QAAO;AAElB,MAAI;AAEA,UADiB,MAAM,UAAU,YAAY,KAAK,YACvB;UACvB;AACJ,UAAO;;IAGlB;CACJ,CAAC;;;AClCF,SAAS,WAAW,KAAuC;AACvD,QAAO,eAAe,QAAQ,eAAe;;AAGjD,IAAM,iBAAiB,CAAC,WAAW,sBAAsB,KAAK,CAAC;AAC/D,IAAM,uBAAuB;CACzB,MAAM,YAAY,sBAAsB,KAAK;AAC7C,KAAI,CAAC,WAAW,UAAU,CAAE,QAAO;AACnC,KAAI,qBAAqB,aAAa,UAAU,WAAW,KAAK,KAAA,EAAW,QAAO;AAClF,QAAO;;AAGX,qBAAqB,qBAAqB,sBAAsB;CAC5D,MAAM;CACN,SAAS;CACT,MAAM;CACN,OAAO;CACP,QAAQ,EAAE,KAAK,MAAM;CACxB,CAAC;AAEF,qBAAqB,qBAAqB,sBAAsB;CAC5D,MAAM;CACN,SAAS;CACT,MAAM;CACN,OAAO;CACP,QAAQ,EAAE,KAAK,MAAM;CACxB,CAAC;AAEF,qBAAqB,qBAAqB,4BAA4B;CAClE,MAAM;CACN,SAAS;CACT,MAAM;CACN,OAAO;CACP;CACH,CAAC;AAEF,qBAAqB,qBAAqB,4BAA4B;CAClE,MAAM;CACN,SAAS;CACT,MAAM;CACN,OAAO;CACP,UAAU;CACb,CAAC;AAEF,qBAAqB,qBAAqB,gCAAgC;CACtE,MAAM;CACN,SAAS;CACT,MAAM;CACN,OAAO;CACP,QAAQ,EAAE,KAAK,MAAM;CACxB,CAAC;AAEF,qBAAqB,qBAAqB,gCAAgC;CACtE,MAAM;CACN,SAAS;CACT,MAAM;CACN,OAAO;CACP;CACH,CAAC;AAEF,qBAAqB,qBAAqB,gCAAgC;CACtE,MAAM;CACN,SAAS;CACT,MAAM;CACN,OAAO;CACP,UAAU;CACb,CAAC;;;AClEF,YAAY;CACR,SAAS;EACL,IAAI;EACJ,MAAM;EACN,aAAa;EACb,YAAY,CACR;GACI,MAAM;GACN,aAAa;GACb,UAAU;GACb,EACD;GACI,MAAM;GACN,aAAa;GACb,MAAM;GACN,UAAU;GACb,CACJ;EACD,QAAQ,CACJ;GACI,MAAM;GACN,aAAa;GAChB,CACJ;EACJ;CACD,SAAS,EACL,SAAS,OAAO,EAAE,aAAkB;EAChC,MAAM,OAAO,QAAQ;AACrB,MAAI,CAAC,MAAM;AACP,cAAW,yBAAyB;AACpC;;EAGJ,MAAM,OAAO,MAAM,oBAAoB,KAAK;AAC5C,MAAI,CAAC,KAAM;EAEX,MAAM,WAAW,QAAQ,QAAQ,SAAS,OAAO,OAAO,GAAG,GAAG;AAC9D,MAAI,OAAO,MAAM,SAAS,IAAI,WAAW,GAAG;AACxC,cAAW,6CAA6C;AACxD;;EAGJ,MAAM,WAAW,MAAM,aAAa,KAAK;AACzC,MAAI,CAAC,SAAU;AAEf,SAAO,SAAS,MAAM,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,KAAK,KAAK;IAEhE;CACJ,CAAC;;;AC/CF,YAAY;CACR,SAAS;EACL,IAAI;EACJ,MAAM;EACN,aAAa;EACb,YAAY,CACR;GACI,MAAM;GACN,aAAa;GACb,UAAU;GACb,EACD;GACI,MAAM;GACN,aAAa;GACb,MAAM;GACN,UAAU;GACb,CACJ;EACD,QAAQ,CACJ;GACI,MAAM;GACN,aAAa;GAChB,CACJ;EACJ;CACD,SAAS,EACL,SAAS,OAAO,EAAE,aAAkB;EAChC,MAAM,YAAY,MAAM,iBAAiB,cAAc;AACvD,MAAI,CAAC,WAAW;AACZ,cAAW,yBAAyB;AACpC,UAAO,EAAE;;EAGb,MAAM,OAAO,QAAQ;EACrB,MAAM,YAAY,QAAQ,cAAc,QAAQ,QAAQ,cAAc;AAEtE,MAAI;GACA,IAAI,YAAuB;AAC3B,OAAI,MAAM;IACN,MAAM,WAAW,MAAM,UAAU,YAAY,KAAK;AAClD,QAAI,CAAC,UAAU;AACX,gBAAW,mBAAmB,OAAO;AACrC,YAAO,EAAE;;AAEb,QAAI,EAAE,oBAAoB,YAAY;AAClC,gBAAW,4BAA4B,OAAO;AAC9C,YAAO,EAAE;;AAEb,gBAAY;;AAGhB,OAAI,WAAW;IACX,MAAM,QAAQ,MAAM,sBAAsB,UAAU;IACpD,MAAM,SAAuD,EAAE;AAC/D,SAAK,MAAM,YAAY,OAAO;KAC1B,MAAM,OAAO,MAAM,UAAU,YAAY,SAAS;AAClD,SAAI,EAAE,gBAAgB,MAAO;AAC7B,YAAO,KAAK;MAAE,MAAM;MAAU,MAAM,MAAM,KAAK,MAAM;MAAE,CAAC;;AAE5D,WAAO;;GAGX,MAAM,WAAW,MAAM,UAAU,aAAa,KAAK;GACnD,MAAM,SAAuD,EAAE;AAC/D,QAAK,MAAM,SAAS,UAAU;AAC1B,QAAI,EAAE,iBAAiB,MAAO;AAC9B,WAAO,KAAK;KAAE,MAAM,MAAM,kBAAkB;KAAE,MAAM,MAAM,MAAM,MAAM;KAAE,CAAC;;AAE7E,UAAO;WACF,KAAU;AACf,cAAW,yBAAyB,IAAI,WAAW,MAAM;AACzD,UAAO,EAAE;;IAGpB;CACJ,CAAC;;;AC1EF,SAAS,oBAAoB,WAA2B;AACpD,QAAO,UAAU,QAAQ,QAAQ,GAAG,CAAC,QAAQ,QAAQ,GAAG;;AAG5D,SAAS,2BAA+C;CACpD,MAAM,YAAY,sBAAsB,KAAK;AAC7C,KAAI,qBAAqB,UACrB,QAAO,UAAU,kBAAkB;AAEvC,KAAI,qBAAqB,KACrB,QAAO,UAAU,WAAW,EAAE,kBAAkB;;AAKxD,SAAS,SAAS,UAA8B,MAAsB;AAClE,KAAI,CAAC,SAAU,QAAO;AACtB,QAAO,GAAG,SAAS,GAAG;;AAG1B,eAAe,qBAAqB,UAA2D;CAC3F,MAAM,eAAe,MAAM,iBAAiB,cAAc;AAC1D,KAAI,CAAC,cAAc;AACf,aAAW,yBAAyB;AACpC;;CAGJ,MAAM,WAAW;CACjB,IAAI,YAAY,SAAS,UAAU,SAAS;CAC5C,IAAI,WAAW,MAAM,aAAa,YAAY,UAAU;AACxD,KAAI,CAAC,SACD,QAAO;CAGX,IAAI,SAAS;AACb,QAAO,MAAM;AACT,cAAY,SAAS,UAAU,GAAG,SAAS,IAAI,OAAO,GAAG;AACzD,aAAW,MAAM,aAAa,YAAY,UAAU;AACpD,MAAI,CAAC,SACD,QAAO;AAEX;;;AAIR,YAAY;CACR,SAAS;EACL,IAAI;EACJ,MAAM;EACN,aAAa;EACb,YAAY,CACR;GACI,MAAM;GACN,aAAa;GACb,UAAU;GACb,EACD;GACI,MAAM;GACN,aAAa;GACb,UAAU;GACb,CACJ;EACD,QAAQ,CACJ;GACI,MAAM;GACN,aAAa;GAChB,CACJ;EACJ;CACD,SAAS,EACL,SAAS,OAAO,EAAE,aAAkB;EAChC,MAAM,MAAM,QAAQ;EACpB,IAAI,OAAO,QAAQ;EACnB,MAAM,cAAc,MAAM,qBAAqB,0BAA0B,CAAC;AAC1E,MAAI,CAAC,YAAa;AAElB,MAAI,OAAO,CAAC,MAAM;AACd,UAAO,MAAM,aAAa,6BAA6B,QAAQ,YAAY;AAC3E,OAAI,CAAC,KAAM;;EAGf,MAAM,aAAa,KAAK,WAAW,IAAI;EACvC,IAAI,iBAAiB,oBAAoB,KAAK;AAC9C,MAAI,CAAC,gBAAgB;AACjB,cAAW,iCAAiC;AAC5C;;AAGJ,MAAI,CAAC,YAAY;GACb,MAAM,WAAW,0BAA0B;AAC3C,OAAI,YAAY,CAAC,eAAe,WAAW,WAAW,IAAI,CACtD,kBAAiB,GAAG,SAAS,GAAG;;EAIxC,MAAM,eAAe,MAAM,iBAAiB,cAAc;AAC1D,MAAI,CAAC,cAAc;AACf,cAAW,yBAAyB;AACpC;;EAGJ,MAAM,mBAAmB,MAAM,aAAa,YAAY,eAAe;AACvE,MAAI,4BAA4B,WAAW;AACvC,aAAU,0BAA0B,iBAAiB;AACrD,UAAO;;AAEX,MAAI,4BAA4B,MAAM;AAClC,cAAW,mDAAmD,eAAe,IAAI;AACjF;;AAIJ,MAAI,EADqB,MAAM,aAAa,YAAY,GAAG,eAAe,IAAI,EAAE,QAAQ,MAAM,CAAC,YAC7D,YAAY;AAC1C,cAAW,4BAA4B,iBAAiB;AACxD;;AAGJ,YAAU,mBAAmB,iBAAiB;AAC9C,SAAO;IAEd;CACJ,CAAC;;;ACzHF,YAAY;CACR,SAAS;EACL,IAAI;EACJ,MAAM;EACN,aAAa;EACb,YAAY;EACZ,YAAY,CACR;GACI,MAAM;GACN,aAAa;GACb,UAAU;GACb,EACD;GACI,MAAM;GACN,aAAa;GACb,UAAU;GACb,CACJ;EACJ;CACD,SAAS,EACL,SAAS,OAAO,YAAiB;EAC7B,MAAM,eAAe,MAAM,iBAAiB,cAAc;AAC1D,MAAI,CAAC,cAAc;AACf,cAAW,yBAAyB;AACpC;;EAGJ,MAAM,OAAO,QAAQ,QAAQ;EAC7B,IAAI,WAAgB;AAEpB,MAAI,KACA,YAAW,MAAM,aAAa,YAAY,KAAK;AAEnD,MAAI,CAAC,SACD,YAAW,sBAAsB,KAAK;AAE1C,MAAI,CAAC,UAAU;AACX,cAAW,kCAAkC;AAC7C;;EAGJ,MAAM,cAAc,SAAS,SAAS;EACtC,MAAM,UAAU,QAAQ,QAAQ,WAAW,MAAM,aAAa,uBAAuB,YAAY,KAAK,YAAY;AAClH,MAAI,CAAC,WAAW,YAAY,YAAa;AAEzC,MAAI;AACA,SAAM,SAAS,OAAO,QAAQ;AAC9B,aAAU,wBAAwB,UAAU;WACvC,KAAU;AACf,cAAW,oBAAoB,YAAY,IAAI,IAAI,WAAW,MAAM;;IAG/E;CACJ,CAAC;;;ACrDF,YAAY;CACR,SAAS;EACL,IAAI;EACJ,MAAM;EACN,aAAa;EACb,YAAY;EACZ,YAAY,CACR;GACI,MAAM;GACN,aAAa;GACb,UAAU;GACb,EACD;GACI,MAAM;GACN,aAAa;GACb,UAAU;GACb,CACJ;EACJ;CACD,SAAS,EACL,SAAS,OAAO,YAAiB;EAC7B,MAAM,eAAe,MAAM,iBAAiB,cAAc;AAC1D,MAAI,CAAC,cAAc;AACf,cAAW,yBAAyB;AACpC;;EAGJ,MAAM,OAAO,QAAQ,QAAQ;EAC7B,IAAI,WAAgB;AAEpB,MAAI,KACA,YAAW,MAAM,aAAa,YAAY,KAAK;AAEnD,MAAI,CAAC,SACD,YAAW,sBAAsB,KAAK;AAE1C,MAAI,CAAC,UAAU;AACX,cAAW,kCAAkC;AAC7C;;AAGJ,MAAI,oBAAoB,aAAa,SAAS,WAAW,KAAK,KAAA,GAAW;AACrE,cAAW,qEAAmE;AAC9E;;EAGJ,MAAM,eAAe,SAAS,kBAAkB;EAChD,MAAM,eAAe,QAAQ,QAAQ;AACrC,MAAI,iBAAiB,KAAA,KAAa,iBAAiB;OAE3C,CADQ,MAAM,cAAc,mCAAmC,aAAa,GAAG,CACzE;;AAGd,MAAI;AACA,SAAM,SAAS,QAAQ;AACvB,aAAU,uBAAuB,aAAa;WACzC,KAAU;AACf,cAAW,YAAY,aAAa,yBAAyB,IAAI,WAAW,MAAM;;IAG7F;CACJ,CAAC;;;AC/DF,YAAY;CACR,SAAS;EACL,IAAI;EACJ,MAAM;EACN,aAAa;EACb,YAAY,CACR;GACI,MAAM;GACN,aAAa;GACb,UAAU;GACb,EACD;GACI,MAAM;GACN,aAAa;GACb,MAAM;GACN,UAAU;GACb,CACJ;EACD,QAAQ,CACJ;GACI,MAAM;GACN,aAAa;GAChB,CACJ;EACJ;CACD,SAAS,EACL,SAAS,OAAO,EAAE,aAAkB;EAChC,MAAM,OAAO,QAAQ;AACrB,MAAI,CAAC,MAAM;AACP,cAAW,yBAAyB;AACpC;;EAGJ,MAAM,OAAO,MAAM,oBAAoB,KAAK;AAC5C,MAAI,CAAC,KAAM;EAEX,MAAM,WAAW,QAAQ,QAAQ,SAAS,OAAO,OAAO,GAAG,GAAG;AAC9D,MAAI,OAAO,MAAM,SAAS,IAAI,WAAW,GAAG;AACxC,cAAW,6CAA6C;AACxD;;EAGJ,MAAM,WAAW,MAAM,aAAa,KAAK;AACzC,MAAI,CAAC,SAAU;AAEf,SAAO,SAAS,MAAM,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,KAAK;IAE9D;CACJ,CAAC;;;AC9CF,YAAY;CACR,SAAS;EACL,IAAI;EACJ,MAAM;EACN,aAAa;EACb,YAAY;GACR;IACI,MAAM;IACN,aAAa;IACb,UAAU;IACb;GACD;IACI,MAAM;IACN,aAAa;IACb,UAAU;IACb;GACD;IACI,MAAM;IACN,aAAa;IACb,UAAU;IACb;GACD;IACI,MAAM;IACN,aAAa;IACb,UAAU;IACb;GACJ;EACD,QAAQ,CACJ;GACI,MAAM;GACN,aAAa;GAChB,CACJ;EACJ;CACD,SAAS,EACL,SAAS,OAAO,EAAE,aAAkB;EAChC,IAAI,OAAO,QAAQ;EACnB,MAAM,WAAW,QAAQ;EACzB,MAAM,MAAM,QAAQ;EACpB,MAAM,YAAY,QAAQ;AAE1B,MAAI,OAAO,CAAC,MAAM;AACd,UAAO,MAAM,aAAa,sEAAsE,QAAQ,GAAG;AAC3G,OAAI,CAAC,KAAM;;AAGf,MAAI,aAAa,CAAC,KAAK,SAAS,UAAU,CACtC,SAAQ;AAIZ,MAAI,CADe,KAAK,WAAW,IAAI,EACtB;GACb,MAAM,YAAY,sBAAsB,KAAK;GAC7C,MAAM,UAAU,qBAAqB,YAC/B,UAAU,kBAAkB,GAC5B,qBAAqB,OACjB,UAAU,WAAW,EAAE,kBAAkB,GACzC,KAAA;AACV,OAAI,WAAW,CAAC,KAAK,WAAW,UAAU,IAAI,CAC1C,QAAO,UAAU,MAAM;QAG3B,QAAO,KAAK,MAAM,EAAE;EAGxB,MAAM,eAAe,MAAM,iBAAiB,cAAc;AAC1D,MAAI,CAAC,cAAc;AACf,cAAW,yBAAyB;AACpC;;AAIJ,MADyB,MAAM,aAAa,YAAY,KAAK;OAGrD,CADc,MAAM,cAAc,SAAS,KAAK,gDAAgD,CACpF;;EAGpB,MAAM,kBAAkB,MAAM,aAAa,YAAY,MAAM,EAAE,QAAQ,MAAM,CAAC;AAC9E,MAAI,EAAE,2BAA2B,OAAO;AACpC,cAAW,4BAA4B,KAAK;AAC5C;;AAGJ,MAAI,SACA,OAAM,gBAAgB,aAAa,SAAS;AAGhD,YAAU,iBAAiB,OAAO;AAClC,SAAO;IAEd;CACJ,CAAC;;;AC1FF,YAAY;CACR,SAAS;EACL,IAAI;EACJ,MAAM;EACN,aAAa;EACb,YAAY,CACR;GACI,MAAM;GACN,aAAa;GACb,UAAU;GACb,EACD;GACI,MAAM;GACN,aAAa;GACb,UAAU;GACb,CACJ;EACJ;CACD,SAAS;EACL,aAAa,YAAiB;GAC1B,IAAI,WAAmB,QAAQ,QAAQ;AACvC,OAAI,CAAC,UAAU;IACX,MAAM,eAAe,sBAAsB,KAAK;AAChD,QAAI,CAAC,gBAAgB,EAAE,UAAU,cAAe,QAAO;AACvD,eAAW,aAAa;;AAE5B,UAAO,SAAS,aAAa,CAAC,SAAS,OAAO;;EAElD,SAAS,OAAO,YAAiB;GAC7B,IAAI,WAAmB,QAAQ,QAAQ;AACvC,OAAI,CAAC,SAED,YADqB,sBAAsB,KAAK,CACxB;GAG5B,MAAM,eAAe,MAAM,iBAAiB,cAAc;AAC1D,OAAI,CAAC,cAAc;AACf,eAAW,yBAAyB;AACpC;;AAGJ,SAAM,YAAY,SAAS,sBAAsB,OAAO,aAAkB;AACtE,QAAI;KACA,MAAM,eAAe,MAAM,aAAa,YAAY,SAAS;AAC7D,SAAI,CAAC,cAAc;AACf,iBAAW,qBAAqB,SAAS;AACzC;;KAGJ,IAAI,eAAe,QAAQ,QAAQ;AACnC,SAAI,CAAC,aAED,iBADiB,SAAS,MAAM,IAAI,CAAC,KAAK,IAAI,aACtB,QAAQ,WAAW,GAAG,GAAG;AAGrD,cAAS,UAAU;AACnB,cAAS,WAAW;AACpB,WAAM,aAAa,YAAY,cAAc,EAAE,QAAQ,MAAM,CAAC;KAG9D,MAAM,OAAO,MADA,aACW,YAAY,EAAE,MAAM,MAAM,CAAC;KACnD,MAAM,MAAM,MAAM,MAAM,UAAU,KAAK;KACvC,MAAM,aAAa,OAAO,OAAO,IAAI,MAAM,CAAC,QAAO,UAAS,CAAC,MAAM,IAAI,CAAC;KACxE,IAAI,iBAAiB;AAErB,cAAS,UAAU,iBAAiB,aAAa,QAAQ,OAAO,GAAG,CAAC;AAEpE,UAAK,MAAM,CAAC,cAAc,aAAa,OAAO,QAAQ,IAAI,MAAM,EAAE;AAC9D,UAAI,SAAS,IAAK;MAElB,MAAM,YAAY,MAAM,SAAS,MAAM,OAAO;MAC9C,MAAM,WAAW,GAAG,eAAe;AAGnC,aAFsB,MAAM,aAAa,YAAY,UAAU,EAAE,QAAQ,MAAM,CAAC,EAElE,aAAa,WAAW,EAAE,aAAa,gBAAgB,QAAQ,CAAC;AAE9E;AACA,eAAS,WAAW,KAAK,MAAO,iBAAiB,aAAc,IAAI;AACnE,eAAS,UAAU,cAAc,eAAe,GAAG,WAAW;;AAGlE,cAAS,WAAW;AACpB,eAAU,wBAAwB,aAAa,QAAQ,OAAO,GAAG,CAAC,IAAI,eAAe,UAAU;aAC1F,KAAU;AACf,gBAAW,gCAAgC,IAAI;AAC/C,WAAM;;KAEZ;;EAET;CACJ,CAAC;;;AC7FF,YAAY;CACR,SAAS;EACL,IAAI;EACJ,MAAM;EACN,aAAa;EACb,YAAY,CACR;GACI,MAAM;GACN,aAAa;GACb,UAAU;GACb,CACJ;EACD,QAAQ;GACJ;IACI,MAAM;IACN,aAAa;IAChB;GACD;IACI,MAAM;IACN,aAAa;IAChB;GACD;IACI,MAAM;IACN,aAAa;IAChB;GACJ;EACJ;CACD,SAAS,EACL,SAAS,OAAO,EAAE,aAAkB;EAChC,MAAM,OAAO,QAAQ;AACrB,MAAI,CAAC,MAAM;AACP,cAAW,yBAAyB;AACpC;;EAGJ,MAAM,OAAO,MAAM,oBAAoB,KAAK;AAC5C,MAAI,CAAC,KAAM;EAEX,MAAM,WAAW,MAAM,aAAa,KAAK;AACzC,MAAI,CAAC,SAAU;EAEf,MAAM,QAAQ,SAAS,MAAM,KAAK;EAClC,MAAM,UAAU,SAAS,MAAM;EAC/B,MAAM,YAAY,YAAY,KAAK,IAAI,QAAQ,MAAM,MAAM,CAAC,QAAO,MAAK,EAAE,SAAS,EAAE,CAAC;AAEtF,SAAO;GACH,OAAO,MAAM;GACb,OAAO;GACP,YAAY,SAAS;GACxB;IAER;CACJ,CAAC;;;AClDF,SAAS,mBAA2B;AAChC,QAAO,oCAAmB,IAAI,MAAM,EAAC,aAAa,CAAC,QAAQ,SAAS,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,MAAM,GAAG,GAAG;;AAG3G,SAAS,gBAAgB,KAAqB;AAC1C,KAAI,IAAI,WAAW,QAAQ,CACvB,QAAO,kBAAkB;AAE7B,KAAI;EACA,MAAM,OAAO,IAAI,IAAI,IAAI,CAAC,SAAS,MAAM,IAAI,CAAC,QAAQ,MAAM,EAAE,SAAS,EAAE;EACzE,MAAM,OAAO,KAAK,KAAK,SAAS;AAChC,MAAI,MAAM,SAAS,IAAI,IAAI,CAAC,KAAK,SAAS,IAAI,CAAE,QAAO;SACnD;AAGR,QAAO,kBAAkB;;AAG7B,SAAS,mBAAmB,KAAsB;AAC9C,KAAI;EACA,MAAM,EAAE,aAAa,IAAI,IAAI,IAAI;AACjC,SAAO,aAAa,WAAW,aAAa,YAAY,aAAa,WAAW,aAAa;SACzF;AACJ,SAAO;;;AAIf,YAAY;CACR,SAAS;EACL,IAAI;EACJ,MAAM;EACN,aAAa;EACb,YAAY;GACR;IAAE,MAAM;IAAO,aAAa;IAAmC,UAAU;IAAM;GAC/E;IAAE,MAAM;IAAY,aAAa;IAAwE,UAAU;IAAO;GAC1H;IACI,MAAM;IACN,aAAa;IACb,UAAU;IACb;GACJ;EACJ;CACD,SAAS;EACL,aAAa,YAAiB;GAC1B,MAAM,MAAM,QAAQ,QAAQ;AAC5B,UAAO,QAAQ,OAAO,mBAAmB,IAAI,CAAC;;EAElD,SAAS,OAAO,YAAiB;GAC7B,MAAM,MAAM,QAAQ,QAAQ;AAC5B,OAAI,CAAC,KAAK;AACN,eAAW,mBAAmB;AAC9B;;GAGJ,MAAM,eAAe,MAAM,iBAAiB,cAAc;AAC1D,OAAI,CAAC,cAAc;AACf,eAAW,yBAAyB;AACpC;;GAKJ,MAAM,mBADF,OAAO,QAAQ,QAAQ,aAAa,WAAW,QAAQ,OAAO,SAAS,MAAM,GAAG,OAC5C,gBAAgB,IAAI;GAC5D,IAAI;GACJ,MAAM,aAAa,QAAQ,QAAQ;AAEnC,OAAI,YAAY;IACZ,MAAM,UAAU,MAAM,iBAAiB,YAAY;IACnD,MAAM,cAAc,QAAQ,SAAS,IAAI,QAAQ,GAAG,OAAO;IAC3D,MAAM,WAAW,WAAW,SAAS,IAAI,GAAG,aAAc,cAAc,GAAG,YAAY,GAAG,eAAe;IACzG,MAAM,cAAc,SAAS,MAAM,IAAI,CAAC,KAAK,IAAI;AACjD,eAAW,YAAY,SAAS,IAAI,IAAI,gBAAgB,WAClD,WACA,GAAG,SAAS,QAAQ,OAAO,GAAG,CAAC,GAAG;UACrC;IACH,MAAM,YAAY,MAAM,kBAAkB,YAAY;AACtD,QAAI,aAAa,KAAM;AACvB,eAAW,GAAG,UAAU,GAAG;;AAG/B,SAAM,YAAY,SAAS,oBAAoB,OAAO,aAAkB;AACpE,aAAS,UAAU;AACnB,aAAS,WAAW;AAEpB,QAAI;KACA,MAAM,WAAW,MAAM,MAAM,KAAK;MAAE,MAAM;MAAQ,aAAa;MAAQ,CAAC;AACxE,SAAI,CAAC,SAAS,IAAI;AACd,iBAAW,8BAA8B,SAAS,WAAW;AAC7D;;KAGJ,IAAI,WAAW,QAAQ,QAAQ;AAC/B,SAAI,CAAC,UAAU;MACX,MAAM,qBAAqB,SAAS,QAAQ,IAAI,sBAAsB;AACtE,UAAI,oBAAoB;OACpB,MAAM,QAAQ,mBAAmB,MAAM,0BAA0B;AACjE,WAAI,QAAQ,GAAI,YAAW,MAAM,GAAG,MAAM;;;AAGlD,SAAI,CAAC,SAAU,YAAW;KAE1B,MAAM,YAAY,SAAS,SAAS,IAAI,GAAG,SAAS,QAAQ,YAAY,IAAI,WAAW,GAAG;AAC1F,cAAS,UAAU,eAAe,SAAS;AAC3C,cAAS,WAAW;AAGpB,YADuB,MAAM,aAAa,YAAY,WAAW,EAAE,QAAQ,MAAM,CAAC,EAC7D,aAAa,SAAS,MAAM,EAAE,aAAa,gBAAgB,QAAQ,CAAC;AAEzF,cAAS,WAAW;AACpB,eAAU,oBAAoB,WAAW;aACpC,KAAK;AACV,gBAAW,8BAA8B,OAAO,IAAI,CAAC;AACrD,WAAM;;KAEZ;;EAET;CACJ,CAAC;;;ACpHF,YAAY,IAAI,aAAa,kBAAU;AACvC,UAAU,IAAI,QAAQ,KAAK;AAC3B,UAAU,IAAI,UAAU,OAAO;AAC/B,UAAU,IAAI,aAAa,UAAU;AACrC,UAAU,IAAI,cAAc,WAAW;AACvC,UAAU,IAAI,gBAAgB,aAAa;AAC3C,UAAU,IAAI,WAAW,QAAQ;AACjC,UAAU,IAAI,aAAa,UAAU;;;ACFrC,IAAI,kBAAmC,EAAE;;;;;AAMzC,SAAgB,mBAAmB,QAA+B;AAC9D,mBAAkB;EAAE,GAAG;EAAiB,GAAG;EAAQ;;;;;AAMvD,SAAgB,qBAAgD;AAC5D,QAAO,EAAE,GAAG,iBAAiB"}
|