angular-grab 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +215 -0
- package/examples/angular-19-app/.editorconfig +17 -0
- package/examples/angular-19-app/.vscode/extensions.json +4 -0
- package/examples/angular-19-app/.vscode/launch.json +20 -0
- package/examples/angular-19-app/.vscode/mcp.json +9 -0
- package/examples/angular-19-app/.vscode/tasks.json +42 -0
- package/examples/angular-19-app/README.md +59 -0
- package/examples/angular-19-app/angular.json +74 -0
- package/examples/angular-19-app/package.json +44 -0
- package/examples/angular-19-app/public/favicon.ico +0 -0
- package/examples/angular-19-app/src/app/app.config.ts +13 -0
- package/examples/angular-19-app/src/app/app.css +37 -0
- package/examples/angular-19-app/src/app/app.html +25 -0
- package/examples/angular-19-app/src/app/app.routes.ts +3 -0
- package/examples/angular-19-app/src/app/app.spec.ts +23 -0
- package/examples/angular-19-app/src/app/app.ts +12 -0
- package/examples/angular-19-app/src/app/button/button.component.ts +25 -0
- package/examples/angular-19-app/src/app/card/card.component.ts +33 -0
- package/examples/angular-19-app/src/app/header/header.component.ts +31 -0
- package/examples/angular-19-app/src/app/popover/popover.component.ts +133 -0
- package/examples/angular-19-app/src/index.html +13 -0
- package/examples/angular-19-app/src/main.ts +6 -0
- package/examples/angular-19-app/src/styles.css +1 -0
- package/examples/angular-19-app/tsconfig.app.json +15 -0
- package/examples/angular-19-app/tsconfig.json +33 -0
- package/examples/angular-19-app/tsconfig.spec.json +15 -0
- package/package.json +14 -111
- package/packages/angular-grab/package.json +96 -0
- package/packages/angular-grab/src/angular/__tests__/context-builder.test.ts +216 -0
- package/packages/angular-grab/src/angular/angular-grab.service.ts +62 -0
- package/packages/angular-grab/src/angular/index.ts +13 -0
- package/packages/angular-grab/src/angular/provide-angular-grab.ts +22 -0
- package/packages/angular-grab/src/angular/resolvers/component-resolver.ts +71 -0
- package/packages/angular-grab/src/angular/resolvers/context-builder.ts +86 -0
- package/packages/angular-grab/src/angular/resolvers/ng-utils.ts +14 -0
- package/packages/angular-grab/src/angular/resolvers/source-resolver.ts +61 -0
- package/packages/angular-grab/src/builder/__tests__/builder.test.ts +72 -0
- package/packages/angular-grab/src/builder/builders/application/index.ts +13 -0
- package/packages/angular-grab/src/builder/builders/dev-server/index.ts +9 -0
- package/packages/angular-grab/src/builder/index.ts +3 -0
- package/packages/angular-grab/src/cli/__tests__/cli.test.ts +239 -0
- package/packages/angular-grab/src/cli/commands/init.ts +106 -0
- package/packages/angular-grab/src/cli/index.ts +15 -0
- package/packages/angular-grab/src/cli/utils/detect-project.ts +78 -0
- package/packages/angular-grab/src/cli/utils/modify-angular-json.ts +42 -0
- package/packages/angular-grab/src/cli/utils/modify-app-config.ts +42 -0
- package/packages/angular-grab/src/core/__tests__/generate-snippet.test.ts +149 -0
- package/packages/angular-grab/src/core/__tests__/plugin-registry.test.ts +286 -0
- package/packages/angular-grab/src/core/__tests__/store.test.ts +118 -0
- package/packages/angular-grab/src/core/__tests__/utils.test.ts +85 -0
- package/packages/angular-grab/src/core/clipboard/copy.ts +104 -0
- package/packages/angular-grab/src/core/clipboard/generate-snippet.ts +38 -0
- package/packages/angular-grab/src/core/constants.ts +10 -0
- package/packages/angular-grab/src/core/grab.ts +596 -0
- package/packages/angular-grab/src/core/index.global.ts +13 -0
- package/packages/angular-grab/src/core/index.ts +19 -0
- package/packages/angular-grab/src/core/keyboard/keyboard-handler.ts +163 -0
- package/packages/angular-grab/src/core/overlay/crosshair.ts +107 -0
- package/packages/angular-grab/src/core/overlay/freeze-overlay.ts +239 -0
- package/packages/angular-grab/src/core/overlay/overlay-renderer.ts +180 -0
- package/packages/angular-grab/src/core/overlay/select-feedback.ts +108 -0
- package/packages/angular-grab/src/core/overlay/toast.ts +175 -0
- package/packages/angular-grab/src/core/picker/element-picker.ts +114 -0
- package/packages/angular-grab/src/core/plugins/plugin-registry.ts +83 -0
- package/packages/angular-grab/src/core/store.ts +52 -0
- package/packages/angular-grab/src/core/toolbar/actions-menu.ts +178 -0
- package/packages/angular-grab/src/core/toolbar/comment-popover.ts +235 -0
- package/packages/angular-grab/src/core/toolbar/copy-actions.ts +98 -0
- package/packages/angular-grab/src/core/toolbar/history-popover.ts +245 -0
- package/packages/angular-grab/src/core/toolbar/theme-manager.ts +188 -0
- package/packages/angular-grab/src/core/toolbar/toolbar-icons.ts +29 -0
- package/packages/angular-grab/src/core/toolbar/toolbar-renderer.ts +239 -0
- package/packages/angular-grab/src/core/types.ts +139 -0
- package/packages/angular-grab/src/core/utils.ts +16 -0
- package/packages/angular-grab/src/esbuild-plugin/__tests__/transform.test.ts +174 -0
- package/packages/angular-grab/src/esbuild-plugin/index.ts +3 -0
- package/packages/angular-grab/src/esbuild-plugin/plugin.ts +29 -0
- package/packages/angular-grab/src/esbuild-plugin/scan.ts +105 -0
- package/packages/angular-grab/src/esbuild-plugin/transform.ts +152 -0
- package/packages/angular-grab/src/vite-plugin/__tests__/plugin.test.ts +84 -0
- package/packages/angular-grab/src/vite-plugin/index.ts +19 -0
- package/packages/angular-grab/src/webpack-plugin/__tests__/plugin.test.ts +72 -0
- package/packages/angular-grab/src/webpack-plugin/index.ts +2 -0
- package/packages/angular-grab/src/webpack-plugin/loader.ts +15 -0
- package/packages/angular-grab/src/webpack-plugin/plugin.ts +20 -0
- package/packages/angular-grab/tsconfig.json +15 -0
- package/packages/angular-grab/tsup.config.ts +119 -0
- package/pnpm-workspace.yaml +3 -0
- package/turbo.json +21 -0
- package/dist/angular/index.d.ts +0 -151
- package/dist/angular/index.js +0 -2811
- package/dist/angular/index.js.map +0 -1
- package/dist/builder/builders/application/index.js +0 -143
- package/dist/builder/builders/application/index.js.map +0 -1
- package/dist/builder/builders/dev-server/index.js +0 -139
- package/dist/builder/builders/dev-server/index.js.map +0 -1
- package/dist/builder/index.js +0 -2
- package/dist/builder/index.js.map +0 -1
- package/dist/builder/package.json +0 -1
- package/dist/cli/index.js +0 -223
- package/dist/cli/index.js.map +0 -1
- package/dist/core/index.cjs +0 -2589
- package/dist/core/index.cjs.map +0 -1
- package/dist/core/index.d.cts +0 -139
- package/dist/core/index.d.ts +0 -139
- package/dist/core/index.global.js +0 -542
- package/dist/core/index.js +0 -2560
- package/dist/core/index.js.map +0 -1
- package/dist/esbuild-plugin/index.cjs +0 -239
- package/dist/esbuild-plugin/index.cjs.map +0 -1
- package/dist/esbuild-plugin/index.d.cts +0 -26
- package/dist/esbuild-plugin/index.d.ts +0 -26
- package/dist/esbuild-plugin/index.js +0 -200
- package/dist/esbuild-plugin/index.js.map +0 -1
- package/dist/vite-plugin/index.d.ts +0 -7
- package/dist/vite-plugin/index.js +0 -128
- package/dist/vite-plugin/index.js.map +0 -1
- package/dist/webpack-plugin/index.cjs +0 -54
- package/dist/webpack-plugin/index.cjs.map +0 -1
- package/dist/webpack-plugin/index.d.cts +0 -5
- package/dist/webpack-plugin/index.d.ts +0 -5
- package/dist/webpack-plugin/index.js +0 -23
- package/dist/webpack-plugin/index.js.map +0 -1
- package/dist/webpack-plugin/loader.cjs +0 -155
- package/dist/webpack-plugin/loader.cjs.map +0 -1
- package/dist/webpack-plugin/loader.d.cts +0 -3
- package/dist/webpack-plugin/loader.d.ts +0 -3
- package/dist/webpack-plugin/loader.js +0 -122
- package/dist/webpack-plugin/loader.js.map +0 -1
- /package/{builders.json → packages/angular-grab/builders.json} +0 -0
- /package/{dist → packages/angular-grab/src}/builder/builders/application/schema.json +0 -0
- /package/{dist → packages/angular-grab/src}/builder/builders/dev-server/schema.json +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/angular/resolvers/ng-utils.ts","../../src/angular/resolvers/component-resolver.ts","../../src/angular/resolvers/source-resolver.ts","../../src/core/store.ts","../../src/core/constants.ts","../../src/core/overlay/overlay-renderer.ts","../../src/core/overlay/crosshair.ts","../../src/core/utils.ts","../../src/core/overlay/toast.ts","../../src/core/picker/element-picker.ts","../../src/core/keyboard/keyboard-handler.ts","../../src/core/clipboard/generate-snippet.ts","../../src/core/clipboard/copy.ts","../../src/core/plugins/plugin-registry.ts","../../src/core/toolbar/theme-manager.ts","../../src/core/toolbar/toolbar-icons.ts","../../src/core/toolbar/toolbar-renderer.ts","../../src/core/toolbar/history-popover.ts","../../src/core/toolbar/actions-menu.ts","../../src/core/toolbar/comment-popover.ts","../../src/core/toolbar/copy-actions.ts","../../src/core/overlay/freeze-overlay.ts","../../src/core/overlay/select-feedback.ts","../../src/core/grab.ts","../../src/angular/resolvers/context-builder.ts","../../src/angular/angular-grab.service.ts","../../src/angular/provide-angular-grab.ts"],"sourcesContent":["export interface NgDebugApi {\n getComponent<T>(element: Element): T | null;\n getOwningComponent<T>(element: Element): T | null;\n getDirectives(element: Element): any[];\n}\n\nexport function getNgApi(): NgDebugApi | null {\n if (typeof window === 'undefined') return null;\n return (window as any).ng || null;\n}\n\nexport function cleanComponentName(name: string): string {\n return name.startsWith('_') ? name.slice(1) : name;\n}\n","import { getNgApi, cleanComponentName } from './ng-utils';\n\nexport function resolveComponent(element: Element): {\n name: string | null;\n hostElement: Element | null;\n stack: Array<{ name: string; hostElement: Element | null }>;\n} {\n const ng = getNgApi();\n if (!ng) return { name: null, hostElement: null, stack: [] };\n\n const stack: Array<{ name: string; hostElement: Element | null }> = [];\n const seen = new Set<any>();\n\n // Walk up the DOM collecting every Angular component\n let current: Element | null = element;\n while (current) {\n const comp = ng.getComponent(current);\n if (comp && !seen.has(comp)) {\n seen.add(comp);\n stack.push({\n name: cleanComponentName(comp.constructor.name),\n hostElement: current,\n });\n }\n current = current.parentElement;\n }\n\n // If no direct component found, try getOwningComponent for the original element\n if (stack.length === 0) {\n let walk: Element | null = element;\n while (walk) {\n const owning = ng.getOwningComponent(walk);\n if (owning && !seen.has(owning)) {\n seen.add(owning);\n // Find the host element\n let host: Element | null = walk.parentElement;\n while (host) {\n if (ng.getComponent(host) === owning) break;\n host = host.parentElement;\n }\n stack.push({\n name: cleanComponentName(owning.constructor.name),\n hostElement: host ?? walk.parentElement,\n });\n // Continue walking from the host to collect parents\n current = host?.parentElement ?? walk.parentElement?.parentElement ?? null;\n while (current) {\n const comp = ng.getComponent(current);\n if (comp && !seen.has(comp)) {\n seen.add(comp);\n stack.push({\n name: cleanComponentName(comp.constructor.name),\n hostElement: current,\n });\n }\n current = current.parentElement;\n }\n break;\n }\n walk = walk.parentElement;\n }\n }\n\n const closest = stack.length > 0 ? stack[0] : { name: null, hostElement: null };\n\n return {\n name: closest.name,\n hostElement: closest.hostElement,\n stack,\n };\n}\n","import { type NgDebugApi, getNgApi, cleanComponentName } from './ng-utils';\n\ninterface SourceMapEntry {\n file: string;\n line: number;\n}\n\nfunction getSourceMap(): Record<string, SourceMapEntry> | null {\n return (globalThis as any).__ANGULAR_GRAB_SOURCE_MAP__ ?? null;\n}\n\nexport function resolveSource(element: Element): {\n filePath: string | null;\n line: number | null;\n column: number | null;\n} {\n const sourceMap = getSourceMap();\n if (!sourceMap) return { filePath: null, line: null, column: null };\n\n const ng = getNgApi();\n if (!ng) return { filePath: null, line: null, column: null };\n\n // Find the component that owns this element\n const componentName = findComponentName(element, ng);\n if (!componentName) return { filePath: null, line: null, column: null };\n\n const entry = sourceMap[componentName];\n if (!entry) return { filePath: null, line: null, column: null };\n\n return { filePath: entry.file, line: entry.line, column: null };\n}\n\nexport function resolveSourceForComponent(componentName: string): {\n filePath: string | null;\n line: number | null;\n column: number | null;\n} {\n const sourceMap = getSourceMap();\n if (!sourceMap) return { filePath: null, line: null, column: null };\n\n const entry = sourceMap[componentName];\n if (!entry) return { filePath: null, line: null, column: null };\n\n return { filePath: entry.file, line: entry.line, column: null };\n}\n\nfunction findComponentName(element: Element, ng: NgDebugApi): string | null {\n // Try direct component on this element\n const direct = ng.getComponent(element);\n if (direct) return cleanComponentName(direct.constructor.name);\n\n // Walk up to find owning component\n let current: Element | null = element;\n while (current) {\n const owning = ng.getOwningComponent(current);\n if (owning) return cleanComponentName(owning.constructor.name);\n current = current.parentElement;\n }\n\n return null;\n}\n","import type { AngularGrabOptions, ToolbarState } from './types';\n\nexport interface GrabState {\n active: boolean;\n frozen: boolean;\n hoveredElement: Element | null;\n options: AngularGrabOptions;\n toolbar: ToolbarState;\n}\n\nexport type StateListener = (state: GrabState, key: keyof GrabState) => void;\n\nexport interface Store {\n state: GrabState;\n subscribe(listener: StateListener): () => void;\n}\n\nexport function createStore(initialOptions: AngularGrabOptions): Store {\n const listeners = new Set<StateListener>();\n\n const raw: GrabState = {\n active: false,\n frozen: false,\n hoveredElement: null,\n options: initialOptions,\n toolbar: {\n visible: initialOptions.showToolbar,\n themeMode: initialOptions.themeMode,\n history: [],\n pendingAction: null,\n },\n };\n\n const state = new Proxy(raw, {\n set(target, prop, value) {\n const key = prop as keyof GrabState;\n if (target[key] === value) return true;\n\n Reflect.set(target, key, value);\n listeners.forEach((fn) => fn(state, key));\n return true;\n },\n });\n\n return {\n state,\n subscribe(listener: StateListener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n };\n}\n","export const Z_INDEX_FREEZE = 2147483644;\nexport const Z_INDEX_CROSSHAIR = 2147483645;\nexport const Z_INDEX_OVERLAY = 2147483646;\nexport const Z_INDEX_LABEL = 2147483647;\nexport const Z_INDEX_TOOLBAR = 2147483646;\nexport const Z_INDEX_TOAST = 2147483647;\nexport const Z_INDEX_POPOVER = 2147483647;\n\nexport const TOOLBAR_TOAST_OFFSET = '72px';\nexport const TOOLBAR_POPOVER_OFFSET = '68px';\n","import { Z_INDEX_OVERLAY, Z_INDEX_LABEL } from '../constants';\n\nconst OVERLAY_ID = '__ag-overlay__';\nconst LABEL_ID = '__ag-label__';\nconst STYLE_ID = '__ag-styles__';\n\nexport interface OverlayRenderer {\n show(element: Element, componentName: string | null, sourcePath?: string | null, cssClasses?: string[]): void;\n hide(): void;\n isOverlayElement(el: Element): boolean;\n dispose(): void;\n}\n\nexport function createOverlayRenderer(): OverlayRenderer {\n let overlay: HTMLDivElement | null = null;\n let label: HTMLDivElement | null = null;\n let rafId: number | null = null;\n let currentElement: Element | null = null;\n let currentComponentName: string | null = null;\n let currentSourcePath: string | null = null;\n let currentCssClasses: string[] = [];\n\n function injectStyles(): void {\n if (document.getElementById(STYLE_ID)) return;\n\n const style = document.createElement('style');\n style.id = STYLE_ID;\n style.textContent = `\n #${OVERLAY_ID} {\n position: fixed;\n pointer-events: none;\n z-index: ${Z_INDEX_OVERLAY};\n border: 2px solid var(--ag-overlay-border, #3b82f6);\n background: var(--ag-overlay-bg, rgba(59, 130, 246, 0.1));\n transition: top 0.05s ease, left 0.05s ease, width 0.05s ease, height 0.05s ease;\n box-sizing: border-box;\n }\n #${LABEL_ID} {\n position: fixed;\n pointer-events: none;\n z-index: ${Z_INDEX_LABEL};\n background: var(--ag-label-bg, #3b82f6);\n color: var(--ag-label-text, #fff);\n font: 11px/1.4 monospace;\n padding: 2px 6px;\n border-radius: 3px;\n white-space: nowrap;\n box-sizing: border-box;\n max-width: 100vw;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n `;\n document.head.appendChild(style);\n }\n\n function ensureElements(): void {\n if (!overlay) {\n injectStyles();\n overlay = document.createElement('div');\n overlay.id = OVERLAY_ID;\n document.body.appendChild(overlay);\n }\n if (!label) {\n label = document.createElement('div');\n label.id = LABEL_ID;\n document.body.appendChild(label);\n }\n }\n\n function positionOverlay(): void {\n if (!currentElement || !overlay || !label) return;\n\n const rect = currentElement.getBoundingClientRect();\n\n // Hide overlay if element is detached or has zero dimensions\n if (rect.width === 0 && rect.height === 0 && !currentElement.isConnected) {\n overlay.style.display = 'none';\n label.style.display = 'none';\n return;\n }\n\n overlay.style.top = `${rect.top}px`;\n overlay.style.left = `${rect.left}px`;\n overlay.style.width = `${rect.width}px`;\n overlay.style.height = `${rect.height}px`;\n overlay.style.display = 'block';\n\n const tag = currentElement.tagName.toLowerCase();\n let labelText = `<${tag}>`;\n if (currentCssClasses.length > 0) {\n labelText += ` .${currentCssClasses.join('.')}`;\n }\n if (currentComponentName) {\n labelText += ` in ${currentComponentName}`;\n }\n if (currentSourcePath) {\n labelText += ` \\u2014 ${currentSourcePath}`;\n }\n label.textContent = labelText;\n\n // Position label above the element, or below if no room\n const labelHeight = 20;\n const gap = 4;\n let labelTop = rect.top - labelHeight - gap;\n if (labelTop < 0) {\n labelTop = rect.bottom + gap;\n }\n\n // Clamp label horizontally to viewport\n let labelLeft = rect.left;\n label.style.top = `${labelTop}px`;\n label.style.left = `${labelLeft}px`;\n label.style.display = 'block';\n\n // After rendering, check if it overflows right edge\n const labelRect = label.getBoundingClientRect();\n const viewportWidth = document.documentElement.clientWidth;\n if (labelRect.right > viewportWidth) {\n labelLeft = Math.max(0, viewportWidth - labelRect.width);\n label.style.left = `${labelLeft}px`;\n }\n if (labelLeft < 0) {\n label.style.left = '0px';\n }\n }\n\n function trackPosition(): void {\n positionOverlay();\n rafId = requestAnimationFrame(trackPosition);\n }\n\n function stopTracking(): void {\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n rafId = null;\n }\n }\n\n return {\n show(element: Element, componentName: string | null, sourcePath?: string | null, cssClasses?: string[]): void {\n ensureElements();\n currentElement = element;\n currentComponentName = componentName;\n currentSourcePath = sourcePath ?? null;\n currentCssClasses = cssClasses ?? [];\n stopTracking();\n trackPosition();\n },\n\n hide(): void {\n stopTracking();\n currentElement = null;\n currentComponentName = null;\n currentSourcePath = null;\n currentCssClasses = [];\n\n if (overlay) overlay.style.display = 'none';\n if (label) label.style.display = 'none';\n },\n\n isOverlayElement(el: Element): boolean {\n return el === overlay || el === label || el.id === OVERLAY_ID || el.id === LABEL_ID;\n },\n\n dispose(): void {\n stopTracking();\n currentElement = null;\n currentComponentName = null;\n currentSourcePath = null;\n currentCssClasses = [];\n\n overlay?.remove();\n label?.remove();\n document.getElementById(STYLE_ID)?.remove();\n overlay = null;\n label = null;\n },\n };\n}\n","import { Z_INDEX_CROSSHAIR } from '../constants';\n\nconst CROSSHAIR_STYLE_ID = '__ag-crosshair-styles__';\nconst H_LINE_ID = '__ag-crosshair-h__';\nconst V_LINE_ID = '__ag-crosshair-v__';\n\nexport interface Crosshair {\n activate(): void;\n deactivate(): void;\n isCrosshairElement(el: Element): boolean;\n dispose(): void;\n}\n\nexport function createCrosshair(): Crosshair {\n let hLine: HTMLDivElement | null = null;\n let vLine: HTMLDivElement | null = null;\n let listening = false;\n\n function injectStyles(): void {\n if (document.getElementById(CROSSHAIR_STYLE_ID)) return;\n\n const style = document.createElement('style');\n style.id = CROSSHAIR_STYLE_ID;\n style.textContent = `\n .ag-crosshair-line {\n position: fixed;\n pointer-events: none;\n z-index: ${Z_INDEX_CROSSHAIR};\n background: var(--ag-accent, #3b82f6);\n opacity: 0.25;\n transition: none;\n }\n #${H_LINE_ID} {\n left: 0;\n right: 0;\n height: 1px;\n }\n #${V_LINE_ID} {\n top: 0;\n bottom: 0;\n width: 1px;\n }\n body.ag-crosshair-active {\n cursor: crosshair !important;\n }\n `;\n document.head.appendChild(style);\n }\n\n function ensureElements(): void {\n if (!hLine) {\n injectStyles();\n hLine = document.createElement('div');\n hLine.id = H_LINE_ID;\n hLine.className = 'ag-crosshair-line';\n document.body.appendChild(hLine);\n }\n if (!vLine) {\n vLine = document.createElement('div');\n vLine.id = V_LINE_ID;\n vLine.className = 'ag-crosshair-line';\n document.body.appendChild(vLine);\n }\n }\n\n function handleMouseMove(e: MouseEvent): void {\n if (hLine) {\n hLine.style.top = `${e.clientY}px`;\n }\n if (vLine) {\n vLine.style.left = `${e.clientX}px`;\n }\n }\n\n return {\n activate(): void {\n if (listening) return;\n listening = true;\n ensureElements();\n document.body.classList.add('ag-crosshair-active');\n document.addEventListener('mousemove', handleMouseMove, true);\n },\n\n deactivate(): void {\n if (!listening) return;\n listening = false;\n document.body.classList.remove('ag-crosshair-active');\n document.removeEventListener('mousemove', handleMouseMove, true);\n if (hLine) hLine.style.top = '-10px';\n if (vLine) vLine.style.left = '-10px';\n },\n\n isCrosshairElement(el: Element): boolean {\n return el === hLine || el === vLine\n || el.id === H_LINE_ID || el.id === V_LINE_ID;\n },\n\n dispose(): void {\n this.deactivate();\n hLine?.remove();\n vLine?.remove();\n document.getElementById(CROSSHAIR_STYLE_ID)?.remove();\n hLine = null;\n vLine = null;\n },\n };\n}\n","export function escapeHtml(text: string): string {\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n}\n\nexport function filterAngularClasses(classList: DOMTokenList): string[] {\n return Array.from(classList).filter(c => !c.startsWith('ng-') && !c.startsWith('_ng'));\n}\n\nconst NG_ATTR_RE = /\\s_ng(host|content)-[a-z0-9-]+=\"[^\"]*\"/gi;\nconst NG_ATTR_EMPTY_RE = /\\s_ng(host|content)-[a-z0-9-]+/gi;\n\nexport function cleanAngularAttrs(html: string): string {\n return html.replace(NG_ATTR_RE, '').replace(NG_ATTR_EMPTY_RE, '');\n}\n","import { escapeHtml } from '../utils';\nimport { Z_INDEX_TOAST } from '../constants';\n\nconst TOAST_ID = '__ag-toast__';\nconst TOAST_STYLE_ID = '__ag-toast-styles__';\n\n// Note: toast state is shared across instances (module-level singleton)\nlet activeTimer: ReturnType<typeof setTimeout> | null = null;\n\nexport interface ToastDetail {\n componentName: string | null;\n filePath: string | null;\n line: number | null;\n column: number | null;\n cssClasses?: string[];\n}\n\nfunction injectToastStyles(): void {\n if (document.getElementById(TOAST_STYLE_ID)) return;\n\n const style = document.createElement('style');\n style.id = TOAST_STYLE_ID;\n style.textContent = `\n #${TOAST_ID} {\n position: fixed;\n bottom: var(--ag-toast-bottom, 24px);\n left: 50%;\n transform: translateX(-50%) translateY(100%);\n z-index: ${Z_INDEX_TOAST};\n background: var(--ag-toast-bg, #0f172a);\n color: var(--ag-toast-text, #e2e8f0);\n font: 500 13px/1.4 -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n padding: 12px 18px;\n border-radius: 10px;\n box-shadow: 0 8px 24px var(--ag-toast-shadow, rgba(0, 0, 0, 0.4));\n pointer-events: none;\n opacity: 0;\n transition: transform 0.25s ease, opacity 0.25s ease;\n letter-spacing: 0.01em;\n max-width: 480px;\n min-width: 260px;\n }\n #${TOAST_ID}.ag-toast-visible {\n transform: translateX(-50%) translateY(0);\n opacity: 1;\n }\n #${TOAST_ID} .ag-toast-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 0;\n }\n #${TOAST_ID} .ag-toast-icon {\n flex-shrink: 0;\n width: 16px;\n height: 16px;\n }\n #${TOAST_ID} .ag-toast-title {\n font-weight: 600;\n color: var(--ag-toast-title, #fff);\n }\n #${TOAST_ID} .ag-toast-details {\n margin-top: 8px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n font-size: 12px;\n font-family: ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, monospace;\n }\n #${TOAST_ID} .ag-toast-row {\n display: flex;\n gap: 8px;\n align-items: baseline;\n }\n #${TOAST_ID} .ag-toast-label {\n color: var(--ag-toast-label, #64748b);\n flex-shrink: 0;\n min-width: 72px;\n }\n #${TOAST_ID} .ag-toast-value {\n color: var(--ag-toast-text, #e2e8f0);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n #${TOAST_ID} .ag-toast-file-link {\n color: var(--ag-toast-text, #e2e8f0);\n text-decoration: none;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n pointer-events: auto;\n cursor: pointer;\n }\n #${TOAST_ID} .ag-toast-file-link:hover {\n text-decoration: underline;\n color: var(--ag-accent, #3b82f6);\n }\n `;\n document.head.appendChild(style);\n}\n\nfunction getOrCreateToast(): HTMLDivElement {\n let toast = document.getElementById(TOAST_ID) as HTMLDivElement | null;\n if (!toast) {\n injectToastStyles();\n toast = document.createElement('div');\n toast.id = TOAST_ID;\n document.body.appendChild(toast);\n }\n return toast;\n}\n\nconst CHECKMARK_SVG = `<svg class=\"ag-toast-icon\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><circle cx=\"8\" cy=\"8\" r=\"7\" fill=\"#22c55e\"/><path d=\"M5 8l2 2 4-4\" stroke=\"#fff\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>`;\n\nexport function showToast(message: string, detail?: ToastDetail, durationMs = 3500): void {\n const toast = getOrCreateToast();\n\n let html = `<div class=\"ag-toast-header\">${CHECKMARK_SVG}<span class=\"ag-toast-title\">${escapeHtml(message)}</span></div>`;\n\n if (detail) {\n html += '<div class=\"ag-toast-details\">';\n\n if (detail.componentName) {\n html += `<div class=\"ag-toast-row\"><span class=\"ag-toast-label\">Component</span><span class=\"ag-toast-value\">${escapeHtml(detail.componentName)}</span></div>`;\n }\n\n if (detail.filePath) {\n let loc = detail.filePath;\n if (detail.line != null) loc += `:${detail.line}`;\n\n let vsCodeUri = `vscode://file/${encodeURI(detail.filePath)}`;\n if (detail.line != null) vsCodeUri += `:${detail.line}`;\n if (detail.line != null && detail.column != null) vsCodeUri += `:${detail.column}`;\n\n html += `<div class=\"ag-toast-row\"><span class=\"ag-toast-label\">File</span>`;\n html += `<a class=\"ag-toast-file-link\" href=\"${escapeHtml(vsCodeUri)}\" title=\"Open in VS Code\">${escapeHtml(loc)}</a>`;\n html += `</div>`;\n }\n\n if (detail.cssClasses && detail.cssClasses.length > 0) {\n const classes = detail.cssClasses.map((c) => `.${escapeHtml(c)}`).join(' ');\n html += `<div class=\"ag-toast-row\"><span class=\"ag-toast-label\">Classes</span><span class=\"ag-toast-value\">${classes}</span></div>`;\n }\n\n html += '</div>';\n }\n\n toast.innerHTML = html;\n\n if (activeTimer) {\n clearTimeout(activeTimer);\n activeTimer = null;\n }\n\n // Force reflow to restart animation if already visible\n toast.classList.remove('ag-toast-visible');\n void toast.offsetHeight;\n\n toast.classList.add('ag-toast-visible');\n\n activeTimer = setTimeout(() => {\n toast.classList.remove('ag-toast-visible');\n activeTimer = null;\n }, durationMs);\n}\n\nexport function disposeToast(): void {\n if (activeTimer) {\n clearTimeout(activeTimer);\n activeTimer = null;\n }\n document.getElementById(TOAST_ID)?.remove();\n document.getElementById(TOAST_STYLE_ID)?.remove();\n}\n","import type { OverlayRenderer } from '../overlay/overlay-renderer';\nimport type { Crosshair } from '../overlay/crosshair';\nimport type { ComponentResolver, SourceResolver } from '../types';\nimport { filterAngularClasses } from '../utils';\n\nexport interface ElementPicker {\n activate(): void;\n deactivate(): void;\n getHoveredElement(): Element | null;\n dispose(): void;\n}\n\nexport interface ElementPickerDeps {\n overlay: OverlayRenderer;\n crosshair: Crosshair;\n getComponentResolver: () => ComponentResolver | null;\n getSourceResolver: () => SourceResolver | null;\n isToolbarElement?: (el: Element) => boolean;\n getFreezeElement?: () => HTMLElement | null;\n onHover: (element: Element | null) => void;\n onSelect: (element: Element) => void;\n}\n\nexport function createElementPicker(deps: ElementPickerDeps): ElementPicker {\n let hoveredElement: Element | null = null;\n let listening = false;\n\n function resolveComponentName(el: Element): string | null {\n const resolver = deps.getComponentResolver();\n if (!resolver) return null;\n\n const result = resolver(el);\n return result?.name ?? null;\n }\n\n function resolveSourcePath(el: Element): string | null {\n const resolver = deps.getSourceResolver();\n if (!resolver) return null;\n\n const result = resolver(el);\n if (!result?.filePath) return null;\n\n let path = result.filePath;\n if (result.line != null) {\n path += `:${result.line}`;\n }\n return path;\n }\n\n function elementAtPoint(x: number, y: number): Element | null {\n // Temporarily hide freeze overlay so elementFromPoint can see through it\n const freezeEl = deps.getFreezeElement?.();\n if (freezeEl) freezeEl.style.pointerEvents = 'none';\n const target = document.elementFromPoint(x, y);\n if (freezeEl) freezeEl.style.pointerEvents = 'auto';\n return target;\n }\n\n function handleMouseMove(e: MouseEvent): void {\n const target = elementAtPoint(e.clientX, e.clientY);\n if (!target || deps.overlay.isOverlayElement(target)) return;\n if (deps.crosshair.isCrosshairElement(target)) return;\n if (deps.isToolbarElement?.(target)) return;\n if (target === hoveredElement) return;\n\n hoveredElement = target;\n const componentName = resolveComponentName(target);\n const sourcePath = resolveSourcePath(target);\n const cssClasses = filterAngularClasses(target.classList);\n deps.overlay.show(target, componentName, sourcePath, cssClasses);\n deps.onHover(target);\n }\n\n function handleClick(e: MouseEvent): void {\n const target = elementAtPoint(e.clientX, e.clientY);\n if (target && (deps.isToolbarElement?.(target) || deps.crosshair.isCrosshairElement(target))) return;\n\n e.preventDefault();\n e.stopPropagation();\n\n if (hoveredElement) {\n deps.onSelect(hoveredElement);\n }\n }\n\n return {\n activate(): void {\n if (listening) return;\n listening = true;\n deps.crosshair.activate();\n document.addEventListener('mousemove', handleMouseMove, true);\n document.addEventListener('click', handleClick, true);\n },\n\n deactivate(): void {\n if (!listening) return;\n listening = false;\n hoveredElement = null;\n deps.crosshair.deactivate();\n document.removeEventListener('mousemove', handleMouseMove, true);\n document.removeEventListener('click', handleClick, true);\n deps.overlay.hide();\n deps.onHover(null);\n },\n\n getHoveredElement(): Element | null {\n return hoveredElement;\n },\n\n dispose(): void {\n this.deactivate();\n },\n };\n}\n","export interface ParsedKey {\n key: string;\n meta: boolean;\n ctrl: boolean;\n shift: boolean;\n alt: boolean;\n}\n\nexport interface KeyboardHandler {\n start(): void;\n stop(): void;\n dispose(): void;\n}\n\nexport interface KeyboardHandlerDeps {\n getActivationKey: () => string;\n getActivationMode: () => 'hold' | 'toggle';\n getKeyHoldDuration: () => number;\n getEnableInInputs: () => boolean;\n onActivate: () => void;\n onDeactivate: () => void;\n isActive: () => boolean;\n}\n\nexport function isMac(): boolean {\n if (typeof navigator === 'undefined') return false;\n const uaData = (navigator as any).userAgentData;\n if (uaData?.platform) return /mac/i.test(uaData.platform);\n return /Mac|iPhone|iPad|iPod/i.test(navigator.userAgent);\n}\n\nexport function parseKeyCombo(combo: string): ParsedKey {\n const parts = combo.split('+').map((s) => s.trim());\n const result: ParsedKey = {\n key: '',\n meta: false,\n ctrl: false,\n shift: false,\n alt: false,\n };\n\n for (const part of parts) {\n const lower = part.toLowerCase();\n if (lower === 'meta' || lower === 'cmd' || lower === 'command') {\n result.meta = true;\n } else if (lower === 'ctrl' || lower === 'control') {\n result.ctrl = true;\n } else if (lower === 'shift') {\n result.shift = true;\n } else if (lower === 'alt' || lower === 'option') {\n result.alt = true;\n } else {\n result.key = lower;\n }\n }\n\n return result;\n}\n\nfunction matchesCombo(e: KeyboardEvent, parsed: ParsedKey): boolean {\n if (parsed.meta && !e.metaKey) return false;\n if (parsed.ctrl && !e.ctrlKey) return false;\n if (parsed.shift && !e.shiftKey) return false;\n if (parsed.alt && !e.altKey) return false;\n\n return e.key.toLowerCase() === parsed.key;\n}\n\nfunction isInputElement(el: EventTarget | null): boolean {\n if (!el || !(el instanceof HTMLElement)) return false;\n const tag = el.tagName;\n return tag === 'INPUT' || tag === 'TEXTAREA' || el.isContentEditable;\n}\n\nexport function createKeyboardHandler(deps: KeyboardHandlerDeps): KeyboardHandler {\n let holdTimer: ReturnType<typeof setTimeout> | null = null;\n let holdActivated = false;\n let listening = false;\n\n function handleKeyDown(e: KeyboardEvent): void {\n if (!deps.getEnableInInputs() && isInputElement(e.target)) return;\n\n const parsed = parseKeyCombo(deps.getActivationKey());\n if (!matchesCombo(e, parsed)) return;\n\n const mode = deps.getActivationMode();\n const holdDuration = deps.getKeyHoldDuration();\n\n if (mode === 'hold') {\n e.preventDefault();\n\n if (holdActivated) return;\n\n if (holdDuration > 0) {\n if (holdTimer) return;\n holdTimer = setTimeout(() => {\n holdActivated = true;\n deps.onActivate();\n }, holdDuration);\n } else {\n holdActivated = true;\n deps.onActivate();\n }\n } else {\n // toggle mode\n e.preventDefault();\n }\n }\n\n function handleKeyUp(e: KeyboardEvent): void {\n const parsed = parseKeyCombo(deps.getActivationKey());\n\n // For key-up we check if the released key matches the main key\n if (e.key.toLowerCase() !== parsed.key) return;\n\n const mode = deps.getActivationMode();\n\n if (mode === 'hold') {\n if (holdTimer) {\n clearTimeout(holdTimer);\n holdTimer = null;\n }\n if (holdActivated) {\n holdActivated = false;\n deps.onDeactivate();\n }\n } else {\n // toggle mode: toggle on key-up so we don't double-fire\n if (deps.isActive()) {\n deps.onDeactivate();\n } else {\n deps.onActivate();\n }\n }\n }\n\n return {\n start(): void {\n if (listening) return;\n listening = true;\n document.addEventListener('keydown', handleKeyDown, true);\n document.addEventListener('keyup', handleKeyUp, true);\n },\n\n stop(): void {\n if (!listening) return;\n listening = false;\n\n if (holdTimer) {\n clearTimeout(holdTimer);\n holdTimer = null;\n }\n holdActivated = false;\n\n document.removeEventListener('keydown', handleKeyDown, true);\n document.removeEventListener('keyup', handleKeyUp, true);\n },\n\n dispose(): void {\n this.stop();\n },\n };\n}\n","import type { ElementContext } from '../types';\nimport { cleanAngularAttrs } from '../utils';\n\nfunction truncateHtml(html: string, maxLines: number): string {\n const lines = html.split('\\n');\n if (lines.length <= maxLines) return html;\n\n return lines.slice(0, maxLines).join('\\n') + '\\n ...';\n}\n\nfunction formatLocation(name: string | null, filePath: string | null, line: number | null, column: number | null): string {\n let locationLine = '';\n if (name) locationLine += `in ${name}`;\n if (filePath) {\n const loc = filePath +\n (line != null ? `:${line}` : '') +\n (line != null && column != null ? `:${column}` : '');\n locationLine += locationLine ? ` at ${loc}` : `at ${loc}`;\n }\n return locationLine;\n}\n\nexport function generateSnippet(context: ElementContext, maxContextLines: number): string {\n const cleaned = cleanAngularAttrs(context.html);\n const truncated = truncateHtml(cleaned, maxContextLines);\n\n const parts: string[] = [truncated];\n\n if (context.componentStack.length > 0) {\n for (const entry of context.componentStack) {\n parts.push(formatLocation(entry.name, entry.filePath, entry.line, entry.column));\n }\n } else if (context.componentName || context.filePath) {\n parts.push(formatLocation(context.componentName, context.filePath, context.line, context.column));\n }\n\n return parts.join('\\n');\n}\n","import type { ElementContext, ComponentStackEntry, ComponentResolver, SourceResolver } from '../types';\nimport type { PluginRegistry } from '../plugins/plugin-registry';\nimport { generateSnippet } from './generate-snippet';\nimport { showToast, type ToastDetail } from '../overlay/toast';\nimport { filterAngularClasses } from '../utils';\n\nexport interface CopyDeps {\n getComponentResolver: () => ComponentResolver | null;\n getSourceResolver: () => SourceResolver | null;\n getMaxContextLines: () => number;\n pluginRegistry: PluginRegistry;\n}\n\nfunction buildSelector(el: Element): string {\n const tag = el.tagName.toLowerCase();\n const id = el.id ? `#${el.id}` : '';\n const classes = filterAngularClasses(el.classList)\n .map((c) => `.${c}`)\n .join('');\n return `${tag}${id}${classes}`;\n}\n\nfunction getCssClasses(el: Element): string[] {\n return filterAngularClasses(el.classList);\n}\n\nexport function buildElementContext(\n element: Element,\n componentResolver: ComponentResolver | null,\n sourceResolver: SourceResolver | null,\n): ElementContext {\n const compResult = componentResolver?.(element);\n const srcResult = sourceResolver?.(element);\n\n // Build component stack from resolver result\n const componentStack: ComponentStackEntry[] = [];\n if (compResult?.stack) {\n for (const entry of compResult.stack) {\n let filePath: string | null = null;\n let line: number | null = null;\n let column: number | null = null;\n\n if (entry.hostElement && sourceResolver) {\n const src = sourceResolver(entry.hostElement);\n if (src) {\n filePath = src.filePath;\n line = src.line;\n column = src.column;\n }\n }\n\n componentStack.push({ name: entry.name, filePath, line, column });\n }\n }\n\n return {\n element,\n html: element.outerHTML,\n componentName: compResult?.name ?? null,\n filePath: srcResult?.filePath ?? null,\n line: srcResult?.line ?? null,\n column: srcResult?.column ?? null,\n componentStack,\n selector: buildSelector(element),\n cssClasses: getCssClasses(element),\n };\n}\n\nexport interface CopyResult {\n context: ElementContext;\n snippet: string;\n}\n\nexport async function copyElement(element: Element, deps: CopyDeps): Promise<CopyResult | null> {\n const context = buildElementContext(\n element,\n deps.getComponentResolver(),\n deps.getSourceResolver(),\n );\n\n deps.pluginRegistry.callHook('onElementSelect', context);\n deps.pluginRegistry.callHook('onBeforeCopy', context);\n\n let snippet = generateSnippet(context, deps.getMaxContextLines());\n snippet = deps.pluginRegistry.callTransformHook(snippet, context);\n\n try {\n await navigator.clipboard.writeText(snippet);\n const detail: ToastDetail = {\n componentName: context.componentName,\n filePath: context.filePath,\n line: context.line,\n column: context.column,\n cssClasses: context.cssClasses,\n };\n showToast('Copied to clipboard', detail);\n deps.pluginRegistry.callHook('onCopySuccess', snippet, context, undefined);\n return { context, snippet };\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n deps.pluginRegistry.callHook('onCopyError', error);\n return null;\n }\n}\n","import type { Plugin, PluginHooks, PluginCleanup, ElementContext, AngularGrabAPI } from '../types';\n\nexport interface PluginRegistry {\n register(plugin: Plugin, api: AngularGrabAPI): void;\n unregister(name: string): void;\n callHook<K extends keyof PluginHooks>(hookName: K, ...args: Parameters<NonNullable<PluginHooks[K]>>): void;\n callTransformHook(text: string, context: ElementContext): string;\n getPlugins(): ReadonlyArray<Plugin>;\n dispose(): void;\n}\n\nexport function createPluginRegistry(): PluginRegistry {\n const plugins = new Map<string, Plugin>();\n const cleanups = new Map<string, PluginCleanup>();\n\n return {\n register(plugin: Plugin, api: AngularGrabAPI): void {\n if (plugins.has(plugin.name)) {\n this.unregister(plugin.name);\n }\n plugins.set(plugin.name, plugin);\n\n if (plugin.setup) {\n const cleanup = plugin.setup(api);\n if (cleanup) {\n cleanups.set(plugin.name, cleanup);\n }\n }\n },\n\n unregister(name: string): void {\n const cleanup = cleanups.get(name);\n if (cleanup) {\n cleanup();\n cleanups.delete(name);\n }\n plugins.delete(name);\n },\n\n callHook<K extends keyof PluginHooks>(hookName: K, ...args: Parameters<NonNullable<PluginHooks[K]>>): void {\n for (const plugin of plugins.values()) {\n const hook = plugin.hooks?.[hookName];\n if (hook) {\n try {\n (hook as (...a: any[]) => void)(...args);\n } catch (err) {\n console.warn(`[angular-grab] Plugin \"${plugin.name}\" hook \"${hookName}\" threw:`, err);\n }\n }\n }\n },\n\n callTransformHook(text: string, context: ElementContext): string {\n let result = text;\n for (const plugin of plugins.values()) {\n const transform = plugin.hooks?.transformCopyContent;\n if (transform) {\n try {\n result = transform(result, context);\n } catch (err) {\n console.warn(`[angular-grab] Plugin \"${plugin.name}\" transformCopyContent threw:`, err);\n }\n }\n }\n return result;\n },\n\n getPlugins(): ReadonlyArray<Plugin> {\n return Array.from(plugins.values());\n },\n\n dispose(): void {\n for (const [name] of plugins) {\n const cleanup = cleanups.get(name);\n if (cleanup) {\n try { cleanup(); } catch { /* ignore */ }\n }\n }\n cleanups.clear();\n plugins.clear();\n },\n };\n}\n","import type { ThemeMode, Theme } from '../types';\n\nconst STYLE_ID = '__ag-theme-vars__';\nconst OVERRIDE_STYLE_ID = '__ag-theme-overrides__';\n\nconst DARK_VARS = `\n :root {\n --ag-bg: #0f172a;\n --ag-text: #e2e8f0;\n --ag-text-muted: #64748b;\n --ag-accent: #3b82f6;\n --ag-accent-hover: #2563eb;\n --ag-surface: #1e293b;\n --ag-border: #334155;\n --ag-overlay-border: #3b82f6;\n --ag-overlay-bg: rgba(59, 130, 246, 0.1);\n --ag-label-bg: #3b82f6;\n --ag-label-text: #fff;\n --ag-toast-bg: #0f172a;\n --ag-toast-text: #e2e8f0;\n --ag-toast-title: #fff;\n --ag-toast-label: #64748b;\n --ag-toast-shadow: rgba(0, 0, 0, 0.4);\n --ag-toolbar-bg: #0f172a;\n --ag-toolbar-text: #94a3b8;\n --ag-toolbar-hover: #1e293b;\n --ag-toolbar-active: #3b82f6;\n --ag-toolbar-border: #1e293b;\n --ag-toolbar-shadow: rgba(0, 0, 0, 0.5);\n --ag-popover-bg: #0f172a;\n --ag-popover-text: #e2e8f0;\n --ag-popover-border: #1e293b;\n --ag-popover-hover: #1e293b;\n --ag-popover-shadow: rgba(0, 0, 0, 0.5);\n }\n`;\n\nconst LIGHT_VARS = `\n :root {\n --ag-bg: #ffffff;\n --ag-text: #334155;\n --ag-text-muted: #94a3b8;\n --ag-accent: #2563eb;\n --ag-accent-hover: #1d4ed8;\n --ag-surface: #f1f5f9;\n --ag-border: #e2e8f0;\n --ag-overlay-border: #2563eb;\n --ag-overlay-bg: rgba(37, 99, 235, 0.08);\n --ag-label-bg: #2563eb;\n --ag-label-text: #fff;\n --ag-toast-bg: #ffffff;\n --ag-toast-text: #334155;\n --ag-toast-title: #0f172a;\n --ag-toast-label: #94a3b8;\n --ag-toast-shadow: rgba(0, 0, 0, 0.12);\n --ag-toolbar-bg: #ffffff;\n --ag-toolbar-text: #64748b;\n --ag-toolbar-hover: #f1f5f9;\n --ag-toolbar-active: #2563eb;\n --ag-toolbar-border: #e2e8f0;\n --ag-toolbar-shadow: rgba(0, 0, 0, 0.12);\n --ag-popover-bg: #ffffff;\n --ag-popover-text: #334155;\n --ag-popover-border: #e2e8f0;\n --ag-popover-hover: #f1f5f9;\n --ag-popover-shadow: rgba(0, 0, 0, 0.12);\n }\n`;\n\n/** Maps Theme interface fields to CSS variable names. */\nconst THEME_TO_VAR: Record<keyof Theme, string> = {\n overlayBorderColor: '--ag-overlay-border',\n overlayBgColor: '--ag-overlay-bg',\n labelBgColor: '--ag-label-bg',\n labelTextColor: '--ag-label-text',\n toastBgColor: '--ag-toast-bg',\n toastTextColor: '--ag-toast-text',\n toolbarBgColor: '--ag-toolbar-bg',\n toolbarTextColor: '--ag-toolbar-text',\n toolbarAccentColor: '--ag-toolbar-active',\n popoverBgColor: '--ag-popover-bg',\n popoverTextColor: '--ag-popover-text',\n popoverBorderColor: '--ag-popover-border',\n};\n\nexport interface ThemeManager {\n apply(mode: ThemeMode): void;\n applyOverrides(theme: Partial<Theme>): void;\n clearOverrides(): void;\n dispose(): void;\n}\n\nexport function createThemeManager(): ThemeManager {\n let styleEl: HTMLStyleElement | null = null;\n let overrideEl: HTMLStyleElement | null = null;\n let currentMode: ThemeMode = 'dark';\n let mediaQuery: MediaQueryList | null = null;\n let mediaHandler: ((e: MediaQueryListEvent) => void) | null = null;\n\n function getOrCreateStyle(): HTMLStyleElement {\n if (styleEl) return styleEl;\n\n const existing = document.getElementById(STYLE_ID) as HTMLStyleElement | null;\n if (existing) {\n styleEl = existing;\n return styleEl;\n }\n\n styleEl = document.createElement('style');\n styleEl.id = STYLE_ID;\n document.head.appendChild(styleEl);\n return styleEl;\n }\n\n function getOrCreateOverrideStyle(): HTMLStyleElement {\n if (overrideEl) return overrideEl;\n\n overrideEl = document.createElement('style');\n overrideEl.id = OVERRIDE_STYLE_ID;\n document.head.appendChild(overrideEl);\n return overrideEl;\n }\n\n function resolveMode(mode: ThemeMode): 'dark' | 'light' {\n if (mode !== 'system') return mode;\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n }\n\n function applyResolved(resolved: 'dark' | 'light'): void {\n const el = getOrCreateStyle();\n el.textContent = resolved === 'dark' ? DARK_VARS : LIGHT_VARS;\n }\n\n function detachMediaListener(): void {\n if (mediaQuery && mediaHandler) {\n mediaQuery.removeEventListener('change', mediaHandler);\n }\n mediaQuery = null;\n mediaHandler = null;\n }\n\n return {\n apply(mode: ThemeMode): void {\n currentMode = mode;\n detachMediaListener();\n\n applyResolved(resolveMode(mode));\n\n if (mode === 'system') {\n mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\n mediaHandler = () => applyResolved(resolveMode('system'));\n mediaQuery.addEventListener('change', mediaHandler);\n }\n },\n\n applyOverrides(theme: Partial<Theme>): void {\n const vars: string[] = [];\n for (const [key, varName] of Object.entries(THEME_TO_VAR)) {\n const value = theme[key as keyof Theme];\n if (value) {\n vars.push(` ${varName}: ${value};`);\n }\n }\n\n if (vars.length === 0) {\n this.clearOverrides();\n return;\n }\n\n const el = getOrCreateOverrideStyle();\n el.textContent = ` :root {\\n${vars.join('\\n')}\\n }`;\n },\n\n clearOverrides(): void {\n overrideEl?.remove();\n document.getElementById(OVERRIDE_STYLE_ID)?.remove();\n overrideEl = null;\n },\n\n dispose(): void {\n detachMediaListener();\n styleEl?.remove();\n document.getElementById(STYLE_ID)?.remove();\n styleEl = null;\n this.clearOverrides();\n },\n };\n}\n","// All icons are 16x16, stroke-based with currentColor for theme compatibility\n\nexport const ICON_GRAB = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M5.5 7V3.5a1 1 0 0 1 2 0V7\"/><path d=\"M7.5 6.5V2.5a1 1 0 0 1 2 0v4\"/><path d=\"M9.5 7V3.5a1 1 0 0 1 2 0V8\"/><path d=\"M5.5 7V5.5a1 1 0 0 0-2 0V9a4 4 0 0 0 4 4h1.5a4 4 0 0 0 4-4V6a1 1 0 0 0-2 0\"/></svg>`;\n\nexport const ICON_HISTORY = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" xmlns=\"http://www.w3.org/2000/svg\"><circle cx=\"8\" cy=\"8\" r=\"6\"/><path d=\"M8 4.5V8l2.5 1.5\"/></svg>`;\n\nexport const ICON_ELLIPSIS = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"currentColor\" xmlns=\"http://www.w3.org/2000/svg\"><circle cx=\"4\" cy=\"8\" r=\"1.25\"/><circle cx=\"8\" cy=\"8\" r=\"1.25\"/><circle cx=\"12\" cy=\"8\" r=\"1.25\"/></svg>`;\n\nexport const ICON_SUN = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" xmlns=\"http://www.w3.org/2000/svg\"><circle cx=\"8\" cy=\"8\" r=\"3\"/><path d=\"M8 1.5v1M8 13.5v1M1.5 8h1M13.5 8h1M3.4 3.4l.7.7M11.9 11.9l.7.7M3.4 12.6l.7-.7M11.9 4.1l.7-.7\"/></svg>`;\n\nexport const ICON_MOON = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M13.5 8.5a5.5 5.5 0 0 1-7-7 5.5 5.5 0 1 0 7 7z\"/></svg>`;\n\nexport const ICON_SYSTEM = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"2\" y=\"2\" width=\"12\" height=\"9\" rx=\"1\"/><path d=\"M5.5 14h5\"/><path d=\"M8 11v3\"/></svg>`;\n\nexport const ICON_POWER = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M8 2v5\"/><path d=\"M4.5 4a5.5 5.5 0 1 0 7 0\"/></svg>`;\n\nexport const ICON_DISMISS = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M4 4l8 8M12 4l-8 8\"/></svg>`;\n\nexport const ICON_COPY = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"5.5\" y=\"5.5\" width=\"7\" height=\"8\" rx=\"1\"/><path d=\"M3.5 10.5v-7a1 1 0 0 1 1-1h5\"/></svg>`;\n\nexport const ICON_STYLES = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M13 1.5l-1.3 4.3a1 1 0 0 1-.7.7L6.7 7.8a1 1 0 0 0-.7.7L4.7 12.8a1 1 0 0 1-.7.7L1.5 14\"/><path d=\"M7.5 5.5l3 3\"/></svg>`;\n\nexport const ICON_CODE = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M5 4.5L1.5 8 5 11.5\"/><path d=\"M11 4.5l3.5 3.5-3.5 3.5\"/><path d=\"M9.5 2.5l-3 11\"/></svg>`;\n\nexport const ICON_COMMENT = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M2 3a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1H5l-3 3V3z\"/></svg>`;\n\nexport const ICON_TRASH = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M2.5 4.5h11\"/><path d=\"M5.5 4.5V3a1 1 0 0 1 1-1h3a1 1 0 0 1 1 1v1.5\"/><path d=\"M4 4.5l.5 8.5a1 1 0 0 0 1 1h5a1 1 0 0 0 1-1l.5-8.5\"/></svg>`;\n\nexport const ICON_FREEZE = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M8 1v14\"/><path d=\"M1 8h14\"/><path d=\"M8 1l2 2M8 1L6 3\"/><path d=\"M8 15l2-2M8 15l-2-2\"/><path d=\"M1 8l2 2M1 8l2-2\"/><path d=\"M15 8l-2 2M15 8l-2-2\"/></svg>`;\n","import type { GrabState } from '../store';\nimport { Z_INDEX_TOOLBAR } from '../constants';\nimport { ICON_GRAB, ICON_HISTORY, ICON_ELLIPSIS, ICON_FREEZE, ICON_SUN, ICON_MOON, ICON_SYSTEM, ICON_POWER, ICON_DISMISS } from './toolbar-icons';\n\nconst TOOLBAR_ID = '__ag-toolbar__';\nconst STYLE_ID = '__ag-toolbar-styles__';\n\nexport interface ToolbarCallbacks {\n onSelectionMode: () => void;\n onHistory: () => void;\n onActions: () => void;\n onFreeze: () => void;\n onThemeToggle: () => void;\n onEnableToggle: () => void;\n onDismiss: () => void;\n}\n\nexport interface ToolbarRenderer {\n show(): void;\n hide(): void;\n update(state: GrabState): void;\n isToolbarElement(el: Element): boolean;\n dispose(): void;\n}\n\nexport function createToolbarRenderer(callbacks: ToolbarCallbacks): ToolbarRenderer {\n let container: HTMLDivElement | null = null;\n let leftGroup: HTMLDivElement | null = null;\n let buttons: Record<string, HTMLButtonElement> = {};\n let allElements = new Set<Element>();\n\n function injectStyles(): void {\n if (document.getElementById(STYLE_ID)) return;\n\n const style = document.createElement('style');\n style.id = STYLE_ID;\n style.textContent = `\n #${TOOLBAR_ID} {\n position: fixed;\n bottom: 20px;\n left: 50%;\n transform: translateX(-50%);\n z-index: ${Z_INDEX_TOOLBAR};\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 4px 6px;\n background: var(--ag-toolbar-bg, #0f172a);\n border: 1px solid var(--ag-toolbar-border, #1e293b);\n border-radius: 24px;\n box-shadow: 0 4px 16px var(--ag-toolbar-shadow, rgba(0, 0, 0, 0.5));\n pointer-events: auto;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n transition: opacity 0.2s ease, transform 0.2s ease;\n }\n #${TOOLBAR_ID}.ag-toolbar-hidden {\n opacity: 0;\n transform: translateX(-50%) translateY(20px);\n pointer-events: none;\n }\n #${TOOLBAR_ID} button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: var(--ag-toolbar-text, #94a3b8);\n cursor: pointer;\n padding: 0;\n transition: background 0.15s ease, color 0.15s ease;\n }\n #${TOOLBAR_ID} button:hover {\n background: var(--ag-toolbar-hover, #1e293b);\n color: var(--ag-accent, #3b82f6);\n }\n #${TOOLBAR_ID} button.ag-btn-active {\n color: var(--ag-toolbar-active, #3b82f6);\n }\n #${TOOLBAR_ID} button.ag-btn-disabled {\n opacity: 0.4;\n color: var(--ag-toolbar-text, #94a3b8);\n }\n #${TOOLBAR_ID} .ag-toolbar-divider {\n width: 1px;\n height: 20px;\n background: var(--ag-toolbar-border, #1e293b);\n margin: 0 4px;\n flex-shrink: 0;\n }\n #${TOOLBAR_ID} .ag-toolbar-left {\n display: flex;\n align-items: center;\n gap: 2px;\n overflow: hidden;\n max-width: 240px;\n opacity: 1;\n transition: max-width 0.25s ease, opacity 0.2s ease, margin 0.25s ease;\n }\n #${TOOLBAR_ID} .ag-toolbar-left.ag-toolbar-left-hidden {\n max-width: 0;\n opacity: 0;\n pointer-events: none;\n }\n `;\n document.head.appendChild(style);\n }\n\n function createButton(name: string, icon: string, title: string, onClick: () => void): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.innerHTML = icon;\n btn.title = title;\n btn.setAttribute('aria-label', title);\n btn.setAttribute('data-ag-btn', name);\n btn.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n onClick();\n });\n return btn;\n }\n\n function ensureContainer(): void {\n if (container) return;\n\n injectStyles();\n\n container = document.createElement('div');\n container.id = TOOLBAR_ID;\n container.setAttribute('role', 'toolbar');\n container.setAttribute('aria-label', 'Angular Grab toolbar');\n\n buttons.selection = createButton('selection', ICON_GRAB, 'Selection mode', callbacks.onSelectionMode);\n buttons.history = createButton('history', ICON_HISTORY, 'History', callbacks.onHistory);\n buttons.actions = createButton('actions', ICON_ELLIPSIS, 'Actions', callbacks.onActions);\n buttons.freeze = createButton('freeze', ICON_FREEZE, 'Freeze page (F)', callbacks.onFreeze);\n buttons.theme = createButton('theme', ICON_SUN, 'Toggle theme', callbacks.onThemeToggle);\n buttons.enable = createButton('enable', ICON_POWER, 'Enable/Disable', callbacks.onEnableToggle);\n buttons.dismiss = createButton('dismiss', ICON_DISMISS, 'Dismiss toolbar', callbacks.onDismiss);\n\n const divider = document.createElement('span');\n divider.className = 'ag-toolbar-divider';\n\n leftGroup = document.createElement('div');\n leftGroup.className = 'ag-toolbar-left';\n leftGroup.appendChild(buttons.selection);\n leftGroup.appendChild(buttons.history);\n leftGroup.appendChild(buttons.actions);\n leftGroup.appendChild(buttons.freeze);\n leftGroup.appendChild(divider);\n container.appendChild(leftGroup);\n container.appendChild(buttons.theme);\n container.appendChild(buttons.enable);\n container.appendChild(buttons.dismiss);\n\n document.body.appendChild(container);\n\n // Track all elements for isToolbarElement checks\n allElements.clear();\n allElements.add(container);\n allElements.add(leftGroup);\n allElements.add(divider);\n for (const btn of Object.values(buttons)) {\n allElements.add(btn);\n }\n }\n\n return {\n show(): void {\n ensureContainer();\n container!.classList.remove('ag-toolbar-hidden');\n },\n\n hide(): void {\n if (container) {\n container.classList.add('ag-toolbar-hidden');\n }\n },\n\n update(state: GrabState): void {\n if (!container) return;\n\n // Selection mode active state\n if (state.active) {\n buttons.selection.classList.add('ag-btn-active');\n } else {\n buttons.selection.classList.remove('ag-btn-active');\n }\n\n // Theme icon\n const mode = state.toolbar.themeMode;\n const themeIcon = mode === 'dark' ? ICON_SUN : mode === 'light' ? ICON_MOON : ICON_SYSTEM;\n const themeLabel = mode === 'dark' ? 'Switch to light mode' : mode === 'light' ? 'Switch to system theme' : 'Switch to dark mode';\n buttons.theme.innerHTML = themeIcon;\n buttons.theme.title = themeLabel;\n buttons.theme.setAttribute('aria-label', themeLabel);\n\n // Freeze button active state\n if (state.frozen) {\n buttons.freeze.classList.add('ag-btn-active');\n } else {\n buttons.freeze.classList.remove('ag-btn-active');\n }\n\n // Enable/disable — hide/show left side\n if (state.options.enabled) {\n buttons.enable.classList.add('ag-btn-active');\n leftGroup?.classList.remove('ag-toolbar-left-hidden');\n } else {\n buttons.enable.classList.remove('ag-btn-active');\n leftGroup?.classList.add('ag-toolbar-left-hidden');\n }\n },\n\n isToolbarElement(el: Element): boolean {\n if (allElements.has(el)) return true;\n\n // Walk up to check if el is inside the toolbar (e.g. SVG children)\n let current: Element | null = el;\n while (current) {\n if (current === container) return true;\n if (current.id === TOOLBAR_ID) return true;\n current = current.parentElement;\n }\n return false;\n },\n\n dispose(): void {\n container?.remove();\n document.getElementById(STYLE_ID)?.remove();\n container = null;\n leftGroup = null;\n buttons = {};\n allElements.clear();\n },\n };\n}\n","import type { HistoryEntry } from '../types';\nimport { escapeHtml } from '../utils';\nimport { Z_INDEX_POPOVER, TOOLBAR_POPOVER_OFFSET } from '../constants';\n\nconst POPOVER_ID = '__ag-history-popover__';\nconst STYLE_ID = '__ag-history-styles__';\n\nexport interface HistoryPopover {\n show(entries: HistoryEntry[]): void;\n hide(): void;\n isVisible(): boolean;\n isPopoverElement(el: Element): boolean;\n dispose(): void;\n}\n\nexport interface HistoryPopoverCallbacks {\n onEntryClick: (entry: HistoryEntry) => void;\n}\n\nfunction formatRelativeTime(timestamp: number): string {\n const diff = Date.now() - timestamp;\n const seconds = Math.floor(diff / 1000);\n\n if (seconds < 60) return 'just now';\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.floor(hours / 24);\n return `${days}d ago`;\n}\n\nfunction shortPath(filePath: string): string {\n const parts = filePath.split('/');\n return parts[parts.length - 1];\n}\n\nfunction buildVsCodeUri(filePath: string, line: number | null, column: number | null): string {\n let uri = `vscode://file/${encodeURI(filePath)}`;\n if (line != null) uri += `:${line}`;\n if (line != null && column != null) uri += `:${column}`;\n return uri;\n}\n\nexport function createHistoryPopover(callbacks: HistoryPopoverCallbacks): HistoryPopover {\n let popover: HTMLDivElement | null = null;\n let visible = false;\n\n function injectStyles(): void {\n if (document.getElementById(STYLE_ID)) return;\n\n const style = document.createElement('style');\n style.id = STYLE_ID;\n style.textContent = `\n #${POPOVER_ID} {\n position: fixed;\n bottom: ${TOOLBAR_POPOVER_OFFSET};\n left: 50%;\n transform: translateX(-50%);\n z-index: ${Z_INDEX_POPOVER};\n background: var(--ag-popover-bg, #0f172a);\n border: 1px solid var(--ag-popover-border, #1e293b);\n border-radius: 12px;\n box-shadow: 0 8px 24px var(--ag-popover-shadow, rgba(0, 0, 0, 0.5));\n min-width: 320px;\n max-width: 420px;\n max-height: 360px;\n overflow-y: auto;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.15s ease, visibility 0.15s ease;\n pointer-events: auto;\n }\n #${POPOVER_ID}.ag-popover-visible {\n opacity: 1;\n visibility: visible;\n }\n #${POPOVER_ID} .ag-history-header {\n padding: 10px 14px 8px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: var(--ag-text-muted, #64748b);\n border-bottom: 1px solid var(--ag-popover-border, #1e293b);\n }\n #${POPOVER_ID} .ag-history-empty {\n padding: 24px 14px;\n text-align: center;\n color: var(--ag-text-muted, #64748b);\n font-size: 13px;\n }\n #${POPOVER_ID} .ag-history-item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding: 8px 14px;\n cursor: pointer;\n border: none;\n border-bottom: 1px solid var(--ag-popover-border, #1e293b);\n background: transparent;\n width: 100%;\n text-align: left;\n font: inherit;\n color: inherit;\n transition: background 0.1s ease;\n }\n #${POPOVER_ID} .ag-history-item:last-child {\n border-bottom: none;\n }\n #${POPOVER_ID} .ag-history-item:hover {\n background: var(--ag-popover-hover, #1e293b);\n }\n #${POPOVER_ID} .ag-history-info {\n flex: 1;\n min-width: 0;\n }\n #${POPOVER_ID} .ag-history-selector {\n font: 12px/1.3 ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, monospace;\n color: var(--ag-popover-text, #e2e8f0);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n #${POPOVER_ID} .ag-history-meta {\n font-size: 11px;\n color: var(--ag-text-muted, #64748b);\n margin-top: 2px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n #${POPOVER_ID} .ag-history-time {\n font-size: 11px;\n color: var(--ag-text-muted, #64748b);\n flex-shrink: 0;\n }\n #${POPOVER_ID} .ag-history-file-link {\n color: var(--ag-text-muted, #64748b);\n text-decoration: none;\n }\n #${POPOVER_ID} .ag-history-file-link:hover {\n text-decoration: underline;\n color: var(--ag-accent, #3b82f6);\n }\n `;\n document.head.appendChild(style);\n }\n\n function ensurePopover(): HTMLDivElement {\n if (popover) return popover;\n\n injectStyles();\n popover = document.createElement('div');\n popover.id = POPOVER_ID;\n popover.setAttribute('role', 'dialog');\n popover.setAttribute('aria-label', 'Grab history');\n document.body.appendChild(popover);\n return popover;\n }\n\n function render(entries: HistoryEntry[]): void {\n const el = ensurePopover();\n\n let html = '<div class=\"ag-history-header\">History</div>';\n\n if (entries.length === 0) {\n html += '<div class=\"ag-history-empty\">No elements grabbed yet</div>';\n } else {\n for (const entry of entries) {\n const selector = escapeHtml(entry.context.selector);\n const comp = entry.context.componentName ? escapeHtml(entry.context.componentName) : '';\n const time = formatRelativeTime(entry.timestamp);\n let meta = comp ? `in ${comp}` : '';\n if (entry.context.filePath) {\n const uri = buildVsCodeUri(entry.context.filePath, entry.context.line, entry.context.column);\n const fileName = escapeHtml(shortPath(entry.context.filePath));\n const sep = meta ? ' \\u2014 ' : '';\n meta += `${sep}<a class=\"ag-history-file-link\" href=\"${escapeHtml(uri)}\" title=\"Open in VS Code\">${fileName}</a>`;\n }\n\n html += `<button class=\"ag-history-item\" data-ag-history-id=\"${escapeHtml(entry.id)}\" aria-label=\"Re-copy ${selector}\">`;\n html += `<div class=\"ag-history-info\">`;\n html += `<div class=\"ag-history-selector\">${selector}</div>`;\n if (meta) html += `<div class=\"ag-history-meta\">${meta}</div>`;\n html += `</div>`;\n html += `<span class=\"ag-history-time\">${time}</span>`;\n html += `</button>`;\n }\n }\n\n el.innerHTML = html;\n\n // Attach click handlers\n const items = el.querySelectorAll('.ag-history-item');\n items.forEach((item) => {\n item.addEventListener('click', (e) => {\n e.stopPropagation();\n const id = (item as HTMLElement).dataset.agHistoryId;\n const entry = entries.find((ent) => ent.id === id);\n if (entry) {\n callbacks.onEntryClick(entry);\n }\n });\n });\n }\n\n return {\n show(entries: HistoryEntry[]): void {\n render(entries);\n visible = true;\n // Force reflow for transition\n void ensurePopover().offsetHeight;\n ensurePopover().classList.add('ag-popover-visible');\n },\n\n hide(): void {\n visible = false;\n popover?.classList.remove('ag-popover-visible');\n },\n\n isVisible(): boolean {\n return visible;\n },\n\n isPopoverElement(el: Element): boolean {\n if (!popover) return false;\n let current: Element | null = el;\n while (current) {\n if (current === popover || current.id === POPOVER_ID) return true;\n current = current.parentElement;\n }\n return false;\n },\n\n dispose(): void {\n popover?.remove();\n document.getElementById(STYLE_ID)?.remove();\n popover = null;\n visible = false;\n },\n };\n}\n","import { ICON_COPY, ICON_STYLES, ICON_CODE, ICON_COMMENT, ICON_TRASH } from './toolbar-icons';\nimport { escapeHtml } from '../utils';\nimport { Z_INDEX_POPOVER, TOOLBAR_POPOVER_OFFSET } from '../constants';\n\nconst MENU_ID = '__ag-actions-menu__';\nconst STYLE_ID = '__ag-actions-styles__';\n\nexport interface ActionsMenuCallbacks {\n onCopyElement: () => void;\n onCopyStyles: () => void;\n onCopyHtml: () => void;\n onComment: () => void;\n onClearHistory: () => void;\n}\n\nexport interface ActionsMenu {\n show(): void;\n hide(): void;\n isVisible(): boolean;\n isMenuElement(el: Element): boolean;\n dispose(): void;\n}\n\ninterface MenuItem {\n icon: string;\n label: string;\n action: () => void;\n separator?: false;\n}\n\ninterface MenuSeparator {\n separator: true;\n}\n\ntype MenuEntry = MenuItem | MenuSeparator;\n\nexport function createActionsMenu(callbacks: ActionsMenuCallbacks): ActionsMenu {\n let menu: HTMLDivElement | null = null;\n let visible = false;\n\n const items: MenuEntry[] = [\n { icon: ICON_COPY, label: 'Copy Element', action: callbacks.onCopyElement },\n { icon: ICON_STYLES, label: 'Copy Styles', action: callbacks.onCopyStyles },\n { icon: ICON_CODE, label: 'Copy HTML', action: callbacks.onCopyHtml },\n { icon: ICON_COMMENT, label: 'Comment', action: callbacks.onComment },\n { separator: true },\n { icon: ICON_TRASH, label: 'Clear History', action: callbacks.onClearHistory },\n ];\n\n function injectStyles(): void {\n if (document.getElementById(STYLE_ID)) return;\n\n const style = document.createElement('style');\n style.id = STYLE_ID;\n style.textContent = `\n #${MENU_ID} {\n position: fixed;\n bottom: ${TOOLBAR_POPOVER_OFFSET};\n left: 50%;\n transform: translateX(-50%);\n z-index: ${Z_INDEX_POPOVER};\n background: var(--ag-popover-bg, #0f172a);\n border: 1px solid var(--ag-popover-border, #1e293b);\n border-radius: 10px;\n box-shadow: 0 8px 24px var(--ag-popover-shadow, rgba(0, 0, 0, 0.5));\n min-width: 200px;\n padding: 4px;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.15s ease, visibility 0.15s ease;\n pointer-events: auto;\n }\n #${MENU_ID}.ag-menu-visible {\n opacity: 1;\n visibility: visible;\n }\n #${MENU_ID} .ag-menu-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 12px;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--ag-popover-text, #e2e8f0);\n font-size: 13px;\n cursor: pointer;\n width: 100%;\n text-align: left;\n transition: background 0.1s ease;\n }\n #${MENU_ID} .ag-menu-item:hover {\n background: var(--ag-popover-hover, #1e293b);\n }\n #${MENU_ID} .ag-menu-item svg {\n flex-shrink: 0;\n opacity: 0.7;\n }\n #${MENU_ID} .ag-menu-sep {\n height: 1px;\n background: var(--ag-popover-border, #1e293b);\n margin: 4px 8px;\n }\n `;\n document.head.appendChild(style);\n }\n\n function ensureMenu(): HTMLDivElement {\n if (menu) return menu;\n\n injectStyles();\n menu = document.createElement('div');\n menu.id = MENU_ID;\n menu.setAttribute('role', 'menu');\n menu.setAttribute('aria-label', 'Actions');\n\n for (const entry of items) {\n if (entry.separator) {\n const sep = document.createElement('div');\n sep.className = 'ag-menu-sep';\n menu.appendChild(sep);\n continue;\n }\n\n const btn = document.createElement('button');\n btn.className = 'ag-menu-item';\n btn.setAttribute('role', 'menuitem');\n btn.innerHTML = `${entry.icon}<span>${escapeHtml(entry.label)}</span>`;\n btn.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n visible = false;\n menu?.classList.remove('ag-menu-visible');\n entry.action();\n });\n menu.appendChild(btn);\n }\n\n document.body.appendChild(menu);\n return menu;\n }\n\n return {\n show(): void {\n const el = ensureMenu();\n visible = true;\n void el.offsetHeight;\n el.classList.add('ag-menu-visible');\n },\n\n hide(): void {\n visible = false;\n menu?.classList.remove('ag-menu-visible');\n },\n\n isVisible(): boolean {\n return visible;\n },\n\n isMenuElement(el: Element): boolean {\n if (!menu) return false;\n let current: Element | null = el;\n while (current) {\n if (current === menu || current.id === MENU_ID) return true;\n current = current.parentElement;\n }\n return false;\n },\n\n dispose(): void {\n menu?.remove();\n document.getElementById(STYLE_ID)?.remove();\n menu = null;\n visible = false;\n },\n };\n}\n","import { Z_INDEX_POPOVER, TOOLBAR_POPOVER_OFFSET } from '../constants';\n\nconst POPOVER_ID = '__ag-comment-popover__';\nconst STYLE_ID = '__ag-comment-styles__';\n\nexport interface CommentPopover {\n show(): void;\n hide(): void;\n isVisible(): boolean;\n isPopoverElement(el: Element): boolean;\n dispose(): void;\n}\n\nexport interface CommentPopoverCallbacks {\n onSubmit: (comment: string) => void;\n onCancel: () => void;\n}\n\nexport function createCommentPopover(callbacks: CommentPopoverCallbacks): CommentPopover {\n let popover: HTMLDivElement | null = null;\n let textarea: HTMLTextAreaElement | null = null;\n let visible = false;\n let keydownHandler: ((e: KeyboardEvent) => void) | null = null;\n\n function injectStyles(): void {\n if (document.getElementById(STYLE_ID)) return;\n\n const style = document.createElement('style');\n style.id = STYLE_ID;\n style.textContent = `\n #${POPOVER_ID} {\n position: fixed;\n bottom: ${TOOLBAR_POPOVER_OFFSET};\n left: 50%;\n transform: translateX(-50%);\n z-index: ${Z_INDEX_POPOVER};\n background: var(--ag-popover-bg, #0f172a);\n border: 1px solid var(--ag-popover-border, #1e293b);\n border-radius: 12px;\n box-shadow: 0 8px 24px var(--ag-popover-shadow, rgba(0, 0, 0, 0.5));\n width: 340px;\n padding: 14px;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.15s ease, visibility 0.15s ease;\n pointer-events: auto;\n }\n #${POPOVER_ID}.ag-comment-visible {\n opacity: 1;\n visibility: visible;\n }\n #${POPOVER_ID} textarea {\n width: 100%;\n min-height: 80px;\n padding: 8px 10px;\n border: 1px solid var(--ag-popover-border, #1e293b);\n border-radius: 8px;\n background: var(--ag-surface, #1e293b);\n color: var(--ag-popover-text, #e2e8f0);\n font: 13px/1.5 -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n resize: vertical;\n outline: none;\n box-sizing: border-box;\n }\n #${POPOVER_ID} textarea:focus {\n border-color: var(--ag-accent, #3b82f6);\n }\n #${POPOVER_ID} textarea::placeholder {\n color: var(--ag-text-muted, #64748b);\n }\n #${POPOVER_ID} .ag-comment-footer {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n margin-top: 10px;\n }\n #${POPOVER_ID} .ag-comment-btn {\n padding: 6px 14px;\n border: none;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.15s ease;\n }\n #${POPOVER_ID} .ag-comment-cancel {\n background: transparent;\n color: var(--ag-text-muted, #64748b);\n }\n #${POPOVER_ID} .ag-comment-cancel:hover {\n background: var(--ag-popover-hover, #1e293b);\n color: var(--ag-popover-text, #e2e8f0);\n }\n #${POPOVER_ID} .ag-comment-submit {\n background: var(--ag-accent, #3b82f6);\n color: #fff;\n }\n #${POPOVER_ID} .ag-comment-submit:hover {\n background: var(--ag-accent-hover, #2563eb);\n }\n `;\n document.head.appendChild(style);\n }\n\n function ensurePopover(): HTMLDivElement {\n if (popover) return popover;\n\n injectStyles();\n\n popover = document.createElement('div');\n popover.id = POPOVER_ID;\n popover.setAttribute('role', 'dialog');\n popover.setAttribute('aria-label', 'Add comment');\n\n textarea = document.createElement('textarea');\n textarea.placeholder = 'Add a comment...';\n textarea.rows = 3;\n\n const footer = document.createElement('div');\n footer.className = 'ag-comment-footer';\n\n const cancelBtn = document.createElement('button');\n cancelBtn.className = 'ag-comment-btn ag-comment-cancel';\n cancelBtn.textContent = 'Cancel';\n cancelBtn.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n doHide();\n callbacks.onCancel();\n });\n\n const submitBtn = document.createElement('button');\n submitBtn.className = 'ag-comment-btn ag-comment-submit';\n submitBtn.textContent = 'Copy with Comment';\n submitBtn.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n const comment = textarea!.value.trim();\n if (comment) {\n doHide();\n callbacks.onSubmit(comment);\n } else {\n textarea!.style.borderColor = 'var(--ag-accent, #3b82f6)';\n textarea!.setAttribute('placeholder', 'Please enter a comment...');\n textarea!.focus();\n setTimeout(() => {\n if (textarea) {\n textarea.style.borderColor = '';\n textarea.setAttribute('placeholder', 'Add a comment...');\n }\n }, 2000);\n }\n });\n\n footer.appendChild(cancelBtn);\n footer.appendChild(submitBtn);\n popover.appendChild(textarea);\n popover.appendChild(footer);\n\n document.body.appendChild(popover);\n return popover;\n }\n\n function attachKeydownInterceptor(): void {\n if (keydownHandler) return;\n\n keydownHandler = (e: KeyboardEvent) => {\n // When textarea is focused, prevent keyboard handler from intercepting\n if (textarea && document.activeElement === textarea) {\n e.stopImmediatePropagation();\n\n if (e.key === 'Escape') {\n doHide();\n callbacks.onCancel();\n }\n }\n };\n\n document.addEventListener('keydown', keydownHandler, true);\n }\n\n function detachKeydownInterceptor(): void {\n if (keydownHandler) {\n document.removeEventListener('keydown', keydownHandler, true);\n keydownHandler = null;\n }\n }\n\n function doHide(): void {\n visible = false;\n popover?.classList.remove('ag-comment-visible');\n detachKeydownInterceptor();\n }\n\n return {\n show(): void {\n const el = ensurePopover();\n textarea!.value = '';\n visible = true;\n void el.offsetHeight;\n el.classList.add('ag-comment-visible');\n attachKeydownInterceptor();\n // Focus after transition starts\n requestAnimationFrame(() => textarea?.focus());\n },\n\n hide(): void {\n doHide();\n },\n\n isVisible(): boolean {\n return visible;\n },\n\n isPopoverElement(el: Element): boolean {\n if (!popover) return false;\n let current: Element | null = el;\n while (current) {\n if (current === popover || current.id === POPOVER_ID) return true;\n current = current.parentElement;\n }\n return false;\n },\n\n dispose(): void {\n detachKeydownInterceptor();\n popover?.remove();\n document.getElementById(STYLE_ID)?.remove();\n popover = null;\n textarea = null;\n visible = false;\n },\n };\n}\n","import type { ElementContext } from '../types';\nimport type { PluginRegistry } from '../plugins/plugin-registry';\nimport { generateSnippet } from '../clipboard/generate-snippet';\nimport { showToast } from '../overlay/toast';\nimport { cleanAngularAttrs } from '../utils';\n\nexport async function copyElementSnippet(\n context: ElementContext,\n maxLines: number,\n pluginRegistry?: PluginRegistry,\n): Promise<boolean> {\n let snippet = generateSnippet(context, maxLines);\n if (pluginRegistry) {\n snippet = pluginRegistry.callTransformHook(snippet, context);\n }\n const ok = await writeAndToast(snippet, 'Copied to clipboard', context);\n if (ok) pluginRegistry?.callHook('onCopySuccess', snippet, context, undefined);\n return ok;\n}\n\nexport async function copyElementHtml(\n context: ElementContext,\n pluginRegistry?: PluginRegistry,\n): Promise<boolean> {\n const cleaned = cleanAngularAttrs(context.html);\n const ok = await writeAndToast(cleaned, 'HTML copied to clipboard', context);\n if (ok) pluginRegistry?.callHook('onCopySuccess', cleaned, context, undefined);\n return ok;\n}\n\nexport async function copyElementStyles(element: Element): Promise<boolean> {\n if (!element.isConnected) {\n showToast('Element is no longer on the page');\n return false;\n }\n\n const computed = window.getComputedStyle(element);\n const tag = element.tagName.toLowerCase();\n const lines: string[] = [`/* Computed styles for <${tag}> */`, `${tag} {`];\n\n const props = [\n 'display', 'position', 'top', 'right', 'bottom', 'left',\n 'width', 'height', 'min-width', 'min-height', 'max-width', 'max-height',\n 'margin', 'padding',\n 'border', 'border-radius',\n 'background', 'background-color',\n 'color', 'font', 'font-size', 'font-weight', 'font-family', 'line-height',\n 'text-align', 'text-decoration', 'text-transform',\n 'opacity', 'overflow', 'z-index',\n 'flex-direction', 'justify-content', 'align-items', 'gap',\n 'grid-template-columns', 'grid-template-rows',\n 'box-shadow', 'cursor', 'transition', 'transform',\n ];\n\n for (const prop of props) {\n const value = computed.getPropertyValue(prop);\n if (value && value !== 'none' && value !== 'normal' && value !== 'auto' && value !== '0px' && value !== 'visible') {\n lines.push(` ${prop}: ${value};`);\n }\n }\n\n lines.push('}');\n const css = lines.join('\\n');\n\n return writeAndToast(css, 'Styles copied to clipboard');\n}\n\nexport async function copyWithComment(\n context: ElementContext,\n comment: string,\n maxLines: number,\n pluginRegistry?: PluginRegistry,\n): Promise<boolean> {\n let snippet = generateSnippet(context, maxLines);\n if (pluginRegistry) {\n snippet = pluginRegistry.callTransformHook(snippet, context);\n }\n const full = `${snippet}\\n\\n/* Comment: ${comment} */`;\n const ok = await writeAndToast(full, 'Copied with comment', context);\n if (ok) pluginRegistry?.callHook('onCopySuccess', full, context, comment);\n return ok;\n}\n\nasync function writeAndToast(text: string, message: string, context?: ElementContext): Promise<boolean> {\n try {\n await navigator.clipboard.writeText(text);\n showToast(message, context ? {\n componentName: context.componentName,\n filePath: context.filePath,\n line: context.line,\n column: context.column,\n cssClasses: context.cssClasses,\n } : undefined);\n return true;\n } catch {\n return false;\n }\n}\n","import { Z_INDEX_FREEZE } from '../constants';\n\nconst FREEZE_ID = '__ag-freeze-overlay__';\nconst FREEZE_STYLE_ID = '__ag-freeze-styles__';\nconst HOVER_STYLE_ID = '__ag-freeze-hover-styles__';\nconst ANIM_STYLE_ID = '__ag-freeze-anim-styles__';\nconst HOVER_ATTR = 'data-ag-hover';\n\n/**\n * Events to block during freeze to prevent hover state changes.\n * Adapted from react-grab's freeze-pseudo-states.ts\n */\nconst MOUSE_EVENTS_TO_BLOCK = [\n 'mouseenter', 'mouseleave', 'mouseover', 'mouseout',\n 'pointerenter', 'pointerleave', 'pointerover', 'pointerout',\n] as const;\n\nconst FOCUS_EVENTS_TO_BLOCK = ['focus', 'blur', 'focusin', 'focusout'] as const;\n\nexport interface FreezeOverlay {\n show(hoveredElement?: Element | null): void;\n hide(): void;\n isVisible(): boolean;\n isFreezeElement(el: Element): boolean;\n getElement(): HTMLDivElement | null;\n dispose(): void;\n}\n\nexport function createFreezeOverlay(): FreezeOverlay {\n let overlay: HTMLDivElement | null = null;\n let visible = false;\n let hoverStyleEl: HTMLStyleElement | null = null;\n let animStyleEl: HTMLStyleElement | null = null;\n let markedElements: Element[] = [];\n\n function injectStyles(): void {\n if (document.getElementById(FREEZE_STYLE_ID)) return;\n\n const style = document.createElement('style');\n style.id = FREEZE_STYLE_ID;\n style.textContent = `\n #${FREEZE_ID} {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n z-index: ${Z_INDEX_FREEZE};\n pointer-events: auto;\n background: transparent;\n }\n `;\n document.head.appendChild(style);\n }\n\n function ensureOverlay(): HTMLDivElement {\n if (overlay) return overlay;\n\n injectStyles();\n overlay = document.createElement('div');\n overlay.id = FREEZE_ID;\n overlay.style.display = 'none';\n document.body.appendChild(overlay);\n return overlay;\n }\n\n // --- Event blocking (from react-grab's freeze-pseudo-states.ts) ---\n\n const stopEvent = (e: Event): void => {\n e.stopImmediatePropagation();\n };\n\n const preventFocusChange = (e: Event): void => {\n e.preventDefault();\n e.stopImmediatePropagation();\n };\n\n function blockEvents(): void {\n for (const type of MOUSE_EVENTS_TO_BLOCK) {\n document.addEventListener(type, stopEvent, true);\n }\n for (const type of FOCUS_EVENTS_TO_BLOCK) {\n document.addEventListener(type, preventFocusChange, true);\n }\n }\n\n function unblockEvents(): void {\n for (const type of MOUSE_EVENTS_TO_BLOCK) {\n document.removeEventListener(type, stopEvent, true);\n }\n for (const type of FOCUS_EVENTS_TO_BLOCK) {\n document.removeEventListener(type, preventFocusChange, true);\n }\n }\n\n // --- Hover preservation via CSS rule cloning ---\n\n /** Mark the hovered element and all ancestors with [data-ag-hover]. */\n function markHoverChain(element: Element): void {\n let current: Element | null = element;\n while (current && current !== document.documentElement) {\n current.setAttribute(HOVER_ATTR, '');\n markedElements.push(current);\n current = current.parentElement;\n }\n }\n\n function clearHoverMarks(): void {\n for (const el of markedElements) {\n el.removeAttribute(HOVER_ATTR);\n }\n markedElements = [];\n }\n\n /**\n * Walk all stylesheets and clone :hover rules as [data-ag-hover] rules.\n * This preserves hover-dependent visibility of child elements\n * (e.g. `.trigger:hover .tooltip { display: block }`) which\n * computed-style snapshotting alone cannot handle.\n */\n function injectHoverRules(): void {\n if (hoverStyleEl) return;\n\n const cloned: string[] = [];\n\n for (const sheet of Array.from(document.styleSheets)) {\n let rules: CSSRuleList;\n try {\n rules = sheet.cssRules;\n } catch {\n continue; // cross-origin stylesheet\n }\n collectHoverRules(rules, cloned);\n }\n\n if (cloned.length === 0) return;\n\n hoverStyleEl = document.createElement('style');\n hoverStyleEl.id = HOVER_STYLE_ID;\n hoverStyleEl.textContent = cloned.join('\\n');\n document.head.appendChild(hoverStyleEl);\n }\n\n function collectHoverRules(rules: CSSRuleList, out: string[]): void {\n for (const rule of Array.from(rules)) {\n if (rule instanceof CSSStyleRule) {\n if (rule.selectorText.includes(':hover')) {\n const newSelector = rule.selectorText.replace(/:hover/g, `[${HOVER_ATTR}]`);\n out.push(`${newSelector} { ${rule.style.cssText} }`);\n }\n } else if (rule instanceof CSSMediaRule) {\n const inner: string[] = [];\n collectHoverRules(rule.cssRules, inner);\n if (inner.length > 0) {\n out.push(`@media ${rule.conditionText} { ${inner.join('\\n')} }`);\n }\n }\n }\n }\n\n function removeHoverRules(): void {\n hoverStyleEl?.remove();\n hoverStyleEl = null;\n }\n\n // --- Animation freezing (from react-grab's freeze-animations.ts) ---\n\n function freezeAnimations(): void {\n if (animStyleEl) return;\n\n animStyleEl = document.createElement('style');\n animStyleEl.id = ANIM_STYLE_ID;\n animStyleEl.textContent = `\n *, *::before, *::after {\n animation-play-state: paused !important;\n transition: none !important;\n }\n `;\n document.head.appendChild(animStyleEl);\n }\n\n function unfreezeAnimations(): void {\n animStyleEl?.remove();\n animStyleEl = null;\n }\n\n return {\n show(hoveredElement?: Element | null): void {\n // 1. Block mouse/focus events to prevent hover state changes\n blockEvents();\n\n // 2. Preserve hover state via CSS rule cloning BEFORE overlay steals hover\n if (hoveredElement) {\n markHoverChain(hoveredElement);\n injectHoverRules();\n }\n\n // 3. Freeze animations so nothing moves while page is frozen\n freezeAnimations();\n\n // 4. Show overlay to block clicks/scrolls\n const el = ensureOverlay();\n el.style.display = 'block';\n visible = true;\n },\n\n hide(): void {\n if (overlay) overlay.style.display = 'none';\n visible = false;\n clearHoverMarks();\n removeHoverRules();\n unfreezeAnimations();\n unblockEvents();\n },\n\n isVisible(): boolean {\n return visible;\n },\n\n isFreezeElement(el: Element): boolean {\n return el === overlay || el.id === FREEZE_ID;\n },\n\n getElement(): HTMLDivElement | null {\n return overlay;\n },\n\n dispose(): void {\n clearHoverMarks();\n removeHoverRules();\n unfreezeAnimations();\n unblockEvents();\n overlay?.remove();\n document.getElementById(FREEZE_STYLE_ID)?.remove();\n overlay = null;\n visible = false;\n },\n };\n}\n","import { Z_INDEX_OVERLAY, Z_INDEX_LABEL } from '../constants';\n\nconst STYLE_ID = '__ag-feedback-styles__';\n\nfunction injectStyles(): void {\n if (document.getElementById(STYLE_ID)) return;\n\n const style = document.createElement('style');\n style.id = STYLE_ID;\n style.textContent = `\n @keyframes ag-flash {\n 0% { opacity: 1; }\n 100% { opacity: 0; transform: scale(1.02); }\n }\n @keyframes ag-pill-in {\n 0% { opacity: 0; transform: translateY(4px) scale(0.9); }\n 30% { opacity: 1; transform: translateY(0) scale(1); }\n 70% { opacity: 1; transform: translateY(0) scale(1); }\n 100% { opacity: 0; transform: translateY(-8px) scale(0.95); }\n }\n .ag-select-flash {\n position: fixed;\n pointer-events: none;\n z-index: ${Z_INDEX_OVERLAY};\n border: 2px solid #22c55e;\n background: rgba(34, 197, 94, 0.12);\n border-radius: 3px;\n box-sizing: border-box;\n animation: ag-flash 0.45s ease-out forwards;\n }\n .ag-select-pill {\n position: fixed;\n pointer-events: none;\n z-index: ${Z_INDEX_LABEL};\n display: flex;\n align-items: center;\n gap: 4px;\n background: #22c55e;\n color: #fff;\n font: 600 10px/1 -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n padding: 3px 8px;\n border-radius: 10px;\n white-space: nowrap;\n letter-spacing: 0.03em;\n text-transform: uppercase;\n box-shadow: 0 2px 8px rgba(34, 197, 94, 0.35);\n animation: ag-pill-in 0.9s ease-out forwards;\n }\n .ag-select-pill svg {\n width: 10px;\n height: 10px;\n flex-shrink: 0;\n }\n `;\n document.head.appendChild(style);\n}\n\nconst CHECK_SVG = `<svg viewBox=\"0 0 10 10\" fill=\"none\"><path d=\"M2 5.5l2 2 4-4\" stroke=\"#fff\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>`;\n\nexport function showSelectFeedback(element: Element): void {\n injectStyles();\n\n const rect = element.getBoundingClientRect();\n\n // Green flash overlay on the element\n const flash = document.createElement('div');\n flash.className = 'ag-select-flash';\n flash.style.top = `${rect.top}px`;\n flash.style.left = `${rect.left}px`;\n flash.style.width = `${rect.width}px`;\n flash.style.height = `${rect.height}px`;\n document.body.appendChild(flash);\n\n // \"Copied\" pill above the element\n const pill = document.createElement('div');\n pill.className = 'ag-select-pill';\n pill.innerHTML = `${CHECK_SVG} Copied`;\n document.body.appendChild(pill);\n\n // Position pill centered above the element (or below if no room)\n const pillWidth = 70; // approximate\n let pillLeft = rect.left + rect.width / 2 - pillWidth / 2;\n let pillTop = rect.top - 24;\n if (pillTop < 4) {\n pillTop = rect.bottom + 6;\n }\n // Clamp to viewport\n const vw = document.documentElement.clientWidth;\n if (pillLeft + pillWidth > vw - 4) pillLeft = vw - pillWidth - 4;\n if (pillLeft < 4) pillLeft = 4;\n\n pill.style.top = `${pillTop}px`;\n pill.style.left = `${pillLeft}px`;\n\n // Clean up after animations complete\n const cleanup = () => {\n flash.remove();\n pill.remove();\n };\n pill.addEventListener('animationend', cleanup);\n\n // Safety fallback\n setTimeout(cleanup, 1200);\n}\n\nexport function disposeFeedbackStyles(): void {\n document.getElementById(STYLE_ID)?.remove();\n}\n","import type {\n AngularGrabOptions,\n AngularGrabAPI,\n Plugin,\n ComponentResolver,\n SourceResolver,\n ElementContext,\n HistoryContext,\n HistoryEntry,\n ThemeMode,\n PendingAction,\n} from './types';\nimport { createStore } from './store';\nimport { createOverlayRenderer } from './overlay/overlay-renderer';\nimport { createCrosshair } from './overlay/crosshair';\nimport { showToast, disposeToast } from './overlay/toast';\nimport { createElementPicker } from './picker/element-picker';\nimport { createKeyboardHandler, isMac } from './keyboard/keyboard-handler';\nimport { copyElement, buildElementContext } from './clipboard/copy';\nimport { createPluginRegistry } from './plugins/plugin-registry';\nimport { createThemeManager } from './toolbar/theme-manager';\nimport { createToolbarRenderer } from './toolbar/toolbar-renderer';\nimport { createHistoryPopover } from './toolbar/history-popover';\nimport { createActionsMenu } from './toolbar/actions-menu';\nimport { createCommentPopover } from './toolbar/comment-popover';\nimport { copyElementSnippet, copyElementHtml, copyElementStyles, copyWithComment } from './toolbar/copy-actions';\nimport { createFreezeOverlay } from './overlay/freeze-overlay';\nimport { showSelectFeedback, disposeFeedbackStyles } from './overlay/select-feedback';\nimport { TOOLBAR_TOAST_OFFSET } from './constants';\n\nconst MAX_HISTORY = 50;\n\nfunction toHistoryContext(ctx: ElementContext): HistoryContext {\n return {\n html: ctx.html,\n componentName: ctx.componentName,\n filePath: ctx.filePath,\n line: ctx.line,\n column: ctx.column,\n componentStack: ctx.componentStack,\n selector: ctx.selector,\n cssClasses: ctx.cssClasses,\n };\n}\n\nfunction getDefaultOptions(): AngularGrabOptions {\n return {\n activationKey: isMac() ? 'Meta+C' : 'Ctrl+C',\n activationMode: 'hold',\n keyHoldDuration: 0,\n maxContextLines: 20,\n enabled: true,\n enableInInputs: false,\n devOnly: true,\n showToolbar: true,\n themeMode: 'dark',\n };\n}\n\nexport function init(options?: Partial<AngularGrabOptions>): AngularGrabAPI {\n return createGrabInstance(options);\n}\n\n/** Check Angular's dev mode flag. Returns true if in dev mode or if the flag is absent. */\nfunction isDevMode(): boolean {\n try {\n // Angular sets ngDevMode to false in production builds\n const ng = (globalThis as any).ngDevMode;\n return typeof ng === 'undefined' || !!ng;\n } catch {\n return true;\n }\n}\n\n/** No-op API returned when devOnly is true and the app is in production. */\nfunction createNoopApi(): AngularGrabAPI {\n const noop = () => {};\n return {\n activate: noop,\n deactivate: noop,\n toggle: noop,\n isActive: () => false,\n setOptions: noop,\n registerPlugin: noop,\n unregisterPlugin: noop,\n setComponentResolver: noop,\n setSourceResolver: noop,\n showToolbar: noop,\n hideToolbar: noop,\n setThemeMode: noop,\n getHistory: () => [],\n clearHistory: noop,\n dispose: noop,\n };\n}\n\nexport function createGrabInstance(options?: Partial<AngularGrabOptions>): AngularGrabAPI {\n const defaults = getDefaultOptions();\n const merged: AngularGrabOptions = { ...defaults, ...options };\n\n if (merged.devOnly && !isDevMode()) {\n return createNoopApi();\n }\n\n const store = createStore(merged);\n const overlay = createOverlayRenderer();\n const crosshair = createCrosshair();\n const freezeOverlay = createFreezeOverlay();\n const pluginRegistry = createPluginRegistry();\n const themeManager = createThemeManager();\n\n let componentResolver: ComponentResolver | null = null;\n let sourceResolver: SourceResolver | null = null;\n\n // Per-instance state for last selected element (not in store to avoid serialization issues)\n let lastSelectedElement: WeakRef<Element> | null = null;\n let lastSelectedContext: ElementContext | null = null;\n let idCounter = 0;\n\n function nextId(): string {\n return `ag-${++idCounter}-${Date.now()}`;\n }\n\n // Apply initial theme\n themeManager.apply(store.state.toolbar.themeMode);\n\n // Set toast bottom offset when toolbar is visible\n updateToastOffset();\n\n // --- Toolbar element check (aggregates all toolbar-related UI) ---\n function isAnyToolbarElement(el: Element): boolean {\n return toolbar.isToolbarElement(el)\n || historyPopover.isPopoverElement(el)\n || actionsMenu.isMenuElement(el)\n || commentPopover.isPopoverElement(el)\n || freezeOverlay.isFreezeElement(el);\n }\n\n // --- History management ---\n function addHistoryEntry(context: ElementContext, snippet: string): void {\n const entry: HistoryEntry = {\n id: nextId(),\n context: toHistoryContext(context),\n snippet,\n timestamp: Date.now(),\n };\n\n lastSelectedElement = new WeakRef(context.element);\n lastSelectedContext = context;\n\n const history = [entry, ...store.state.toolbar.history].slice(0, MAX_HISTORY);\n store.state.toolbar = { ...store.state.toolbar, history };\n }\n\n /** Returns the live Element if it's still connected to the DOM. */\n function getLastSelectedElement(): Element | null {\n const el = lastSelectedElement?.deref() ?? null;\n if (el && !el.isConnected) {\n lastSelectedElement = null;\n lastSelectedContext = null;\n return null;\n }\n return el;\n }\n\n // --- Close all popovers ---\n function closeAllPopovers(): void {\n historyPopover.hide();\n actionsMenu.hide();\n commentPopover.hide();\n }\n\n // --- Pending action execution ---\n async function executePendingAction(pending: PendingAction, element: Element): Promise<void> {\n const context = buildElementContext(element, componentResolver, sourceResolver);\n const maxLines = store.state.options.maxContextLines;\n\n lastSelectedElement = new WeakRef(element);\n lastSelectedContext = context;\n store.state.toolbar = { ...store.state.toolbar, pendingAction: null };\n\n switch (pending.type) {\n case 'copy-element': {\n const ok = await copyElementSnippet(context, maxLines, pluginRegistry);\n if (ok) {\n showSelectFeedback(element);\n addHistoryEntry(context, '');\n }\n break;\n }\n case 'copy-styles':\n await copyElementStyles(element);\n break;\n case 'copy-html':\n await copyElementHtml(context, pluginRegistry);\n break;\n case 'comment':\n commentPopover.show();\n return; // Don't deactivate — user still needs to type\n }\n }\n\n // --- Picker ---\n const picker = createElementPicker({\n overlay,\n crosshair,\n getComponentResolver: () => componentResolver,\n getSourceResolver: () => sourceResolver,\n isToolbarElement: isAnyToolbarElement,\n getFreezeElement: () => freezeOverlay.getElement(),\n onHover(element) {\n store.state.hoveredElement = element;\n if (element) {\n pluginRegistry.callHook('onElementHover', element);\n }\n },\n async onSelect(element) {\n const pending = store.state.toolbar.pendingAction;\n\n if (pending) {\n await executePendingAction(pending, element);\n // Comment flow keeps picker active\n if (pending.type !== 'comment') {\n doDeactivate();\n }\n return;\n }\n\n // Default copy flow\n const result = await copyElement(element, {\n getComponentResolver: () => componentResolver,\n getSourceResolver: () => sourceResolver,\n getMaxContextLines: () => store.state.options.maxContextLines,\n pluginRegistry,\n });\n\n if (result) {\n showSelectFeedback(element);\n addHistoryEntry(result.context, result.snippet);\n }\n },\n });\n\n function doActivate(): void {\n if (!store.state.options.enabled) return;\n if (store.state.active) return;\n\n // Show toolbar if it was dismissed\n if (store.state.toolbar.visible === false && store.state.options.showToolbar) {\n store.state.toolbar = { ...store.state.toolbar, visible: true };\n toolbar.show();\n toolbar.update(store.state);\n }\n\n store.state.active = true;\n picker.activate();\n pluginRegistry.callHook('onActivate');\n toolbar.update(store.state);\n }\n\n function doDeactivate(): void {\n if (!store.state.active) return;\n\n store.state.active = false;\n store.state.frozen = false;\n freezeOverlay.hide();\n store.state.toolbar = { ...store.state.toolbar, pendingAction: null };\n picker.deactivate();\n pluginRegistry.callHook('onDeactivate');\n toolbar.update(store.state);\n }\n\n function toggleFreeze(): void {\n store.state.frozen = !store.state.frozen;\n if (store.state.frozen) {\n freezeOverlay.show(store.state.hoveredElement);\n } else {\n freezeOverlay.hide();\n }\n toolbar.update(store.state);\n }\n\n // --- Toolbar ---\n const toolbar = createToolbarRenderer({\n onSelectionMode() {\n closeAllPopovers();\n if (store.state.active) {\n doDeactivate();\n } else {\n doActivate();\n }\n },\n\n onHistory() {\n actionsMenu.hide();\n commentPopover.hide();\n if (historyPopover.isVisible()) {\n historyPopover.hide();\n } else {\n historyPopover.show([...store.state.toolbar.history]);\n }\n },\n\n onActions() {\n historyPopover.hide();\n commentPopover.hide();\n if (actionsMenu.isVisible()) {\n actionsMenu.hide();\n } else {\n actionsMenu.show();\n }\n },\n\n onFreeze() {\n closeAllPopovers();\n if (!store.state.active) {\n doActivate();\n }\n toggleFreeze();\n },\n\n onThemeToggle() {\n const current = store.state.toolbar.themeMode;\n const newMode: ThemeMode = current === 'dark' ? 'light' : current === 'light' ? 'system' : 'dark';\n store.state.toolbar = { ...store.state.toolbar, themeMode: newMode };\n themeManager.apply(newMode);\n toolbar.update(store.state);\n },\n\n onEnableToggle() {\n closeAllPopovers();\n const newEnabled = !store.state.options.enabled;\n store.state.options = { ...store.state.options, enabled: newEnabled };\n if (!newEnabled) {\n doDeactivate();\n }\n toolbar.update(store.state);\n },\n\n onDismiss() {\n closeAllPopovers();\n doDeactivate();\n store.state.toolbar = { ...store.state.toolbar, visible: false };\n toolbar.hide();\n },\n });\n\n // --- History Popover ---\n const historyPopover = createHistoryPopover({\n async onEntryClick(entry: HistoryEntry) {\n historyPopover.hide();\n try {\n await navigator.clipboard.writeText(entry.snippet);\n showToast('Re-copied to clipboard', {\n componentName: entry.context.componentName,\n filePath: entry.context.filePath,\n line: entry.context.line,\n column: entry.context.column,\n cssClasses: entry.context.cssClasses,\n });\n } catch {\n // clipboard write failed silently\n }\n },\n });\n\n // --- Actions Menu ---\n const actionsMenu = createActionsMenu({\n onCopyElement() {\n if (lastSelectedContext) {\n copyElementSnippet(lastSelectedContext, store.state.options.maxContextLines, pluginRegistry);\n } else {\n store.state.toolbar = { ...store.state.toolbar, pendingAction: { type: 'copy-element' } };\n doActivate();\n }\n },\n\n onCopyStyles() {\n const el = getLastSelectedElement();\n if (el) {\n copyElementStyles(el);\n } else {\n store.state.toolbar = { ...store.state.toolbar, pendingAction: { type: 'copy-styles' } };\n doActivate();\n }\n },\n\n onCopyHtml() {\n if (lastSelectedContext) {\n copyElementHtml(lastSelectedContext, pluginRegistry);\n } else {\n store.state.toolbar = { ...store.state.toolbar, pendingAction: { type: 'copy-html' } };\n doActivate();\n }\n },\n\n onComment() {\n if (lastSelectedContext) {\n commentPopover.show();\n } else {\n store.state.toolbar = { ...store.state.toolbar, pendingAction: { type: 'comment' } };\n doActivate();\n }\n },\n\n onClearHistory() {\n lastSelectedContext = null;\n lastSelectedElement = null;\n store.state.toolbar = { ...store.state.toolbar, history: [] };\n },\n });\n\n // --- Comment Popover ---\n const commentPopover = createCommentPopover({\n async onSubmit(comment: string) {\n if (lastSelectedContext) {\n await copyWithComment(lastSelectedContext, comment, store.state.options.maxContextLines, pluginRegistry);\n }\n if (store.state.active) {\n doDeactivate();\n }\n },\n onCancel() {\n if (store.state.active) {\n doDeactivate();\n }\n },\n });\n\n // --- Close popovers on outside click ---\n function handleDocumentClick(e: MouseEvent): void {\n const target = e.target as Element | null;\n if (!target) return;\n\n if (isAnyToolbarElement(target)) return;\n\n // Close popovers if click is outside toolbar UI\n if (historyPopover.isVisible() || actionsMenu.isVisible() || commentPopover.isVisible()) {\n closeAllPopovers();\n }\n }\n document.addEventListener('click', handleDocumentClick);\n\n // --- Toast offset helper ---\n function updateToastOffset(): void {\n if (store.state.toolbar.visible) {\n document.documentElement.style.setProperty('--ag-toast-bottom', TOOLBAR_TOAST_OFFSET);\n } else {\n document.documentElement.style.removeProperty('--ag-toast-bottom');\n }\n }\n\n // --- Freeze key handler (F key during selection mode) ---\n function handleFreezeKey(e: KeyboardEvent): void {\n if (!store.state.active) return;\n if (e.key.toLowerCase() !== 'f') return;\n const tag = (e.target as Element)?.tagName;\n if (tag === 'INPUT' || tag === 'TEXTAREA') return;\n if ((e.target as HTMLElement)?.isContentEditable) return;\n\n e.preventDefault();\n toggleFreeze();\n }\n document.addEventListener('keydown', handleFreezeKey, true);\n\n // --- Keyboard handler ---\n const keyboard = createKeyboardHandler({\n getActivationKey: () => store.state.options.activationKey,\n getActivationMode: () => store.state.options.activationMode,\n getKeyHoldDuration: () => store.state.options.keyHoldDuration,\n getEnableInInputs: () => store.state.options.enableInInputs,\n onActivate: doActivate,\n onDeactivate: doDeactivate,\n isActive: () => store.state.active,\n });\n\n // Build the API object so plugins can reference it\n const api: AngularGrabAPI = {\n activate: doActivate,\n deactivate: doDeactivate,\n\n toggle(): void {\n if (store.state.active) {\n doDeactivate();\n } else {\n doActivate();\n }\n },\n\n isActive(): boolean {\n return store.state.active;\n },\n\n setOptions(opts: Partial<AngularGrabOptions>): void {\n store.state.options = { ...store.state.options, ...opts };\n },\n\n registerPlugin(plugin: Plugin): void {\n if (plugin.options) {\n store.state.options = { ...store.state.options, ...plugin.options };\n }\n if (plugin.theme) {\n themeManager.applyOverrides(plugin.theme);\n }\n pluginRegistry.register(plugin, api);\n },\n\n unregisterPlugin(name: string): void {\n pluginRegistry.unregister(name);\n },\n\n setComponentResolver(resolver: ComponentResolver): void {\n componentResolver = resolver;\n },\n\n setSourceResolver(resolver: SourceResolver): void {\n sourceResolver = resolver;\n },\n\n showToolbar(): void {\n store.state.toolbar = { ...store.state.toolbar, visible: true };\n toolbar.show();\n toolbar.update(store.state);\n updateToastOffset();\n },\n\n hideToolbar(): void {\n closeAllPopovers();\n store.state.toolbar = { ...store.state.toolbar, visible: false };\n toolbar.hide();\n updateToastOffset();\n },\n\n setThemeMode(mode: ThemeMode): void {\n store.state.toolbar = { ...store.state.toolbar, themeMode: mode };\n themeManager.apply(mode);\n toolbar.update(store.state);\n },\n\n getHistory(): HistoryEntry[] {\n return [...store.state.toolbar.history];\n },\n\n clearHistory(): void {\n lastSelectedContext = null;\n lastSelectedElement = null;\n store.state.toolbar = { ...store.state.toolbar, history: [] };\n },\n\n dispose(): void {\n doDeactivate();\n document.removeEventListener('click', handleDocumentClick);\n document.removeEventListener('keydown', handleFreezeKey, true);\n keyboard.dispose();\n picker.dispose();\n overlay.dispose();\n crosshair.dispose();\n freezeOverlay.dispose();\n disposeToast();\n disposeFeedbackStyles();\n pluginRegistry.dispose();\n closeAllPopovers();\n toolbar.dispose();\n historyPopover.dispose();\n actionsMenu.dispose();\n commentPopover.dispose();\n themeManager.dispose();\n document.documentElement.style.removeProperty('--ag-toast-bottom');\n },\n };\n\n // Start listening for keyboard shortcuts\n if (store.state.options.enabled) {\n keyboard.start();\n }\n\n // Toolbar starts hidden — it appears when selection mode is first activated\n store.state.toolbar = { ...store.state.toolbar, visible: false };\n\n // React to enabled option changes\n store.subscribe((state, key) => {\n if (key === 'options') {\n if (state.options.enabled) {\n keyboard.start();\n } else {\n keyboard.stop();\n doDeactivate();\n }\n }\n if (key === 'toolbar') {\n updateToastOffset();\n }\n });\n\n return api;\n}\n","import { filterAngularClasses, type ElementContext, type ComponentStackEntry } from '../../core';\nimport { resolveComponent } from './component-resolver';\nimport { resolveSource, resolveSourceForComponent } from './source-resolver';\n\nconst MAX_HTML_LENGTH = 2000;\n\nexport function buildContext(element: Element): ElementContext {\n const compResult = resolveComponent(element);\n const { filePath, line, column } = resolveSource(element);\n const html = extractHtml(element);\n const selector = generateSelector(element);\n\n const cssClasses = filterAngularClasses(element.classList);\n\n const componentStack: ComponentStackEntry[] = compResult.stack.map((entry) => {\n const src = resolveSourceForComponent(entry.name);\n return {\n name: entry.name,\n filePath: src.filePath,\n line: src.line,\n column: src.column,\n };\n });\n\n return {\n element,\n html,\n componentName: compResult.name,\n filePath,\n line,\n column,\n componentStack,\n selector,\n cssClasses,\n };\n}\n\nfunction extractHtml(element: Element): string {\n const html = element.outerHTML;\n if (html.length <= MAX_HTML_LENGTH) return html;\n return html.slice(0, MAX_HTML_LENGTH) + '<!-- truncated -->';\n}\n\nfunction generateSelector(element: Element): string {\n const parts: string[] = [];\n let current: Element | null = element;\n\n while (current && current !== document.documentElement) {\n let selector = current.tagName.toLowerCase();\n\n if (current.id) {\n selector += `#${current.id}`;\n parts.unshift(selector);\n break;\n }\n\n const className = current.getAttribute('class');\n if (className) {\n const classes = className\n .trim()\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, 3);\n if (classes.length > 0) {\n selector += '.' + classes.join('.');\n }\n }\n\n // Add nth-of-type if there are sibling elements with the same tag\n const parent = current.parentElement;\n if (parent) {\n const siblings = Array.from(parent.children).filter(\n (s) => s.tagName === current!.tagName\n );\n if (siblings.length > 1) {\n const index = siblings.indexOf(current) + 1;\n selector += `:nth-of-type(${index})`;\n }\n }\n\n parts.unshift(selector);\n current = current.parentElement;\n }\n\n return parts.join(' > ');\n}\n","import { init } from '../core';\nimport type { AngularGrabAPI, AngularGrabOptions, Plugin } from '../core';\nimport { resolveComponent } from './resolvers/component-resolver';\nimport { resolveSource } from './resolvers/source-resolver';\n\ndeclare const ngDevMode: boolean | undefined;\n\nlet instance: AngularGrabAPI | null = null;\n\n/**\n * Initialize angular-grab. Registers Angular-specific component and source\n * resolvers, then returns the API handle. Idempotent — subsequent calls\n * return the same instance.\n */\nexport function initAngularGrab(options?: Partial<AngularGrabOptions>): AngularGrabAPI {\n if (instance) return instance;\n\n // No-op in production\n if (options?.devOnly !== false && typeof ngDevMode !== 'undefined' && !ngDevMode) {\n instance = createNoOpApi();\n return instance;\n }\n\n instance = init(options);\n instance.setComponentResolver((el) => resolveComponent(el));\n instance.setSourceResolver((el) => resolveSource(el));\n\n return instance;\n}\n\nexport function getAngularGrabApi(): AngularGrabAPI | null {\n return instance;\n}\n\nexport function registerAngularGrabPlugin(plugin: Plugin): void {\n instance?.registerPlugin(plugin);\n}\n\nexport function disposeAngularGrab(): void {\n instance?.dispose();\n instance = null;\n}\n\nfunction createNoOpApi(): AngularGrabAPI {\n return {\n activate() {},\n deactivate() {},\n toggle() {},\n isActive() { return false; },\n setOptions() {},\n registerPlugin() {},\n unregisterPlugin() {},\n setComponentResolver() {},\n setSourceResolver() {},\n showToolbar() {},\n hideToolbar() {},\n setThemeMode() {},\n getHistory() { return []; },\n clearHistory() {},\n dispose() {},\n };\n}\n","import {\n InjectionToken,\n makeEnvironmentProviders,\n provideEnvironmentInitializer,\n type EnvironmentProviders,\n} from '@angular/core';\nimport type { AngularGrabOptions, AngularGrabAPI } from '../core';\nimport { initAngularGrab } from './angular-grab.service';\n\nexport const ANGULAR_GRAB_API = new InjectionToken<AngularGrabAPI>('ANGULAR_GRAB_API');\n\nexport function provideAngularGrab(\n options?: Partial<AngularGrabOptions>,\n): EnvironmentProviders {\n return makeEnvironmentProviders([\n {\n provide: ANGULAR_GRAB_API,\n useFactory: () => initAngularGrab(options),\n },\n provideEnvironmentInitializer(() => initAngularGrab(options)),\n ]);\n}\n"],"mappings":";AAMO,SAAS,WAA8B;AAC5C,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,SAAQ,OAAe,MAAM;AAC/B;AAEO,SAAS,mBAAmB,MAAsB;AACvD,SAAO,KAAK,WAAW,GAAG,IAAI,KAAK,MAAM,CAAC,IAAI;AAChD;;;ACXO,SAAS,iBAAiB,SAI/B;AACA,QAAM,KAAK,SAAS;AACpB,MAAI,CAAC,GAAI,QAAO,EAAE,MAAM,MAAM,aAAa,MAAM,OAAO,CAAC,EAAE;AAE3D,QAAM,QAA8D,CAAC;AACrE,QAAM,OAAO,oBAAI,IAAS;AAG1B,MAAI,UAA0B;AAC9B,SAAO,SAAS;AACd,UAAM,OAAO,GAAG,aAAa,OAAO;AACpC,QAAI,QAAQ,CAAC,KAAK,IAAI,IAAI,GAAG;AAC3B,WAAK,IAAI,IAAI;AACb,YAAM,KAAK;AAAA,QACT,MAAM,mBAAmB,KAAK,YAAY,IAAI;AAAA,QAC9C,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AACA,cAAU,QAAQ;AAAA,EACpB;AAGA,MAAI,MAAM,WAAW,GAAG;AACtB,QAAI,OAAuB;AAC3B,WAAO,MAAM;AACX,YAAM,SAAS,GAAG,mBAAmB,IAAI;AACzC,UAAI,UAAU,CAAC,KAAK,IAAI,MAAM,GAAG;AAC/B,aAAK,IAAI,MAAM;AAEf,YAAI,OAAuB,KAAK;AAChC,eAAO,MAAM;AACX,cAAI,GAAG,aAAa,IAAI,MAAM,OAAQ;AACtC,iBAAO,KAAK;AAAA,QACd;AACA,cAAM,KAAK;AAAA,UACT,MAAM,mBAAmB,OAAO,YAAY,IAAI;AAAA,UAChD,aAAa,QAAQ,KAAK;AAAA,QAC5B,CAAC;AAED,kBAAU,MAAM,iBAAiB,KAAK,eAAe,iBAAiB;AACtE,eAAO,SAAS;AACd,gBAAM,OAAO,GAAG,aAAa,OAAO;AACpC,cAAI,QAAQ,CAAC,KAAK,IAAI,IAAI,GAAG;AAC3B,iBAAK,IAAI,IAAI;AACb,kBAAM,KAAK;AAAA,cACT,MAAM,mBAAmB,KAAK,YAAY,IAAI;AAAA,cAC9C,aAAa;AAAA,YACf,CAAC;AAAA,UACH;AACA,oBAAU,QAAQ;AAAA,QACpB;AACA;AAAA,MACF;AACA,aAAO,KAAK;AAAA,IACd;AAAA,EACF;AAEA,QAAM,UAAU,MAAM,SAAS,IAAI,MAAM,CAAC,IAAI,EAAE,MAAM,MAAM,aAAa,KAAK;AAE9E,SAAO;AAAA,IACL,MAAM,QAAQ;AAAA,IACd,aAAa,QAAQ;AAAA,IACrB;AAAA,EACF;AACF;;;AC/DA,SAAS,eAAsD;AAC7D,SAAQ,WAAmB,+BAA+B;AAC5D;AAEO,SAAS,cAAc,SAI5B;AACA,QAAM,YAAY,aAAa;AAC/B,MAAI,CAAC,UAAW,QAAO,EAAE,UAAU,MAAM,MAAM,MAAM,QAAQ,KAAK;AAElE,QAAM,KAAK,SAAS;AACpB,MAAI,CAAC,GAAI,QAAO,EAAE,UAAU,MAAM,MAAM,MAAM,QAAQ,KAAK;AAG3D,QAAM,gBAAgB,kBAAkB,SAAS,EAAE;AACnD,MAAI,CAAC,cAAe,QAAO,EAAE,UAAU,MAAM,MAAM,MAAM,QAAQ,KAAK;AAEtE,QAAM,QAAQ,UAAU,aAAa;AACrC,MAAI,CAAC,MAAO,QAAO,EAAE,UAAU,MAAM,MAAM,MAAM,QAAQ,KAAK;AAE9D,SAAO,EAAE,UAAU,MAAM,MAAM,MAAM,MAAM,MAAM,QAAQ,KAAK;AAChE;AAEO,SAAS,0BAA0B,eAIxC;AACA,QAAM,YAAY,aAAa;AAC/B,MAAI,CAAC,UAAW,QAAO,EAAE,UAAU,MAAM,MAAM,MAAM,QAAQ,KAAK;AAElE,QAAM,QAAQ,UAAU,aAAa;AACrC,MAAI,CAAC,MAAO,QAAO,EAAE,UAAU,MAAM,MAAM,MAAM,QAAQ,KAAK;AAE9D,SAAO,EAAE,UAAU,MAAM,MAAM,MAAM,MAAM,MAAM,QAAQ,KAAK;AAChE;AAEA,SAAS,kBAAkB,SAAkB,IAA+B;AAE1E,QAAM,SAAS,GAAG,aAAa,OAAO;AACtC,MAAI,OAAQ,QAAO,mBAAmB,OAAO,YAAY,IAAI;AAG7D,MAAI,UAA0B;AAC9B,SAAO,SAAS;AACd,UAAM,SAAS,GAAG,mBAAmB,OAAO;AAC5C,QAAI,OAAQ,QAAO,mBAAmB,OAAO,YAAY,IAAI;AAC7D,cAAU,QAAQ;AAAA,EACpB;AAEA,SAAO;AACT;;;AC3CO,SAAS,YAAY,gBAA2C;AACrE,QAAM,YAAY,oBAAI,IAAmB;AAEzC,QAAM,MAAiB;AAAA,IACrB,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,gBAAgB;AAAA,IAChB,SAAS;AAAA,IACT,SAAS;AAAA,MACP,SAAS,eAAe;AAAA,MACxB,WAAW,eAAe;AAAA,MAC1B,SAAS,CAAC;AAAA,MACV,eAAe;AAAA,IACjB;AAAA,EACF;AAEA,QAAM,QAAQ,IAAI,MAAM,KAAK;AAAA,IAC3B,IAAI,QAAQ,MAAM,OAAO;AACvB,YAAM,MAAM;AACZ,UAAI,OAAO,GAAG,MAAM,MAAO,QAAO;AAElC,cAAQ,IAAI,QAAQ,KAAK,KAAK;AAC9B,gBAAU,QAAQ,CAAC,OAAO,GAAG,OAAO,GAAG,CAAC;AACxC,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA,UAAU,UAAyB;AACjC,gBAAU,IAAI,QAAQ;AACtB,aAAO,MAAM,UAAU,OAAO,QAAQ;AAAA,IACxC;AAAA,EACF;AACF;;;ACnDO,IAAM,iBAAiB;AACvB,IAAM,oBAAoB;AAC1B,IAAM,kBAAkB;AACxB,IAAM,gBAAgB;AACtB,IAAM,kBAAkB;AACxB,IAAM,gBAAgB;AACtB,IAAM,kBAAkB;AAExB,IAAM,uBAAuB;AAC7B,IAAM,yBAAyB;;;ACPtC,IAAM,aAAa;AACnB,IAAM,WAAW;AACjB,IAAM,WAAW;AASV,SAAS,wBAAyC;AACvD,MAAI,UAAiC;AACrC,MAAI,QAA+B;AACnC,MAAI,QAAuB;AAC3B,MAAI,iBAAiC;AACrC,MAAI,uBAAsC;AAC1C,MAAI,oBAAmC;AACvC,MAAI,oBAA8B,CAAC;AAEnC,WAASA,gBAAqB;AAC5B,QAAI,SAAS,eAAe,QAAQ,EAAG;AAEvC,UAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,UAAM,KAAK;AACX,UAAM,cAAc;AAAA,SACf,UAAU;AAAA;AAAA;AAAA,mBAGA,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAMzB,QAAQ;AAAA;AAAA;AAAA,mBAGE,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAa5B,aAAS,KAAK,YAAY,KAAK;AAAA,EACjC;AAEA,WAAS,iBAAuB;AAC9B,QAAI,CAAC,SAAS;AACZ,MAAAA,cAAa;AACb,gBAAU,SAAS,cAAc,KAAK;AACtC,cAAQ,KAAK;AACb,eAAS,KAAK,YAAY,OAAO;AAAA,IACnC;AACA,QAAI,CAAC,OAAO;AACV,cAAQ,SAAS,cAAc,KAAK;AACpC,YAAM,KAAK;AACX,eAAS,KAAK,YAAY,KAAK;AAAA,IACjC;AAAA,EACF;AAEA,WAAS,kBAAwB;AAC/B,QAAI,CAAC,kBAAkB,CAAC,WAAW,CAAC,MAAO;AAE3C,UAAM,OAAO,eAAe,sBAAsB;AAGlD,QAAI,KAAK,UAAU,KAAK,KAAK,WAAW,KAAK,CAAC,eAAe,aAAa;AACxE,cAAQ,MAAM,UAAU;AACxB,YAAM,MAAM,UAAU;AACtB;AAAA,IACF;AAEA,YAAQ,MAAM,MAAM,GAAG,KAAK,GAAG;AAC/B,YAAQ,MAAM,OAAO,GAAG,KAAK,IAAI;AACjC,YAAQ,MAAM,QAAQ,GAAG,KAAK,KAAK;AACnC,YAAQ,MAAM,SAAS,GAAG,KAAK,MAAM;AACrC,YAAQ,MAAM,UAAU;AAExB,UAAM,MAAM,eAAe,QAAQ,YAAY;AAC/C,QAAI,YAAY,IAAI,GAAG;AACvB,QAAI,kBAAkB,SAAS,GAAG;AAChC,mBAAa,KAAK,kBAAkB,KAAK,GAAG,CAAC;AAAA,IAC/C;AACA,QAAI,sBAAsB;AACxB,mBAAa,OAAO,oBAAoB;AAAA,IAC1C;AACA,QAAI,mBAAmB;AACrB,mBAAa,WAAW,iBAAiB;AAAA,IAC3C;AACA,UAAM,cAAc;AAGpB,UAAM,cAAc;AACpB,UAAM,MAAM;AACZ,QAAI,WAAW,KAAK,MAAM,cAAc;AACxC,QAAI,WAAW,GAAG;AAChB,iBAAW,KAAK,SAAS;AAAA,IAC3B;AAGA,QAAI,YAAY,KAAK;AACrB,UAAM,MAAM,MAAM,GAAG,QAAQ;AAC7B,UAAM,MAAM,OAAO,GAAG,SAAS;AAC/B,UAAM,MAAM,UAAU;AAGtB,UAAM,YAAY,MAAM,sBAAsB;AAC9C,UAAM,gBAAgB,SAAS,gBAAgB;AAC/C,QAAI,UAAU,QAAQ,eAAe;AACnC,kBAAY,KAAK,IAAI,GAAG,gBAAgB,UAAU,KAAK;AACvD,YAAM,MAAM,OAAO,GAAG,SAAS;AAAA,IACjC;AACA,QAAI,YAAY,GAAG;AACjB,YAAM,MAAM,OAAO;AAAA,IACrB;AAAA,EACF;AAEA,WAAS,gBAAsB;AAC7B,oBAAgB;AAChB,YAAQ,sBAAsB,aAAa;AAAA,EAC7C;AAEA,WAAS,eAAqB;AAC5B,QAAI,UAAU,MAAM;AAClB,2BAAqB,KAAK;AAC1B,cAAQ;AAAA,IACV;AAAA,EACF;AAEA,SAAO;AAAA,IACL,KAAK,SAAkB,eAA8B,YAA4B,YAA6B;AAC5G,qBAAe;AACf,uBAAiB;AACjB,6BAAuB;AACvB,0BAAoB,cAAc;AAClC,0BAAoB,cAAc,CAAC;AACnC,mBAAa;AACb,oBAAc;AAAA,IAChB;AAAA,IAEA,OAAa;AACX,mBAAa;AACb,uBAAiB;AACjB,6BAAuB;AACvB,0BAAoB;AACpB,0BAAoB,CAAC;AAErB,UAAI,QAAS,SAAQ,MAAM,UAAU;AACrC,UAAI,MAAO,OAAM,MAAM,UAAU;AAAA,IACnC;AAAA,IAEA,iBAAiB,IAAsB;AACrC,aAAO,OAAO,WAAW,OAAO,SAAS,GAAG,OAAO,cAAc,GAAG,OAAO;AAAA,IAC7E;AAAA,IAEA,UAAgB;AACd,mBAAa;AACb,uBAAiB;AACjB,6BAAuB;AACvB,0BAAoB;AACpB,0BAAoB,CAAC;AAErB,eAAS,OAAO;AAChB,aAAO,OAAO;AACd,eAAS,eAAe,QAAQ,GAAG,OAAO;AAC1C,gBAAU;AACV,cAAQ;AAAA,IACV;AAAA,EACF;AACF;;;ACjLA,IAAM,qBAAqB;AAC3B,IAAM,YAAY;AAClB,IAAM,YAAY;AASX,SAAS,kBAA6B;AAC3C,MAAI,QAA+B;AACnC,MAAI,QAA+B;AACnC,MAAI,YAAY;AAEhB,WAASC,gBAAqB;AAC5B,QAAI,SAAS,eAAe,kBAAkB,EAAG;AAEjD,UAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,UAAM,KAAK;AACX,UAAM,cAAc;AAAA;AAAA;AAAA;AAAA,mBAIL,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA,SAK3B,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,SAKT,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASd,aAAS,KAAK,YAAY,KAAK;AAAA,EACjC;AAEA,WAAS,iBAAuB;AAC9B,QAAI,CAAC,OAAO;AACV,MAAAA,cAAa;AACb,cAAQ,SAAS,cAAc,KAAK;AACpC,YAAM,KAAK;AACX,YAAM,YAAY;AAClB,eAAS,KAAK,YAAY,KAAK;AAAA,IACjC;AACA,QAAI,CAAC,OAAO;AACV,cAAQ,SAAS,cAAc,KAAK;AACpC,YAAM,KAAK;AACX,YAAM,YAAY;AAClB,eAAS,KAAK,YAAY,KAAK;AAAA,IACjC;AAAA,EACF;AAEA,WAAS,gBAAgB,GAAqB;AAC5C,QAAI,OAAO;AACT,YAAM,MAAM,MAAM,GAAG,EAAE,OAAO;AAAA,IAChC;AACA,QAAI,OAAO;AACT,YAAM,MAAM,OAAO,GAAG,EAAE,OAAO;AAAA,IACjC;AAAA,EACF;AAEA,SAAO;AAAA,IACL,WAAiB;AACf,UAAI,UAAW;AACf,kBAAY;AACZ,qBAAe;AACf,eAAS,KAAK,UAAU,IAAI,qBAAqB;AACjD,eAAS,iBAAiB,aAAa,iBAAiB,IAAI;AAAA,IAC9D;AAAA,IAEA,aAAmB;AACjB,UAAI,CAAC,UAAW;AAChB,kBAAY;AACZ,eAAS,KAAK,UAAU,OAAO,qBAAqB;AACpD,eAAS,oBAAoB,aAAa,iBAAiB,IAAI;AAC/D,UAAI,MAAO,OAAM,MAAM,MAAM;AAC7B,UAAI,MAAO,OAAM,MAAM,OAAO;AAAA,IAChC;AAAA,IAEA,mBAAmB,IAAsB;AACvC,aAAO,OAAO,SAAS,OAAO,SACzB,GAAG,OAAO,aAAa,GAAG,OAAO;AAAA,IACxC;AAAA,IAEA,UAAgB;AACd,WAAK,WAAW;AAChB,aAAO,OAAO;AACd,aAAO,OAAO;AACd,eAAS,eAAe,kBAAkB,GAAG,OAAO;AACpD,cAAQ;AACR,cAAQ;AAAA,IACV;AAAA,EACF;AACF;;;AC1GO,SAAS,WAAW,MAAsB;AAC/C,QAAM,MAAM,SAAS,cAAc,KAAK;AACxC,MAAI,cAAc;AAClB,SAAO,IAAI;AACb;AAEO,SAAS,qBAAqB,WAAmC;AACtE,SAAO,MAAM,KAAK,SAAS,EAAE,OAAO,OAAK,CAAC,EAAE,WAAW,KAAK,KAAK,CAAC,EAAE,WAAW,KAAK,CAAC;AACvF;AAEA,IAAM,aAAa;AACnB,IAAM,mBAAmB;AAElB,SAAS,kBAAkB,MAAsB;AACtD,SAAO,KAAK,QAAQ,YAAY,EAAE,EAAE,QAAQ,kBAAkB,EAAE;AAClE;;;ACZA,IAAM,WAAW;AACjB,IAAM,iBAAiB;AAGvB,IAAI,cAAoD;AAUxD,SAAS,oBAA0B;AACjC,MAAI,SAAS,eAAe,cAAc,EAAG;AAE7C,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM,KAAK;AACX,QAAM,cAAc;AAAA,OACf,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,iBAKE,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAcvB,QAAQ;AAAA;AAAA;AAAA;AAAA,OAIR,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAMR,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,OAKR,QAAQ;AAAA;AAAA;AAAA;AAAA,OAIR,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAQR,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,OAKR,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,OAKR,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAMR,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OASR,QAAQ;AAAA;AAAA;AAAA;AAAA;AAKb,WAAS,KAAK,YAAY,KAAK;AACjC;AAEA,SAAS,mBAAmC;AAC1C,MAAI,QAAQ,SAAS,eAAe,QAAQ;AAC5C,MAAI,CAAC,OAAO;AACV,sBAAkB;AAClB,YAAQ,SAAS,cAAc,KAAK;AACpC,UAAM,KAAK;AACX,aAAS,KAAK,YAAY,KAAK;AAAA,EACjC;AACA,SAAO;AACT;AAEA,IAAM,gBAAgB;AAEf,SAAS,UAAU,SAAiB,QAAsB,aAAa,MAAY;AACxF,QAAM,QAAQ,iBAAiB;AAE/B,MAAI,OAAO,gCAAgC,aAAa,gCAAgC,WAAW,OAAO,CAAC;AAE3G,MAAI,QAAQ;AACV,YAAQ;AAER,QAAI,OAAO,eAAe;AACxB,cAAQ,uGAAuG,WAAW,OAAO,aAAa,CAAC;AAAA,IACjJ;AAEA,QAAI,OAAO,UAAU;AACnB,UAAI,MAAM,OAAO;AACjB,UAAI,OAAO,QAAQ,KAAM,QAAO,IAAI,OAAO,IAAI;AAE/C,UAAI,YAAY,iBAAiB,UAAU,OAAO,QAAQ,CAAC;AAC3D,UAAI,OAAO,QAAQ,KAAM,cAAa,IAAI,OAAO,IAAI;AACrD,UAAI,OAAO,QAAQ,QAAQ,OAAO,UAAU,KAAM,cAAa,IAAI,OAAO,MAAM;AAEhF,cAAQ;AACR,cAAQ,uCAAuC,WAAW,SAAS,CAAC,6BAA6B,WAAW,GAAG,CAAC;AAChH,cAAQ;AAAA,IACV;AAEA,QAAI,OAAO,cAAc,OAAO,WAAW,SAAS,GAAG;AACrD,YAAM,UAAU,OAAO,WAAW,IAAI,CAAC,MAAM,IAAI,WAAW,CAAC,CAAC,EAAE,EAAE,KAAK,GAAG;AAC1E,cAAQ,qGAAqG,OAAO;AAAA,IACtH;AAEA,YAAQ;AAAA,EACV;AAEA,QAAM,YAAY;AAElB,MAAI,aAAa;AACf,iBAAa,WAAW;AACxB,kBAAc;AAAA,EAChB;AAGA,QAAM,UAAU,OAAO,kBAAkB;AACzC,OAAK,MAAM;AAEX,QAAM,UAAU,IAAI,kBAAkB;AAEtC,gBAAc,WAAW,MAAM;AAC7B,UAAM,UAAU,OAAO,kBAAkB;AACzC,kBAAc;AAAA,EAChB,GAAG,UAAU;AACf;AAEO,SAAS,eAAqB;AACnC,MAAI,aAAa;AACf,iBAAa,WAAW;AACxB,kBAAc;AAAA,EAChB;AACA,WAAS,eAAe,QAAQ,GAAG,OAAO;AAC1C,WAAS,eAAe,cAAc,GAAG,OAAO;AAClD;;;ACvJO,SAAS,oBAAoB,MAAwC;AAC1E,MAAI,iBAAiC;AACrC,MAAI,YAAY;AAEhB,WAAS,qBAAqB,IAA4B;AACxD,UAAM,WAAW,KAAK,qBAAqB;AAC3C,QAAI,CAAC,SAAU,QAAO;AAEtB,UAAM,SAAS,SAAS,EAAE;AAC1B,WAAO,QAAQ,QAAQ;AAAA,EACzB;AAEA,WAAS,kBAAkB,IAA4B;AACrD,UAAM,WAAW,KAAK,kBAAkB;AACxC,QAAI,CAAC,SAAU,QAAO;AAEtB,UAAM,SAAS,SAAS,EAAE;AAC1B,QAAI,CAAC,QAAQ,SAAU,QAAO;AAE9B,QAAI,OAAO,OAAO;AAClB,QAAI,OAAO,QAAQ,MAAM;AACvB,cAAQ,IAAI,OAAO,IAAI;AAAA,IACzB;AACA,WAAO;AAAA,EACT;AAEA,WAAS,eAAe,GAAW,GAA2B;AAE5D,UAAM,WAAW,KAAK,mBAAmB;AACzC,QAAI,SAAU,UAAS,MAAM,gBAAgB;AAC7C,UAAM,SAAS,SAAS,iBAAiB,GAAG,CAAC;AAC7C,QAAI,SAAU,UAAS,MAAM,gBAAgB;AAC7C,WAAO;AAAA,EACT;AAEA,WAAS,gBAAgB,GAAqB;AAC5C,UAAM,SAAS,eAAe,EAAE,SAAS,EAAE,OAAO;AAClD,QAAI,CAAC,UAAU,KAAK,QAAQ,iBAAiB,MAAM,EAAG;AACtD,QAAI,KAAK,UAAU,mBAAmB,MAAM,EAAG;AAC/C,QAAI,KAAK,mBAAmB,MAAM,EAAG;AACrC,QAAI,WAAW,eAAgB;AAE/B,qBAAiB;AACjB,UAAM,gBAAgB,qBAAqB,MAAM;AACjD,UAAM,aAAa,kBAAkB,MAAM;AAC3C,UAAM,aAAa,qBAAqB,OAAO,SAAS;AACxD,SAAK,QAAQ,KAAK,QAAQ,eAAe,YAAY,UAAU;AAC/D,SAAK,QAAQ,MAAM;AAAA,EACrB;AAEA,WAAS,YAAY,GAAqB;AACxC,UAAM,SAAS,eAAe,EAAE,SAAS,EAAE,OAAO;AAClD,QAAI,WAAW,KAAK,mBAAmB,MAAM,KAAK,KAAK,UAAU,mBAAmB,MAAM,GAAI;AAE9F,MAAE,eAAe;AACjB,MAAE,gBAAgB;AAElB,QAAI,gBAAgB;AAClB,WAAK,SAAS,cAAc;AAAA,IAC9B;AAAA,EACF;AAEA,SAAO;AAAA,IACL,WAAiB;AACf,UAAI,UAAW;AACf,kBAAY;AACZ,WAAK,UAAU,SAAS;AACxB,eAAS,iBAAiB,aAAa,iBAAiB,IAAI;AAC5D,eAAS,iBAAiB,SAAS,aAAa,IAAI;AAAA,IACtD;AAAA,IAEA,aAAmB;AACjB,UAAI,CAAC,UAAW;AAChB,kBAAY;AACZ,uBAAiB;AACjB,WAAK,UAAU,WAAW;AAC1B,eAAS,oBAAoB,aAAa,iBAAiB,IAAI;AAC/D,eAAS,oBAAoB,SAAS,aAAa,IAAI;AACvD,WAAK,QAAQ,KAAK;AAClB,WAAK,QAAQ,IAAI;AAAA,IACnB;AAAA,IAEA,oBAAoC;AAClC,aAAO;AAAA,IACT;AAAA,IAEA,UAAgB;AACd,WAAK,WAAW;AAAA,IAClB;AAAA,EACF;AACF;;;ACzFO,SAAS,QAAiB;AAC/B,MAAI,OAAO,cAAc,YAAa,QAAO;AAC7C,QAAM,SAAU,UAAkB;AAClC,MAAI,QAAQ,SAAU,QAAO,OAAO,KAAK,OAAO,QAAQ;AACxD,SAAO,wBAAwB,KAAK,UAAU,SAAS;AACzD;AAEO,SAAS,cAAc,OAA0B;AACtD,QAAM,QAAQ,MAAM,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AAClD,QAAM,SAAoB;AAAA,IACxB,KAAK;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,KAAK;AAAA,EACP;AAEA,aAAW,QAAQ,OAAO;AACxB,UAAM,QAAQ,KAAK,YAAY;AAC/B,QAAI,UAAU,UAAU,UAAU,SAAS,UAAU,WAAW;AAC9D,aAAO,OAAO;AAAA,IAChB,WAAW,UAAU,UAAU,UAAU,WAAW;AAClD,aAAO,OAAO;AAAA,IAChB,WAAW,UAAU,SAAS;AAC5B,aAAO,QAAQ;AAAA,IACjB,WAAW,UAAU,SAAS,UAAU,UAAU;AAChD,aAAO,MAAM;AAAA,IACf,OAAO;AACL,aAAO,MAAM;AAAA,IACf;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,aAAa,GAAkB,QAA4B;AAClE,MAAI,OAAO,QAAQ,CAAC,EAAE,QAAS,QAAO;AACtC,MAAI,OAAO,QAAQ,CAAC,EAAE,QAAS,QAAO;AACtC,MAAI,OAAO,SAAS,CAAC,EAAE,SAAU,QAAO;AACxC,MAAI,OAAO,OAAO,CAAC,EAAE,OAAQ,QAAO;AAEpC,SAAO,EAAE,IAAI,YAAY,MAAM,OAAO;AACxC;AAEA,SAAS,eAAe,IAAiC;AACvD,MAAI,CAAC,MAAM,EAAE,cAAc,aAAc,QAAO;AAChD,QAAM,MAAM,GAAG;AACf,SAAO,QAAQ,WAAW,QAAQ,cAAc,GAAG;AACrD;AAEO,SAAS,sBAAsB,MAA4C;AAChF,MAAI,YAAkD;AACtD,MAAI,gBAAgB;AACpB,MAAI,YAAY;AAEhB,WAAS,cAAc,GAAwB;AAC7C,QAAI,CAAC,KAAK,kBAAkB,KAAK,eAAe,EAAE,MAAM,EAAG;AAE3D,UAAM,SAAS,cAAc,KAAK,iBAAiB,CAAC;AACpD,QAAI,CAAC,aAAa,GAAG,MAAM,EAAG;AAE9B,UAAM,OAAO,KAAK,kBAAkB;AACpC,UAAM,eAAe,KAAK,mBAAmB;AAE7C,QAAI,SAAS,QAAQ;AACnB,QAAE,eAAe;AAEjB,UAAI,cAAe;AAEnB,UAAI,eAAe,GAAG;AACpB,YAAI,UAAW;AACf,oBAAY,WAAW,MAAM;AAC3B,0BAAgB;AAChB,eAAK,WAAW;AAAA,QAClB,GAAG,YAAY;AAAA,MACjB,OAAO;AACL,wBAAgB;AAChB,aAAK,WAAW;AAAA,MAClB;AAAA,IACF,OAAO;AAEL,QAAE,eAAe;AAAA,IACnB;AAAA,EACF;AAEA,WAAS,YAAY,GAAwB;AAC3C,UAAM,SAAS,cAAc,KAAK,iBAAiB,CAAC;AAGpD,QAAI,EAAE,IAAI,YAAY,MAAM,OAAO,IAAK;AAExC,UAAM,OAAO,KAAK,kBAAkB;AAEpC,QAAI,SAAS,QAAQ;AACnB,UAAI,WAAW;AACb,qBAAa,SAAS;AACtB,oBAAY;AAAA,MACd;AACA,UAAI,eAAe;AACjB,wBAAgB;AAChB,aAAK,aAAa;AAAA,MACpB;AAAA,IACF,OAAO;AAEL,UAAI,KAAK,SAAS,GAAG;AACnB,aAAK,aAAa;AAAA,MACpB,OAAO;AACL,aAAK,WAAW;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,QAAc;AACZ,UAAI,UAAW;AACf,kBAAY;AACZ,eAAS,iBAAiB,WAAW,eAAe,IAAI;AACxD,eAAS,iBAAiB,SAAS,aAAa,IAAI;AAAA,IACtD;AAAA,IAEA,OAAa;AACX,UAAI,CAAC,UAAW;AAChB,kBAAY;AAEZ,UAAI,WAAW;AACb,qBAAa,SAAS;AACtB,oBAAY;AAAA,MACd;AACA,sBAAgB;AAEhB,eAAS,oBAAoB,WAAW,eAAe,IAAI;AAC3D,eAAS,oBAAoB,SAAS,aAAa,IAAI;AAAA,IACzD;AAAA,IAEA,UAAgB;AACd,WAAK,KAAK;AAAA,IACZ;AAAA,EACF;AACF;;;AC/JA,SAAS,aAAa,MAAc,UAA0B;AAC5D,QAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,MAAI,MAAM,UAAU,SAAU,QAAO;AAErC,SAAO,MAAM,MAAM,GAAG,QAAQ,EAAE,KAAK,IAAI,IAAI;AAC/C;AAEA,SAAS,eAAe,MAAqB,UAAyB,MAAqB,QAA+B;AACxH,MAAI,eAAe;AACnB,MAAI,KAAM,iBAAgB,MAAM,IAAI;AACpC,MAAI,UAAU;AACZ,UAAM,MAAM,YACT,QAAQ,OAAO,IAAI,IAAI,KAAK,OAC5B,QAAQ,QAAQ,UAAU,OAAO,IAAI,MAAM,KAAK;AACnD,oBAAgB,eAAe,OAAO,GAAG,KAAK,MAAM,GAAG;AAAA,EACzD;AACA,SAAO;AACT;AAEO,SAAS,gBAAgB,SAAyB,iBAAiC;AACxF,QAAM,UAAU,kBAAkB,QAAQ,IAAI;AAC9C,QAAM,YAAY,aAAa,SAAS,eAAe;AAEvD,QAAM,QAAkB,CAAC,SAAS;AAElC,MAAI,QAAQ,eAAe,SAAS,GAAG;AACrC,eAAW,SAAS,QAAQ,gBAAgB;AAC1C,YAAM,KAAK,eAAe,MAAM,MAAM,MAAM,UAAU,MAAM,MAAM,MAAM,MAAM,CAAC;AAAA,IACjF;AAAA,EACF,WAAW,QAAQ,iBAAiB,QAAQ,UAAU;AACpD,UAAM,KAAK,eAAe,QAAQ,eAAe,QAAQ,UAAU,QAAQ,MAAM,QAAQ,MAAM,CAAC;AAAA,EAClG;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;;;ACxBA,SAAS,cAAc,IAAqB;AAC1C,QAAM,MAAM,GAAG,QAAQ,YAAY;AACnC,QAAM,KAAK,GAAG,KAAK,IAAI,GAAG,EAAE,KAAK;AACjC,QAAM,UAAU,qBAAqB,GAAG,SAAS,EAC9C,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,EAClB,KAAK,EAAE;AACV,SAAO,GAAG,GAAG,GAAG,EAAE,GAAG,OAAO;AAC9B;AAEA,SAAS,cAAc,IAAuB;AAC5C,SAAO,qBAAqB,GAAG,SAAS;AAC1C;AAEO,SAAS,oBACd,SACA,mBACA,gBACgB;AAChB,QAAM,aAAa,oBAAoB,OAAO;AAC9C,QAAM,YAAY,iBAAiB,OAAO;AAG1C,QAAM,iBAAwC,CAAC;AAC/C,MAAI,YAAY,OAAO;AACrB,eAAW,SAAS,WAAW,OAAO;AACpC,UAAI,WAA0B;AAC9B,UAAI,OAAsB;AAC1B,UAAI,SAAwB;AAE5B,UAAI,MAAM,eAAe,gBAAgB;AACvC,cAAM,MAAM,eAAe,MAAM,WAAW;AAC5C,YAAI,KAAK;AACP,qBAAW,IAAI;AACf,iBAAO,IAAI;AACX,mBAAS,IAAI;AAAA,QACf;AAAA,MACF;AAEA,qBAAe,KAAK,EAAE,MAAM,MAAM,MAAM,UAAU,MAAM,OAAO,CAAC;AAAA,IAClE;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,MAAM,QAAQ;AAAA,IACd,eAAe,YAAY,QAAQ;AAAA,IACnC,UAAU,WAAW,YAAY;AAAA,IACjC,MAAM,WAAW,QAAQ;AAAA,IACzB,QAAQ,WAAW,UAAU;AAAA,IAC7B;AAAA,IACA,UAAU,cAAc,OAAO;AAAA,IAC/B,YAAY,cAAc,OAAO;AAAA,EACnC;AACF;AAOA,eAAsB,YAAY,SAAkB,MAA4C;AAC9F,QAAM,UAAU;AAAA,IACd;AAAA,IACA,KAAK,qBAAqB;AAAA,IAC1B,KAAK,kBAAkB;AAAA,EACzB;AAEA,OAAK,eAAe,SAAS,mBAAmB,OAAO;AACvD,OAAK,eAAe,SAAS,gBAAgB,OAAO;AAEpD,MAAI,UAAU,gBAAgB,SAAS,KAAK,mBAAmB,CAAC;AAChE,YAAU,KAAK,eAAe,kBAAkB,SAAS,OAAO;AAEhE,MAAI;AACF,UAAM,UAAU,UAAU,UAAU,OAAO;AAC3C,UAAM,SAAsB;AAAA,MAC1B,eAAe,QAAQ;AAAA,MACvB,UAAU,QAAQ;AAAA,MAClB,MAAM,QAAQ;AAAA,MACd,QAAQ,QAAQ;AAAA,MAChB,YAAY,QAAQ;AAAA,IACtB;AACA,cAAU,uBAAuB,MAAM;AACvC,SAAK,eAAe,SAAS,iBAAiB,SAAS,SAAS,MAAS;AACzE,WAAO,EAAE,SAAS,QAAQ;AAAA,EAC5B,SAAS,KAAK;AACZ,UAAM,QAAQ,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;AAChE,SAAK,eAAe,SAAS,eAAe,KAAK;AACjD,WAAO;AAAA,EACT;AACF;;;AC5FO,SAAS,uBAAuC;AACrD,QAAM,UAAU,oBAAI,IAAoB;AACxC,QAAM,WAAW,oBAAI,IAA2B;AAEhD,SAAO;AAAA,IACL,SAAS,QAAgB,KAA2B;AAClD,UAAI,QAAQ,IAAI,OAAO,IAAI,GAAG;AAC5B,aAAK,WAAW,OAAO,IAAI;AAAA,MAC7B;AACA,cAAQ,IAAI,OAAO,MAAM,MAAM;AAE/B,UAAI,OAAO,OAAO;AAChB,cAAM,UAAU,OAAO,MAAM,GAAG;AAChC,YAAI,SAAS;AACX,mBAAS,IAAI,OAAO,MAAM,OAAO;AAAA,QACnC;AAAA,MACF;AAAA,IACF;AAAA,IAEA,WAAW,MAAoB;AAC7B,YAAM,UAAU,SAAS,IAAI,IAAI;AACjC,UAAI,SAAS;AACX,gBAAQ;AACR,iBAAS,OAAO,IAAI;AAAA,MACtB;AACA,cAAQ,OAAO,IAAI;AAAA,IACrB;AAAA,IAEA,SAAsC,aAAgB,MAAqD;AACzG,iBAAW,UAAU,QAAQ,OAAO,GAAG;AACrC,cAAM,OAAO,OAAO,QAAQ,QAAQ;AACpC,YAAI,MAAM;AACR,cAAI;AACF,YAAC,KAA+B,GAAG,IAAI;AAAA,UACzC,SAAS,KAAK;AACZ,oBAAQ,KAAK,0BAA0B,OAAO,IAAI,WAAW,QAAQ,YAAY,GAAG;AAAA,UACtF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IAEA,kBAAkB,MAAc,SAAiC;AAC/D,UAAI,SAAS;AACb,iBAAW,UAAU,QAAQ,OAAO,GAAG;AACrC,cAAM,YAAY,OAAO,OAAO;AAChC,YAAI,WAAW;AACb,cAAI;AACF,qBAAS,UAAU,QAAQ,OAAO;AAAA,UACpC,SAAS,KAAK;AACZ,oBAAQ,KAAK,0BAA0B,OAAO,IAAI,iCAAiC,GAAG;AAAA,UACxF;AAAA,QACF;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,IAEA,aAAoC;AAClC,aAAO,MAAM,KAAK,QAAQ,OAAO,CAAC;AAAA,IACpC;AAAA,IAEA,UAAgB;AACd,iBAAW,CAAC,IAAI,KAAK,SAAS;AAC5B,cAAM,UAAU,SAAS,IAAI,IAAI;AACjC,YAAI,SAAS;AACX,cAAI;AAAE,oBAAQ;AAAA,UAAG,QAAQ;AAAA,UAAe;AAAA,QAC1C;AAAA,MACF;AACA,eAAS,MAAM;AACf,cAAQ,MAAM;AAAA,IAChB;AAAA,EACF;AACF;;;AChFA,IAAMC,YAAW;AACjB,IAAM,oBAAoB;AAE1B,IAAM,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgClB,IAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiCnB,IAAM,eAA4C;AAAA,EAChD,oBAAoB;AAAA,EACpB,gBAAgB;AAAA,EAChB,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,oBAAoB;AACtB;AASO,SAAS,qBAAmC;AACjD,MAAI,UAAmC;AACvC,MAAI,aAAsC;AAC1C,MAAI,cAAyB;AAC7B,MAAI,aAAoC;AACxC,MAAI,eAA0D;AAE9D,WAAS,mBAAqC;AAC5C,QAAI,QAAS,QAAO;AAEpB,UAAM,WAAW,SAAS,eAAeA,SAAQ;AACjD,QAAI,UAAU;AACZ,gBAAU;AACV,aAAO;AAAA,IACT;AAEA,cAAU,SAAS,cAAc,OAAO;AACxC,YAAQ,KAAKA;AACb,aAAS,KAAK,YAAY,OAAO;AACjC,WAAO;AAAA,EACT;AAEA,WAAS,2BAA6C;AACpD,QAAI,WAAY,QAAO;AAEvB,iBAAa,SAAS,cAAc,OAAO;AAC3C,eAAW,KAAK;AAChB,aAAS,KAAK,YAAY,UAAU;AACpC,WAAO;AAAA,EACT;AAEA,WAAS,YAAY,MAAmC;AACtD,QAAI,SAAS,SAAU,QAAO;AAC9B,WAAO,OAAO,WAAW,8BAA8B,EAAE,UAAU,SAAS;AAAA,EAC9E;AAEA,WAAS,cAAc,UAAkC;AACvD,UAAM,KAAK,iBAAiB;AAC5B,OAAG,cAAc,aAAa,SAAS,YAAY;AAAA,EACrD;AAEA,WAAS,sBAA4B;AACnC,QAAI,cAAc,cAAc;AAC9B,iBAAW,oBAAoB,UAAU,YAAY;AAAA,IACvD;AACA,iBAAa;AACb,mBAAe;AAAA,EACjB;AAEA,SAAO;AAAA,IACL,MAAM,MAAuB;AAC3B,oBAAc;AACd,0BAAoB;AAEpB,oBAAc,YAAY,IAAI,CAAC;AAE/B,UAAI,SAAS,UAAU;AACrB,qBAAa,OAAO,WAAW,8BAA8B;AAC7D,uBAAe,MAAM,cAAc,YAAY,QAAQ,CAAC;AACxD,mBAAW,iBAAiB,UAAU,YAAY;AAAA,MACpD;AAAA,IACF;AAAA,IAEA,eAAe,OAA6B;AAC1C,YAAM,OAAiB,CAAC;AACxB,iBAAW,CAAC,KAAK,OAAO,KAAK,OAAO,QAAQ,YAAY,GAAG;AACzD,cAAM,QAAQ,MAAM,GAAkB;AACtC,YAAI,OAAO;AACT,eAAK,KAAK,OAAO,OAAO,KAAK,KAAK,GAAG;AAAA,QACvC;AAAA,MACF;AAEA,UAAI,KAAK,WAAW,GAAG;AACrB,aAAK,eAAe;AACpB;AAAA,MACF;AAEA,YAAM,KAAK,yBAAyB;AACpC,SAAG,cAAc;AAAA,EAAc,KAAK,KAAK,IAAI,CAAC;AAAA;AAAA,IAChD;AAAA,IAEA,iBAAuB;AACrB,kBAAY,OAAO;AACnB,eAAS,eAAe,iBAAiB,GAAG,OAAO;AACnD,mBAAa;AAAA,IACf;AAAA,IAEA,UAAgB;AACd,0BAAoB;AACpB,eAAS,OAAO;AAChB,eAAS,eAAeA,SAAQ,GAAG,OAAO;AAC1C,gBAAU;AACV,WAAK,eAAe;AAAA,IACtB;AAAA,EACF;AACF;;;ACzLO,IAAM,YAAY;AAElB,IAAM,eAAe;AAErB,IAAM,gBAAgB;AAEtB,IAAM,WAAW;AAEjB,IAAM,YAAY;AAElB,IAAM,cAAc;AAEpB,IAAM,aAAa;AAEnB,IAAM,eAAe;AAErB,IAAM,YAAY;AAElB,IAAM,cAAc;AAEpB,IAAM,YAAY;AAElB,IAAM,eAAe;AAErB,IAAM,aAAa;AAEnB,IAAM,cAAc;;;ACxB3B,IAAM,aAAa;AACnB,IAAMC,YAAW;AAoBV,SAAS,sBAAsB,WAA8C;AAClF,MAAI,YAAmC;AACvC,MAAI,YAAmC;AACvC,MAAI,UAA6C,CAAC;AAClD,MAAI,cAAc,oBAAI,IAAa;AAEnC,WAASC,gBAAqB;AAC5B,QAAI,SAAS,eAAeD,SAAQ,EAAG;AAEvC,UAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,UAAM,KAAKA;AACX,UAAM,cAAc;AAAA,SACf,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,mBAKA,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAazB,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,SAKV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAcV,UAAU;AAAA;AAAA;AAAA;AAAA,SAIV,UAAU;AAAA;AAAA;AAAA,SAGV,UAAU;AAAA;AAAA;AAAA;AAAA,SAIV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAOV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SASV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAMf,aAAS,KAAK,YAAY,KAAK;AAAA,EACjC;AAEA,WAAS,aAAa,MAAc,MAAc,OAAe,SAAwC;AACvG,UAAM,MAAM,SAAS,cAAc,QAAQ;AAC3C,QAAI,YAAY;AAChB,QAAI,QAAQ;AACZ,QAAI,aAAa,cAAc,KAAK;AACpC,QAAI,aAAa,eAAe,IAAI;AACpC,QAAI,iBAAiB,SAAS,CAAC,MAAM;AACnC,QAAE,eAAe;AACjB,QAAE,gBAAgB;AAClB,cAAQ;AAAA,IACV,CAAC;AACD,WAAO;AAAA,EACT;AAEA,WAAS,kBAAwB;AAC/B,QAAI,UAAW;AAEf,IAAAC,cAAa;AAEb,gBAAY,SAAS,cAAc,KAAK;AACxC,cAAU,KAAK;AACf,cAAU,aAAa,QAAQ,SAAS;AACxC,cAAU,aAAa,cAAc,sBAAsB;AAE3D,YAAQ,YAAY,aAAa,aAAa,WAAW,kBAAkB,UAAU,eAAe;AACpG,YAAQ,UAAU,aAAa,WAAW,cAAc,WAAW,UAAU,SAAS;AACtF,YAAQ,UAAU,aAAa,WAAW,eAAe,WAAW,UAAU,SAAS;AACvF,YAAQ,SAAS,aAAa,UAAU,aAAa,mBAAmB,UAAU,QAAQ;AAC1F,YAAQ,QAAQ,aAAa,SAAS,UAAU,gBAAgB,UAAU,aAAa;AACvF,YAAQ,SAAS,aAAa,UAAU,YAAY,kBAAkB,UAAU,cAAc;AAC9F,YAAQ,UAAU,aAAa,WAAW,cAAc,mBAAmB,UAAU,SAAS;AAE9F,UAAM,UAAU,SAAS,cAAc,MAAM;AAC7C,YAAQ,YAAY;AAEpB,gBAAY,SAAS,cAAc,KAAK;AACxC,cAAU,YAAY;AACtB,cAAU,YAAY,QAAQ,SAAS;AACvC,cAAU,YAAY,QAAQ,OAAO;AACrC,cAAU,YAAY,QAAQ,OAAO;AACrC,cAAU,YAAY,QAAQ,MAAM;AACpC,cAAU,YAAY,OAAO;AAC7B,cAAU,YAAY,SAAS;AAC/B,cAAU,YAAY,QAAQ,KAAK;AACnC,cAAU,YAAY,QAAQ,MAAM;AACpC,cAAU,YAAY,QAAQ,OAAO;AAErC,aAAS,KAAK,YAAY,SAAS;AAGnC,gBAAY,MAAM;AAClB,gBAAY,IAAI,SAAS;AACzB,gBAAY,IAAI,SAAS;AACzB,gBAAY,IAAI,OAAO;AACvB,eAAW,OAAO,OAAO,OAAO,OAAO,GAAG;AACxC,kBAAY,IAAI,GAAG;AAAA,IACrB;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAa;AACX,sBAAgB;AAChB,gBAAW,UAAU,OAAO,mBAAmB;AAAA,IACjD;AAAA,IAEA,OAAa;AACX,UAAI,WAAW;AACb,kBAAU,UAAU,IAAI,mBAAmB;AAAA,MAC7C;AAAA,IACF;AAAA,IAEA,OAAO,OAAwB;AAC7B,UAAI,CAAC,UAAW;AAGhB,UAAI,MAAM,QAAQ;AAChB,gBAAQ,UAAU,UAAU,IAAI,eAAe;AAAA,MACjD,OAAO;AACL,gBAAQ,UAAU,UAAU,OAAO,eAAe;AAAA,MACpD;AAGA,YAAM,OAAO,MAAM,QAAQ;AAC3B,YAAM,YAAY,SAAS,SAAS,WAAW,SAAS,UAAU,YAAY;AAC9E,YAAM,aAAa,SAAS,SAAS,yBAAyB,SAAS,UAAU,2BAA2B;AAC5G,cAAQ,MAAM,YAAY;AAC1B,cAAQ,MAAM,QAAQ;AACtB,cAAQ,MAAM,aAAa,cAAc,UAAU;AAGnD,UAAI,MAAM,QAAQ;AAChB,gBAAQ,OAAO,UAAU,IAAI,eAAe;AAAA,MAC9C,OAAO;AACL,gBAAQ,OAAO,UAAU,OAAO,eAAe;AAAA,MACjD;AAGA,UAAI,MAAM,QAAQ,SAAS;AACzB,gBAAQ,OAAO,UAAU,IAAI,eAAe;AAC5C,mBAAW,UAAU,OAAO,wBAAwB;AAAA,MACtD,OAAO;AACL,gBAAQ,OAAO,UAAU,OAAO,eAAe;AAC/C,mBAAW,UAAU,IAAI,wBAAwB;AAAA,MACnD;AAAA,IACF;AAAA,IAEA,iBAAiB,IAAsB;AACrC,UAAI,YAAY,IAAI,EAAE,EAAG,QAAO;AAGhC,UAAI,UAA0B;AAC9B,aAAO,SAAS;AACd,YAAI,YAAY,UAAW,QAAO;AAClC,YAAI,QAAQ,OAAO,WAAY,QAAO;AACtC,kBAAU,QAAQ;AAAA,MACpB;AACA,aAAO;AAAA,IACT;AAAA,IAEA,UAAgB;AACd,iBAAW,OAAO;AAClB,eAAS,eAAeD,SAAQ,GAAG,OAAO;AAC1C,kBAAY;AACZ,kBAAY;AACZ,gBAAU,CAAC;AACX,kBAAY,MAAM;AAAA,IACpB;AAAA,EACF;AACF;;;AC1OA,IAAM,aAAa;AACnB,IAAME,YAAW;AAcjB,SAAS,mBAAmB,WAA2B;AACrD,QAAM,OAAO,KAAK,IAAI,IAAI;AAC1B,QAAM,UAAU,KAAK,MAAM,OAAO,GAAI;AAEtC,MAAI,UAAU,GAAI,QAAO;AACzB,QAAM,UAAU,KAAK,MAAM,UAAU,EAAE;AACvC,MAAI,UAAU,GAAI,QAAO,GAAG,OAAO;AACnC,QAAM,QAAQ,KAAK,MAAM,UAAU,EAAE;AACrC,MAAI,QAAQ,GAAI,QAAO,GAAG,KAAK;AAC/B,QAAM,OAAO,KAAK,MAAM,QAAQ,EAAE;AAClC,SAAO,GAAG,IAAI;AAChB;AAEA,SAAS,UAAU,UAA0B;AAC3C,QAAM,QAAQ,SAAS,MAAM,GAAG;AAChC,SAAO,MAAM,MAAM,SAAS,CAAC;AAC/B;AAEA,SAAS,eAAe,UAAkB,MAAqB,QAA+B;AAC5F,MAAI,MAAM,iBAAiB,UAAU,QAAQ,CAAC;AAC9C,MAAI,QAAQ,KAAM,QAAO,IAAI,IAAI;AACjC,MAAI,QAAQ,QAAQ,UAAU,KAAM,QAAO,IAAI,MAAM;AACrD,SAAO;AACT;AAEO,SAAS,qBAAqB,WAAoD;AACvF,MAAI,UAAiC;AACrC,MAAI,UAAU;AAEd,WAASC,gBAAqB;AAC5B,QAAI,SAAS,eAAeD,SAAQ,EAAG;AAEvC,UAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,UAAM,KAAKA;AACX,UAAM,cAAc;AAAA,SACf,UAAU;AAAA;AAAA,kBAED,sBAAsB;AAAA;AAAA;AAAA,mBAGrB,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAezB,UAAU;AAAA;AAAA;AAAA;AAAA,SAIV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SASV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAMV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAgBV,UAAU;AAAA;AAAA;AAAA,SAGV,UAAU;AAAA;AAAA;AAAA,SAGV,UAAU;AAAA;AAAA;AAAA;AAAA,SAIV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAOV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAQV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,SAKV,UAAU;AAAA;AAAA;AAAA;AAAA,SAIV,UAAU;AAAA;AAAA;AAAA;AAAA;AAKf,aAAS,KAAK,YAAY,KAAK;AAAA,EACjC;AAEA,WAAS,gBAAgC;AACvC,QAAI,QAAS,QAAO;AAEpB,IAAAC,cAAa;AACb,cAAU,SAAS,cAAc,KAAK;AACtC,YAAQ,KAAK;AACb,YAAQ,aAAa,QAAQ,QAAQ;AACrC,YAAQ,aAAa,cAAc,cAAc;AACjD,aAAS,KAAK,YAAY,OAAO;AACjC,WAAO;AAAA,EACT;AAEA,WAAS,OAAO,SAA+B;AAC7C,UAAM,KAAK,cAAc;AAEzB,QAAI,OAAO;AAEX,QAAI,QAAQ,WAAW,GAAG;AACxB,cAAQ;AAAA,IACV,OAAO;AACL,iBAAW,SAAS,SAAS;AAC3B,cAAM,WAAW,WAAW,MAAM,QAAQ,QAAQ;AAClD,cAAM,OAAO,MAAM,QAAQ,gBAAgB,WAAW,MAAM,QAAQ,aAAa,IAAI;AACrF,cAAM,OAAO,mBAAmB,MAAM,SAAS;AAC/C,YAAI,OAAO,OAAO,MAAM,IAAI,KAAK;AACjC,YAAI,MAAM,QAAQ,UAAU;AAC1B,gBAAM,MAAM,eAAe,MAAM,QAAQ,UAAU,MAAM,QAAQ,MAAM,MAAM,QAAQ,MAAM;AAC3F,gBAAM,WAAW,WAAW,UAAU,MAAM,QAAQ,QAAQ,CAAC;AAC7D,gBAAM,MAAM,OAAO,aAAa;AAChC,kBAAQ,GAAG,GAAG,yCAAyC,WAAW,GAAG,CAAC,6BAA6B,QAAQ;AAAA,QAC7G;AAEA,gBAAQ,uDAAuD,WAAW,MAAM,EAAE,CAAC,yBAAyB,QAAQ;AACpH,gBAAQ;AACR,gBAAQ,oCAAoC,QAAQ;AACpD,YAAI,KAAM,SAAQ,gCAAgC,IAAI;AACtD,gBAAQ;AACR,gBAAQ,iCAAiC,IAAI;AAC7C,gBAAQ;AAAA,MACV;AAAA,IACF;AAEA,OAAG,YAAY;AAGf,UAAM,QAAQ,GAAG,iBAAiB,kBAAkB;AACpD,UAAM,QAAQ,CAAC,SAAS;AACtB,WAAK,iBAAiB,SAAS,CAAC,MAAM;AACpC,UAAE,gBAAgB;AAClB,cAAM,KAAM,KAAqB,QAAQ;AACzC,cAAM,QAAQ,QAAQ,KAAK,CAAC,QAAQ,IAAI,OAAO,EAAE;AACjD,YAAI,OAAO;AACT,oBAAU,aAAa,KAAK;AAAA,QAC9B;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,KAAK,SAA+B;AAClC,aAAO,OAAO;AACd,gBAAU;AAEV,WAAK,cAAc,EAAE;AACrB,oBAAc,EAAE,UAAU,IAAI,oBAAoB;AAAA,IACpD;AAAA,IAEA,OAAa;AACX,gBAAU;AACV,eAAS,UAAU,OAAO,oBAAoB;AAAA,IAChD;AAAA,IAEA,YAAqB;AACnB,aAAO;AAAA,IACT;AAAA,IAEA,iBAAiB,IAAsB;AACrC,UAAI,CAAC,QAAS,QAAO;AACrB,UAAI,UAA0B;AAC9B,aAAO,SAAS;AACd,YAAI,YAAY,WAAW,QAAQ,OAAO,WAAY,QAAO;AAC7D,kBAAU,QAAQ;AAAA,MACpB;AACA,aAAO;AAAA,IACT;AAAA,IAEA,UAAgB;AACd,eAAS,OAAO;AAChB,eAAS,eAAeD,SAAQ,GAAG,OAAO;AAC1C,gBAAU;AACV,gBAAU;AAAA,IACZ;AAAA,EACF;AACF;;;AChPA,IAAM,UAAU;AAChB,IAAME,YAAW;AA+BV,SAAS,kBAAkB,WAA8C;AAC9E,MAAI,OAA8B;AAClC,MAAI,UAAU;AAEd,QAAM,QAAqB;AAAA,IACzB,EAAE,MAAM,WAAW,OAAO,gBAAgB,QAAQ,UAAU,cAAc;AAAA,IAC1E,EAAE,MAAM,aAAa,OAAO,eAAe,QAAQ,UAAU,aAAa;AAAA,IAC1E,EAAE,MAAM,WAAW,OAAO,aAAa,QAAQ,UAAU,WAAW;AAAA,IACpE,EAAE,MAAM,cAAc,OAAO,WAAW,QAAQ,UAAU,UAAU;AAAA,IACpE,EAAE,WAAW,KAAK;AAAA,IAClB,EAAE,MAAM,YAAY,OAAO,iBAAiB,QAAQ,UAAU,eAAe;AAAA,EAC/E;AAEA,WAASC,gBAAqB;AAC5B,QAAI,SAAS,eAAeD,SAAQ,EAAG;AAEvC,UAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,UAAM,KAAKA;AACX,UAAM,cAAc;AAAA,SACf,OAAO;AAAA;AAAA,kBAEE,sBAAsB;AAAA;AAAA;AAAA,mBAGrB,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAazB,OAAO;AAAA;AAAA;AAAA;AAAA,SAIP,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAeP,OAAO;AAAA;AAAA;AAAA,SAGP,OAAO;AAAA;AAAA;AAAA;AAAA,SAIP,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAMZ,aAAS,KAAK,YAAY,KAAK;AAAA,EACjC;AAEA,WAAS,aAA6B;AACpC,QAAI,KAAM,QAAO;AAEjB,IAAAC,cAAa;AACb,WAAO,SAAS,cAAc,KAAK;AACnC,SAAK,KAAK;AACV,SAAK,aAAa,QAAQ,MAAM;AAChC,SAAK,aAAa,cAAc,SAAS;AAEzC,eAAW,SAAS,OAAO;AACzB,UAAI,MAAM,WAAW;AACnB,cAAM,MAAM,SAAS,cAAc,KAAK;AACxC,YAAI,YAAY;AAChB,aAAK,YAAY,GAAG;AACpB;AAAA,MACF;AAEA,YAAM,MAAM,SAAS,cAAc,QAAQ;AAC3C,UAAI,YAAY;AAChB,UAAI,aAAa,QAAQ,UAAU;AACnC,UAAI,YAAY,GAAG,MAAM,IAAI,SAAS,WAAW,MAAM,KAAK,CAAC;AAC7D,UAAI,iBAAiB,SAAS,CAAC,MAAM;AACnC,UAAE,eAAe;AACjB,UAAE,gBAAgB;AAClB,kBAAU;AACV,cAAM,UAAU,OAAO,iBAAiB;AACxC,cAAM,OAAO;AAAA,MACf,CAAC;AACD,WAAK,YAAY,GAAG;AAAA,IACtB;AAEA,aAAS,KAAK,YAAY,IAAI;AAC9B,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,OAAa;AACX,YAAM,KAAK,WAAW;AACtB,gBAAU;AACV,WAAK,GAAG;AACR,SAAG,UAAU,IAAI,iBAAiB;AAAA,IACpC;AAAA,IAEA,OAAa;AACX,gBAAU;AACV,YAAM,UAAU,OAAO,iBAAiB;AAAA,IAC1C;AAAA,IAEA,YAAqB;AACnB,aAAO;AAAA,IACT;AAAA,IAEA,cAAc,IAAsB;AAClC,UAAI,CAAC,KAAM,QAAO;AAClB,UAAI,UAA0B;AAC9B,aAAO,SAAS;AACd,YAAI,YAAY,QAAQ,QAAQ,OAAO,QAAS,QAAO;AACvD,kBAAU,QAAQ;AAAA,MACpB;AACA,aAAO;AAAA,IACT;AAAA,IAEA,UAAgB;AACd,YAAM,OAAO;AACb,eAAS,eAAeD,SAAQ,GAAG,OAAO;AAC1C,aAAO;AACP,gBAAU;AAAA,IACZ;AAAA,EACF;AACF;;;AC/KA,IAAME,cAAa;AACnB,IAAMC,YAAW;AAeV,SAAS,qBAAqB,WAAoD;AACvF,MAAI,UAAiC;AACrC,MAAI,WAAuC;AAC3C,MAAI,UAAU;AACd,MAAI,iBAAsD;AAE1D,WAASC,gBAAqB;AAC5B,QAAI,SAAS,eAAeD,SAAQ,EAAG;AAEvC,UAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,UAAM,KAAKA;AACX,UAAM,cAAc;AAAA,SACfD,WAAU;AAAA;AAAA,kBAED,sBAAsB;AAAA;AAAA;AAAA,mBAGrB,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAazBA,WAAU;AAAA;AAAA;AAAA;AAAA,SAIVA,WAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAaVA,WAAU;AAAA;AAAA;AAAA,SAGVA,WAAU;AAAA;AAAA;AAAA,SAGVA,WAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAMVA,WAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SASVA,WAAU;AAAA;AAAA;AAAA;AAAA,SAIVA,WAAU;AAAA;AAAA;AAAA;AAAA,SAIVA,WAAU;AAAA;AAAA;AAAA;AAAA,SAIVA,WAAU;AAAA;AAAA;AAAA;AAIf,aAAS,KAAK,YAAY,KAAK;AAAA,EACjC;AAEA,WAAS,gBAAgC;AACvC,QAAI,QAAS,QAAO;AAEpB,IAAAE,cAAa;AAEb,cAAU,SAAS,cAAc,KAAK;AACtC,YAAQ,KAAKF;AACb,YAAQ,aAAa,QAAQ,QAAQ;AACrC,YAAQ,aAAa,cAAc,aAAa;AAEhD,eAAW,SAAS,cAAc,UAAU;AAC5C,aAAS,cAAc;AACvB,aAAS,OAAO;AAEhB,UAAM,SAAS,SAAS,cAAc,KAAK;AAC3C,WAAO,YAAY;AAEnB,UAAM,YAAY,SAAS,cAAc,QAAQ;AACjD,cAAU,YAAY;AACtB,cAAU,cAAc;AACxB,cAAU,iBAAiB,SAAS,CAAC,MAAM;AACzC,QAAE,eAAe;AACjB,QAAE,gBAAgB;AAClB,aAAO;AACP,gBAAU,SAAS;AAAA,IACrB,CAAC;AAED,UAAM,YAAY,SAAS,cAAc,QAAQ;AACjD,cAAU,YAAY;AACtB,cAAU,cAAc;AACxB,cAAU,iBAAiB,SAAS,CAAC,MAAM;AACzC,QAAE,eAAe;AACjB,QAAE,gBAAgB;AAClB,YAAM,UAAU,SAAU,MAAM,KAAK;AACrC,UAAI,SAAS;AACX,eAAO;AACP,kBAAU,SAAS,OAAO;AAAA,MAC5B,OAAO;AACL,iBAAU,MAAM,cAAc;AAC9B,iBAAU,aAAa,eAAe,2BAA2B;AACjE,iBAAU,MAAM;AAChB,mBAAW,MAAM;AACf,cAAI,UAAU;AACZ,qBAAS,MAAM,cAAc;AAC7B,qBAAS,aAAa,eAAe,kBAAkB;AAAA,UACzD;AAAA,QACF,GAAG,GAAI;AAAA,MACT;AAAA,IACF,CAAC;AAED,WAAO,YAAY,SAAS;AAC5B,WAAO,YAAY,SAAS;AAC5B,YAAQ,YAAY,QAAQ;AAC5B,YAAQ,YAAY,MAAM;AAE1B,aAAS,KAAK,YAAY,OAAO;AACjC,WAAO;AAAA,EACT;AAEA,WAAS,2BAAiC;AACxC,QAAI,eAAgB;AAEpB,qBAAiB,CAAC,MAAqB;AAErC,UAAI,YAAY,SAAS,kBAAkB,UAAU;AACnD,UAAE,yBAAyB;AAE3B,YAAI,EAAE,QAAQ,UAAU;AACtB,iBAAO;AACP,oBAAU,SAAS;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AAEA,aAAS,iBAAiB,WAAW,gBAAgB,IAAI;AAAA,EAC3D;AAEA,WAAS,2BAAiC;AACxC,QAAI,gBAAgB;AAClB,eAAS,oBAAoB,WAAW,gBAAgB,IAAI;AAC5D,uBAAiB;AAAA,IACnB;AAAA,EACF;AAEA,WAAS,SAAe;AACtB,cAAU;AACV,aAAS,UAAU,OAAO,oBAAoB;AAC9C,6BAAyB;AAAA,EAC3B;AAEA,SAAO;AAAA,IACL,OAAa;AACX,YAAM,KAAK,cAAc;AACzB,eAAU,QAAQ;AAClB,gBAAU;AACV,WAAK,GAAG;AACR,SAAG,UAAU,IAAI,oBAAoB;AACrC,+BAAyB;AAEzB,4BAAsB,MAAM,UAAU,MAAM,CAAC;AAAA,IAC/C;AAAA,IAEA,OAAa;AACX,aAAO;AAAA,IACT;AAAA,IAEA,YAAqB;AACnB,aAAO;AAAA,IACT;AAAA,IAEA,iBAAiB,IAAsB;AACrC,UAAI,CAAC,QAAS,QAAO;AACrB,UAAI,UAA0B;AAC9B,aAAO,SAAS;AACd,YAAI,YAAY,WAAW,QAAQ,OAAOA,YAAY,QAAO;AAC7D,kBAAU,QAAQ;AAAA,MACpB;AACA,aAAO;AAAA,IACT;AAAA,IAEA,UAAgB;AACd,+BAAyB;AACzB,eAAS,OAAO;AAChB,eAAS,eAAeC,SAAQ,GAAG,OAAO;AAC1C,gBAAU;AACV,iBAAW;AACX,gBAAU;AAAA,IACZ;AAAA,EACF;AACF;;;ACpOA,eAAsB,mBACpB,SACA,UACA,gBACkB;AAClB,MAAI,UAAU,gBAAgB,SAAS,QAAQ;AAC/C,MAAI,gBAAgB;AAClB,cAAU,eAAe,kBAAkB,SAAS,OAAO;AAAA,EAC7D;AACA,QAAM,KAAK,MAAM,cAAc,SAAS,uBAAuB,OAAO;AACtE,MAAI,GAAI,iBAAgB,SAAS,iBAAiB,SAAS,SAAS,MAAS;AAC7E,SAAO;AACT;AAEA,eAAsB,gBACpB,SACA,gBACkB;AAClB,QAAM,UAAU,kBAAkB,QAAQ,IAAI;AAC9C,QAAM,KAAK,MAAM,cAAc,SAAS,4BAA4B,OAAO;AAC3E,MAAI,GAAI,iBAAgB,SAAS,iBAAiB,SAAS,SAAS,MAAS;AAC7E,SAAO;AACT;AAEA,eAAsB,kBAAkB,SAAoC;AAC1E,MAAI,CAAC,QAAQ,aAAa;AACxB,cAAU,kCAAkC;AAC5C,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,OAAO,iBAAiB,OAAO;AAChD,QAAM,MAAM,QAAQ,QAAQ,YAAY;AACxC,QAAM,QAAkB,CAAC,2BAA2B,GAAG,QAAQ,GAAG,GAAG,IAAI;AAEzE,QAAM,QAAQ;AAAA,IACZ;AAAA,IAAW;AAAA,IAAY;AAAA,IAAO;AAAA,IAAS;AAAA,IAAU;AAAA,IACjD;AAAA,IAAS;AAAA,IAAU;AAAA,IAAa;AAAA,IAAc;AAAA,IAAa;AAAA,IAC3D;AAAA,IAAU;AAAA,IACV;AAAA,IAAU;AAAA,IACV;AAAA,IAAc;AAAA,IACd;AAAA,IAAS;AAAA,IAAQ;AAAA,IAAa;AAAA,IAAe;AAAA,IAAe;AAAA,IAC5D;AAAA,IAAc;AAAA,IAAmB;AAAA,IACjC;AAAA,IAAW;AAAA,IAAY;AAAA,IACvB;AAAA,IAAkB;AAAA,IAAmB;AAAA,IAAe;AAAA,IACpD;AAAA,IAAyB;AAAA,IACzB;AAAA,IAAc;AAAA,IAAU;AAAA,IAAc;AAAA,EACxC;AAEA,aAAW,QAAQ,OAAO;AACxB,UAAM,QAAQ,SAAS,iBAAiB,IAAI;AAC5C,QAAI,SAAS,UAAU,UAAU,UAAU,YAAY,UAAU,UAAU,UAAU,SAAS,UAAU,WAAW;AACjH,YAAM,KAAK,KAAK,IAAI,KAAK,KAAK,GAAG;AAAA,IACnC;AAAA,EACF;AAEA,QAAM,KAAK,GAAG;AACd,QAAM,MAAM,MAAM,KAAK,IAAI;AAE3B,SAAO,cAAc,KAAK,4BAA4B;AACxD;AAEA,eAAsB,gBACpB,SACA,SACA,UACA,gBACkB;AAClB,MAAI,UAAU,gBAAgB,SAAS,QAAQ;AAC/C,MAAI,gBAAgB;AAClB,cAAU,eAAe,kBAAkB,SAAS,OAAO;AAAA,EAC7D;AACA,QAAM,OAAO,GAAG,OAAO;AAAA;AAAA,cAAmB,OAAO;AACjD,QAAM,KAAK,MAAM,cAAc,MAAM,uBAAuB,OAAO;AACnE,MAAI,GAAI,iBAAgB,SAAS,iBAAiB,MAAM,SAAS,OAAO;AACxE,SAAO;AACT;AAEA,eAAe,cAAc,MAAc,SAAiB,SAA4C;AACtG,MAAI;AACF,UAAM,UAAU,UAAU,UAAU,IAAI;AACxC,cAAU,SAAS,UAAU;AAAA,MAC3B,eAAe,QAAQ;AAAA,MACvB,UAAU,QAAQ;AAAA,MAClB,MAAM,QAAQ;AAAA,MACd,QAAQ,QAAQ;AAAA,MAChB,YAAY,QAAQ;AAAA,IACtB,IAAI,MAAS;AACb,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;AC/FA,IAAM,YAAY;AAClB,IAAM,kBAAkB;AACxB,IAAM,iBAAiB;AACvB,IAAM,gBAAgB;AACtB,IAAM,aAAa;AAMnB,IAAM,wBAAwB;AAAA,EAC5B;AAAA,EAAc;AAAA,EAAc;AAAA,EAAa;AAAA,EACzC;AAAA,EAAgB;AAAA,EAAgB;AAAA,EAAe;AACjD;AAEA,IAAM,wBAAwB,CAAC,SAAS,QAAQ,WAAW,UAAU;AAW9D,SAAS,sBAAqC;AACnD,MAAI,UAAiC;AACrC,MAAI,UAAU;AACd,MAAI,eAAwC;AAC5C,MAAI,cAAuC;AAC3C,MAAI,iBAA4B,CAAC;AAEjC,WAASE,gBAAqB;AAC5B,QAAI,SAAS,eAAe,eAAe,EAAG;AAE9C,UAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,UAAM,KAAK;AACX,UAAM,cAAc;AAAA,SACf,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAMC,cAAc;AAAA;AAAA;AAAA;AAAA;AAK7B,aAAS,KAAK,YAAY,KAAK;AAAA,EACjC;AAEA,WAAS,gBAAgC;AACvC,QAAI,QAAS,QAAO;AAEpB,IAAAA,cAAa;AACb,cAAU,SAAS,cAAc,KAAK;AACtC,YAAQ,KAAK;AACb,YAAQ,MAAM,UAAU;AACxB,aAAS,KAAK,YAAY,OAAO;AACjC,WAAO;AAAA,EACT;AAIA,QAAM,YAAY,CAAC,MAAmB;AACpC,MAAE,yBAAyB;AAAA,EAC7B;AAEA,QAAM,qBAAqB,CAAC,MAAmB;AAC7C,MAAE,eAAe;AACjB,MAAE,yBAAyB;AAAA,EAC7B;AAEA,WAAS,cAAoB;AAC3B,eAAW,QAAQ,uBAAuB;AACxC,eAAS,iBAAiB,MAAM,WAAW,IAAI;AAAA,IACjD;AACA,eAAW,QAAQ,uBAAuB;AACxC,eAAS,iBAAiB,MAAM,oBAAoB,IAAI;AAAA,IAC1D;AAAA,EACF;AAEA,WAAS,gBAAsB;AAC7B,eAAW,QAAQ,uBAAuB;AACxC,eAAS,oBAAoB,MAAM,WAAW,IAAI;AAAA,IACpD;AACA,eAAW,QAAQ,uBAAuB;AACxC,eAAS,oBAAoB,MAAM,oBAAoB,IAAI;AAAA,IAC7D;AAAA,EACF;AAKA,WAAS,eAAe,SAAwB;AAC9C,QAAI,UAA0B;AAC9B,WAAO,WAAW,YAAY,SAAS,iBAAiB;AACtD,cAAQ,aAAa,YAAY,EAAE;AACnC,qBAAe,KAAK,OAAO;AAC3B,gBAAU,QAAQ;AAAA,IACpB;AAAA,EACF;AAEA,WAAS,kBAAwB;AAC/B,eAAW,MAAM,gBAAgB;AAC/B,SAAG,gBAAgB,UAAU;AAAA,IAC/B;AACA,qBAAiB,CAAC;AAAA,EACpB;AAQA,WAAS,mBAAyB;AAChC,QAAI,aAAc;AAElB,UAAM,SAAmB,CAAC;AAE1B,eAAW,SAAS,MAAM,KAAK,SAAS,WAAW,GAAG;AACpD,UAAI;AACJ,UAAI;AACF,gBAAQ,MAAM;AAAA,MAChB,QAAQ;AACN;AAAA,MACF;AACA,wBAAkB,OAAO,MAAM;AAAA,IACjC;AAEA,QAAI,OAAO,WAAW,EAAG;AAEzB,mBAAe,SAAS,cAAc,OAAO;AAC7C,iBAAa,KAAK;AAClB,iBAAa,cAAc,OAAO,KAAK,IAAI;AAC3C,aAAS,KAAK,YAAY,YAAY;AAAA,EACxC;AAEA,WAAS,kBAAkB,OAAoB,KAAqB;AAClE,eAAW,QAAQ,MAAM,KAAK,KAAK,GAAG;AACpC,UAAI,gBAAgB,cAAc;AAChC,YAAI,KAAK,aAAa,SAAS,QAAQ,GAAG;AACxC,gBAAM,cAAc,KAAK,aAAa,QAAQ,WAAW,IAAI,UAAU,GAAG;AAC1E,cAAI,KAAK,GAAG,WAAW,MAAM,KAAK,MAAM,OAAO,IAAI;AAAA,QACrD;AAAA,MACF,WAAW,gBAAgB,cAAc;AACvC,cAAM,QAAkB,CAAC;AACzB,0BAAkB,KAAK,UAAU,KAAK;AACtC,YAAI,MAAM,SAAS,GAAG;AACpB,cAAI,KAAK,UAAU,KAAK,aAAa,MAAM,MAAM,KAAK,IAAI,CAAC,IAAI;AAAA,QACjE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,WAAS,mBAAyB;AAChC,kBAAc,OAAO;AACrB,mBAAe;AAAA,EACjB;AAIA,WAAS,mBAAyB;AAChC,QAAI,YAAa;AAEjB,kBAAc,SAAS,cAAc,OAAO;AAC5C,gBAAY,KAAK;AACjB,gBAAY,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAM1B,aAAS,KAAK,YAAY,WAAW;AAAA,EACvC;AAEA,WAAS,qBAA2B;AAClC,iBAAa,OAAO;AACpB,kBAAc;AAAA,EAChB;AAEA,SAAO;AAAA,IACL,KAAK,gBAAuC;AAE1C,kBAAY;AAGZ,UAAI,gBAAgB;AAClB,uBAAe,cAAc;AAC7B,yBAAiB;AAAA,MACnB;AAGA,uBAAiB;AAGjB,YAAM,KAAK,cAAc;AACzB,SAAG,MAAM,UAAU;AACnB,gBAAU;AAAA,IACZ;AAAA,IAEA,OAAa;AACX,UAAI,QAAS,SAAQ,MAAM,UAAU;AACrC,gBAAU;AACV,sBAAgB;AAChB,uBAAiB;AACjB,yBAAmB;AACnB,oBAAc;AAAA,IAChB;AAAA,IAEA,YAAqB;AACnB,aAAO;AAAA,IACT;AAAA,IAEA,gBAAgB,IAAsB;AACpC,aAAO,OAAO,WAAW,GAAG,OAAO;AAAA,IACrC;AAAA,IAEA,aAAoC;AAClC,aAAO;AAAA,IACT;AAAA,IAEA,UAAgB;AACd,sBAAgB;AAChB,uBAAiB;AACjB,yBAAmB;AACnB,oBAAc;AACd,eAAS,OAAO;AAChB,eAAS,eAAe,eAAe,GAAG,OAAO;AACjD,gBAAU;AACV,gBAAU;AAAA,IACZ;AAAA,EACF;AACF;;;AC5OA,IAAMC,YAAW;AAEjB,SAAS,eAAqB;AAC5B,MAAI,SAAS,eAAeA,SAAQ,EAAG;AAEvC,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM,KAAKA;AACX,QAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAcL,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAUf,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqB5B,WAAS,KAAK,YAAY,KAAK;AACjC;AAEA,IAAM,YAAY;AAEX,SAAS,mBAAmB,SAAwB;AACzD,eAAa;AAEb,QAAM,OAAO,QAAQ,sBAAsB;AAG3C,QAAM,QAAQ,SAAS,cAAc,KAAK;AAC1C,QAAM,YAAY;AAClB,QAAM,MAAM,MAAM,GAAG,KAAK,GAAG;AAC7B,QAAM,MAAM,OAAO,GAAG,KAAK,IAAI;AAC/B,QAAM,MAAM,QAAQ,GAAG,KAAK,KAAK;AACjC,QAAM,MAAM,SAAS,GAAG,KAAK,MAAM;AACnC,WAAS,KAAK,YAAY,KAAK;AAG/B,QAAM,OAAO,SAAS,cAAc,KAAK;AACzC,OAAK,YAAY;AACjB,OAAK,YAAY,GAAG,SAAS;AAC7B,WAAS,KAAK,YAAY,IAAI;AAG9B,QAAM,YAAY;AAClB,MAAI,WAAW,KAAK,OAAO,KAAK,QAAQ,IAAI,YAAY;AACxD,MAAI,UAAU,KAAK,MAAM;AACzB,MAAI,UAAU,GAAG;AACf,cAAU,KAAK,SAAS;AAAA,EAC1B;AAEA,QAAM,KAAK,SAAS,gBAAgB;AACpC,MAAI,WAAW,YAAY,KAAK,EAAG,YAAW,KAAK,YAAY;AAC/D,MAAI,WAAW,EAAG,YAAW;AAE7B,OAAK,MAAM,MAAM,GAAG,OAAO;AAC3B,OAAK,MAAM,OAAO,GAAG,QAAQ;AAG7B,QAAM,UAAU,MAAM;AACpB,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACA,OAAK,iBAAiB,gBAAgB,OAAO;AAG7C,aAAW,SAAS,IAAI;AAC1B;AAEO,SAAS,wBAA8B;AAC5C,WAAS,eAAeA,SAAQ,GAAG,OAAO;AAC5C;;;AC7EA,IAAM,cAAc;AAEpB,SAAS,iBAAiB,KAAqC;AAC7D,SAAO;AAAA,IACL,MAAM,IAAI;AAAA,IACV,eAAe,IAAI;AAAA,IACnB,UAAU,IAAI;AAAA,IACd,MAAM,IAAI;AAAA,IACV,QAAQ,IAAI;AAAA,IACZ,gBAAgB,IAAI;AAAA,IACpB,UAAU,IAAI;AAAA,IACd,YAAY,IAAI;AAAA,EAClB;AACF;AAEA,SAAS,oBAAwC;AAC/C,SAAO;AAAA,IACL,eAAe,MAAM,IAAI,WAAW;AAAA,IACpC,gBAAgB;AAAA,IAChB,iBAAiB;AAAA,IACjB,iBAAiB;AAAA,IACjB,SAAS;AAAA,IACT,gBAAgB;AAAA,IAChB,SAAS;AAAA,IACT,aAAa;AAAA,IACb,WAAW;AAAA,EACb;AACF;AAEO,SAAS,KAAK,SAAuD;AAC1E,SAAO,mBAAmB,OAAO;AACnC;AAGA,SAAS,YAAqB;AAC5B,MAAI;AAEF,UAAM,KAAM,WAAmB;AAC/B,WAAO,OAAO,OAAO,eAAe,CAAC,CAAC;AAAA,EACxC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGA,SAAS,gBAAgC;AACvC,QAAM,OAAO,MAAM;AAAA,EAAC;AACpB,SAAO;AAAA,IACL,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,UAAU,MAAM;AAAA,IAChB,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,kBAAkB;AAAA,IAClB,sBAAsB;AAAA,IACtB,mBAAmB;AAAA,IACnB,aAAa;AAAA,IACb,aAAa;AAAA,IACb,cAAc;AAAA,IACd,YAAY,MAAM,CAAC;AAAA,IACnB,cAAc;AAAA,IACd,SAAS;AAAA,EACX;AACF;AAEO,SAAS,mBAAmB,SAAuD;AACxF,QAAM,WAAW,kBAAkB;AACnC,QAAM,SAA6B,EAAE,GAAG,UAAU,GAAG,QAAQ;AAE7D,MAAI,OAAO,WAAW,CAAC,UAAU,GAAG;AAClC,WAAO,cAAc;AAAA,EACvB;AAEA,QAAM,QAAQ,YAAY,MAAM;AAChC,QAAM,UAAU,sBAAsB;AACtC,QAAM,YAAY,gBAAgB;AAClC,QAAM,gBAAgB,oBAAoB;AAC1C,QAAM,iBAAiB,qBAAqB;AAC5C,QAAM,eAAe,mBAAmB;AAExC,MAAI,oBAA8C;AAClD,MAAI,iBAAwC;AAG5C,MAAI,sBAA+C;AACnD,MAAI,sBAA6C;AACjD,MAAI,YAAY;AAEhB,WAAS,SAAiB;AACxB,WAAO,MAAM,EAAE,SAAS,IAAI,KAAK,IAAI,CAAC;AAAA,EACxC;AAGA,eAAa,MAAM,MAAM,MAAM,QAAQ,SAAS;AAGhD,oBAAkB;AAGlB,WAAS,oBAAoB,IAAsB;AACjD,WAAO,QAAQ,iBAAiB,EAAE,KAC7B,eAAe,iBAAiB,EAAE,KAClC,YAAY,cAAc,EAAE,KAC5B,eAAe,iBAAiB,EAAE,KAClC,cAAc,gBAAgB,EAAE;AAAA,EACvC;AAGA,WAAS,gBAAgB,SAAyB,SAAuB;AACvE,UAAM,QAAsB;AAAA,MAC1B,IAAI,OAAO;AAAA,MACX,SAAS,iBAAiB,OAAO;AAAA,MACjC;AAAA,MACA,WAAW,KAAK,IAAI;AAAA,IACtB;AAEA,0BAAsB,IAAI,QAAQ,QAAQ,OAAO;AACjD,0BAAsB;AAEtB,UAAM,UAAU,CAAC,OAAO,GAAG,MAAM,MAAM,QAAQ,OAAO,EAAE,MAAM,GAAG,WAAW;AAC5E,UAAM,MAAM,UAAU,EAAE,GAAG,MAAM,MAAM,SAAS,QAAQ;AAAA,EAC1D;AAGA,WAAS,yBAAyC;AAChD,UAAM,KAAK,qBAAqB,MAAM,KAAK;AAC3C,QAAI,MAAM,CAAC,GAAG,aAAa;AACzB,4BAAsB;AACtB,4BAAsB;AACtB,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAGA,WAAS,mBAAyB;AAChC,mBAAe,KAAK;AACpB,gBAAY,KAAK;AACjB,mBAAe,KAAK;AAAA,EACtB;AAGA,iBAAe,qBAAqB,SAAwB,SAAiC;AAC3F,UAAM,UAAU,oBAAoB,SAAS,mBAAmB,cAAc;AAC9E,UAAM,WAAW,MAAM,MAAM,QAAQ;AAErC,0BAAsB,IAAI,QAAQ,OAAO;AACzC,0BAAsB;AACtB,UAAM,MAAM,UAAU,EAAE,GAAG,MAAM,MAAM,SAAS,eAAe,KAAK;AAEpE,YAAQ,QAAQ,MAAM;AAAA,MACpB,KAAK,gBAAgB;AACnB,cAAM,KAAK,MAAM,mBAAmB,SAAS,UAAU,cAAc;AACrE,YAAI,IAAI;AACN,6BAAmB,OAAO;AAC1B,0BAAgB,SAAS,EAAE;AAAA,QAC7B;AACA;AAAA,MACF;AAAA,MACA,KAAK;AACH,cAAM,kBAAkB,OAAO;AAC/B;AAAA,MACF,KAAK;AACH,cAAM,gBAAgB,SAAS,cAAc;AAC7C;AAAA,MACF,KAAK;AACH,uBAAe,KAAK;AACpB;AAAA,IACJ;AAAA,EACF;AAGA,QAAM,SAAS,oBAAoB;AAAA,IACjC;AAAA,IACA;AAAA,IACA,sBAAsB,MAAM;AAAA,IAC5B,mBAAmB,MAAM;AAAA,IACzB,kBAAkB;AAAA,IAClB,kBAAkB,MAAM,cAAc,WAAW;AAAA,IACjD,QAAQ,SAAS;AACf,YAAM,MAAM,iBAAiB;AAC7B,UAAI,SAAS;AACX,uBAAe,SAAS,kBAAkB,OAAO;AAAA,MACnD;AAAA,IACF;AAAA,IACA,MAAM,SAAS,SAAS;AACtB,YAAM,UAAU,MAAM,MAAM,QAAQ;AAEpC,UAAI,SAAS;AACX,cAAM,qBAAqB,SAAS,OAAO;AAE3C,YAAI,QAAQ,SAAS,WAAW;AAC9B,uBAAa;AAAA,QACf;AACA;AAAA,MACF;AAGA,YAAM,SAAS,MAAM,YAAY,SAAS;AAAA,QACxC,sBAAsB,MAAM;AAAA,QAC5B,mBAAmB,MAAM;AAAA,QACzB,oBAAoB,MAAM,MAAM,MAAM,QAAQ;AAAA,QAC9C;AAAA,MACF,CAAC;AAED,UAAI,QAAQ;AACV,2BAAmB,OAAO;AAC1B,wBAAgB,OAAO,SAAS,OAAO,OAAO;AAAA,MAChD;AAAA,IACF;AAAA,EACF,CAAC;AAED,WAAS,aAAmB;AAC1B,QAAI,CAAC,MAAM,MAAM,QAAQ,QAAS;AAClC,QAAI,MAAM,MAAM,OAAQ;AAGxB,QAAI,MAAM,MAAM,QAAQ,YAAY,SAAS,MAAM,MAAM,QAAQ,aAAa;AAC5E,YAAM,MAAM,UAAU,EAAE,GAAG,MAAM,MAAM,SAAS,SAAS,KAAK;AAC9D,cAAQ,KAAK;AACb,cAAQ,OAAO,MAAM,KAAK;AAAA,IAC5B;AAEA,UAAM,MAAM,SAAS;AACrB,WAAO,SAAS;AAChB,mBAAe,SAAS,YAAY;AACpC,YAAQ,OAAO,MAAM,KAAK;AAAA,EAC5B;AAEA,WAAS,eAAqB;AAC5B,QAAI,CAAC,MAAM,MAAM,OAAQ;AAEzB,UAAM,MAAM,SAAS;AACrB,UAAM,MAAM,SAAS;AACrB,kBAAc,KAAK;AACnB,UAAM,MAAM,UAAU,EAAE,GAAG,MAAM,MAAM,SAAS,eAAe,KAAK;AACpE,WAAO,WAAW;AAClB,mBAAe,SAAS,cAAc;AACtC,YAAQ,OAAO,MAAM,KAAK;AAAA,EAC5B;AAEA,WAAS,eAAqB;AAC5B,UAAM,MAAM,SAAS,CAAC,MAAM,MAAM;AAClC,QAAI,MAAM,MAAM,QAAQ;AACtB,oBAAc,KAAK,MAAM,MAAM,cAAc;AAAA,IAC/C,OAAO;AACL,oBAAc,KAAK;AAAA,IACrB;AACA,YAAQ,OAAO,MAAM,KAAK;AAAA,EAC5B;AAGA,QAAM,UAAU,sBAAsB;AAAA,IACpC,kBAAkB;AAChB,uBAAiB;AACjB,UAAI,MAAM,MAAM,QAAQ;AACtB,qBAAa;AAAA,MACf,OAAO;AACL,mBAAW;AAAA,MACb;AAAA,IACF;AAAA,IAEA,YAAY;AACV,kBAAY,KAAK;AACjB,qBAAe,KAAK;AACpB,UAAI,eAAe,UAAU,GAAG;AAC9B,uBAAe,KAAK;AAAA,MACtB,OAAO;AACL,uBAAe,KAAK,CAAC,GAAG,MAAM,MAAM,QAAQ,OAAO,CAAC;AAAA,MACtD;AAAA,IACF;AAAA,IAEA,YAAY;AACV,qBAAe,KAAK;AACpB,qBAAe,KAAK;AACpB,UAAI,YAAY,UAAU,GAAG;AAC3B,oBAAY,KAAK;AAAA,MACnB,OAAO;AACL,oBAAY,KAAK;AAAA,MACnB;AAAA,IACF;AAAA,IAEA,WAAW;AACT,uBAAiB;AACjB,UAAI,CAAC,MAAM,MAAM,QAAQ;AACvB,mBAAW;AAAA,MACb;AACA,mBAAa;AAAA,IACf;AAAA,IAEA,gBAAgB;AACd,YAAM,UAAU,MAAM,MAAM,QAAQ;AACpC,YAAM,UAAqB,YAAY,SAAS,UAAU,YAAY,UAAU,WAAW;AAC3F,YAAM,MAAM,UAAU,EAAE,GAAG,MAAM,MAAM,SAAS,WAAW,QAAQ;AACnE,mBAAa,MAAM,OAAO;AAC1B,cAAQ,OAAO,MAAM,KAAK;AAAA,IAC5B;AAAA,IAEA,iBAAiB;AACf,uBAAiB;AACjB,YAAM,aAAa,CAAC,MAAM,MAAM,QAAQ;AACxC,YAAM,MAAM,UAAU,EAAE,GAAG,MAAM,MAAM,SAAS,SAAS,WAAW;AACpE,UAAI,CAAC,YAAY;AACf,qBAAa;AAAA,MACf;AACA,cAAQ,OAAO,MAAM,KAAK;AAAA,IAC5B;AAAA,IAEA,YAAY;AACV,uBAAiB;AACjB,mBAAa;AACb,YAAM,MAAM,UAAU,EAAE,GAAG,MAAM,MAAM,SAAS,SAAS,MAAM;AAC/D,cAAQ,KAAK;AAAA,IACf;AAAA,EACF,CAAC;AAGD,QAAM,iBAAiB,qBAAqB;AAAA,IAC1C,MAAM,aAAa,OAAqB;AACtC,qBAAe,KAAK;AACpB,UAAI;AACF,cAAM,UAAU,UAAU,UAAU,MAAM,OAAO;AACjD,kBAAU,0BAA0B;AAAA,UAClC,eAAe,MAAM,QAAQ;AAAA,UAC7B,UAAU,MAAM,QAAQ;AAAA,UACxB,MAAM,MAAM,QAAQ;AAAA,UACpB,QAAQ,MAAM,QAAQ;AAAA,UACtB,YAAY,MAAM,QAAQ;AAAA,QAC5B,CAAC;AAAA,MACH,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF,CAAC;AAGD,QAAM,cAAc,kBAAkB;AAAA,IACpC,gBAAgB;AACd,UAAI,qBAAqB;AACvB,2BAAmB,qBAAqB,MAAM,MAAM,QAAQ,iBAAiB,cAAc;AAAA,MAC7F,OAAO;AACL,cAAM,MAAM,UAAU,EAAE,GAAG,MAAM,MAAM,SAAS,eAAe,EAAE,MAAM,eAAe,EAAE;AACxF,mBAAW;AAAA,MACb;AAAA,IACF;AAAA,IAEA,eAAe;AACb,YAAM,KAAK,uBAAuB;AAClC,UAAI,IAAI;AACN,0BAAkB,EAAE;AAAA,MACtB,OAAO;AACL,cAAM,MAAM,UAAU,EAAE,GAAG,MAAM,MAAM,SAAS,eAAe,EAAE,MAAM,cAAc,EAAE;AACvF,mBAAW;AAAA,MACb;AAAA,IACF;AAAA,IAEA,aAAa;AACX,UAAI,qBAAqB;AACvB,wBAAgB,qBAAqB,cAAc;AAAA,MACrD,OAAO;AACL,cAAM,MAAM,UAAU,EAAE,GAAG,MAAM,MAAM,SAAS,eAAe,EAAE,MAAM,YAAY,EAAE;AACrF,mBAAW;AAAA,MACb;AAAA,IACF;AAAA,IAEA,YAAY;AACV,UAAI,qBAAqB;AACvB,uBAAe,KAAK;AAAA,MACtB,OAAO;AACL,cAAM,MAAM,UAAU,EAAE,GAAG,MAAM,MAAM,SAAS,eAAe,EAAE,MAAM,UAAU,EAAE;AACnF,mBAAW;AAAA,MACb;AAAA,IACF;AAAA,IAEA,iBAAiB;AACf,4BAAsB;AACtB,4BAAsB;AACtB,YAAM,MAAM,UAAU,EAAE,GAAG,MAAM,MAAM,SAAS,SAAS,CAAC,EAAE;AAAA,IAC9D;AAAA,EACF,CAAC;AAGD,QAAM,iBAAiB,qBAAqB;AAAA,IAC1C,MAAM,SAAS,SAAiB;AAC9B,UAAI,qBAAqB;AACvB,cAAM,gBAAgB,qBAAqB,SAAS,MAAM,MAAM,QAAQ,iBAAiB,cAAc;AAAA,MACzG;AACA,UAAI,MAAM,MAAM,QAAQ;AACtB,qBAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,WAAW;AACT,UAAI,MAAM,MAAM,QAAQ;AACtB,qBAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF,CAAC;AAGD,WAAS,oBAAoB,GAAqB;AAChD,UAAM,SAAS,EAAE;AACjB,QAAI,CAAC,OAAQ;AAEb,QAAI,oBAAoB,MAAM,EAAG;AAGjC,QAAI,eAAe,UAAU,KAAK,YAAY,UAAU,KAAK,eAAe,UAAU,GAAG;AACvF,uBAAiB;AAAA,IACnB;AAAA,EACF;AACA,WAAS,iBAAiB,SAAS,mBAAmB;AAGtD,WAAS,oBAA0B;AACjC,QAAI,MAAM,MAAM,QAAQ,SAAS;AAC/B,eAAS,gBAAgB,MAAM,YAAY,qBAAqB,oBAAoB;AAAA,IACtF,OAAO;AACL,eAAS,gBAAgB,MAAM,eAAe,mBAAmB;AAAA,IACnE;AAAA,EACF;AAGA,WAAS,gBAAgB,GAAwB;AAC/C,QAAI,CAAC,MAAM,MAAM,OAAQ;AACzB,QAAI,EAAE,IAAI,YAAY,MAAM,IAAK;AACjC,UAAM,MAAO,EAAE,QAAoB;AACnC,QAAI,QAAQ,WAAW,QAAQ,WAAY;AAC3C,QAAK,EAAE,QAAwB,kBAAmB;AAElD,MAAE,eAAe;AACjB,iBAAa;AAAA,EACf;AACA,WAAS,iBAAiB,WAAW,iBAAiB,IAAI;AAG1D,QAAM,WAAW,sBAAsB;AAAA,IACrC,kBAAkB,MAAM,MAAM,MAAM,QAAQ;AAAA,IAC5C,mBAAmB,MAAM,MAAM,MAAM,QAAQ;AAAA,IAC7C,oBAAoB,MAAM,MAAM,MAAM,QAAQ;AAAA,IAC9C,mBAAmB,MAAM,MAAM,MAAM,QAAQ;AAAA,IAC7C,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,UAAU,MAAM,MAAM,MAAM;AAAA,EAC9B,CAAC;AAGD,QAAM,MAAsB;AAAA,IAC1B,UAAU;AAAA,IACV,YAAY;AAAA,IAEZ,SAAe;AACb,UAAI,MAAM,MAAM,QAAQ;AACtB,qBAAa;AAAA,MACf,OAAO;AACL,mBAAW;AAAA,MACb;AAAA,IACF;AAAA,IAEA,WAAoB;AAClB,aAAO,MAAM,MAAM;AAAA,IACrB;AAAA,IAEA,WAAW,MAAyC;AAClD,YAAM,MAAM,UAAU,EAAE,GAAG,MAAM,MAAM,SAAS,GAAG,KAAK;AAAA,IAC1D;AAAA,IAEA,eAAe,QAAsB;AACnC,UAAI,OAAO,SAAS;AAClB,cAAM,MAAM,UAAU,EAAE,GAAG,MAAM,MAAM,SAAS,GAAG,OAAO,QAAQ;AAAA,MACpE;AACA,UAAI,OAAO,OAAO;AAChB,qBAAa,eAAe,OAAO,KAAK;AAAA,MAC1C;AACA,qBAAe,SAAS,QAAQ,GAAG;AAAA,IACrC;AAAA,IAEA,iBAAiB,MAAoB;AACnC,qBAAe,WAAW,IAAI;AAAA,IAChC;AAAA,IAEA,qBAAqB,UAAmC;AACtD,0BAAoB;AAAA,IACtB;AAAA,IAEA,kBAAkB,UAAgC;AAChD,uBAAiB;AAAA,IACnB;AAAA,IAEA,cAAoB;AAClB,YAAM,MAAM,UAAU,EAAE,GAAG,MAAM,MAAM,SAAS,SAAS,KAAK;AAC9D,cAAQ,KAAK;AACb,cAAQ,OAAO,MAAM,KAAK;AAC1B,wBAAkB;AAAA,IACpB;AAAA,IAEA,cAAoB;AAClB,uBAAiB;AACjB,YAAM,MAAM,UAAU,EAAE,GAAG,MAAM,MAAM,SAAS,SAAS,MAAM;AAC/D,cAAQ,KAAK;AACb,wBAAkB;AAAA,IACpB;AAAA,IAEA,aAAa,MAAuB;AAClC,YAAM,MAAM,UAAU,EAAE,GAAG,MAAM,MAAM,SAAS,WAAW,KAAK;AAChE,mBAAa,MAAM,IAAI;AACvB,cAAQ,OAAO,MAAM,KAAK;AAAA,IAC5B;AAAA,IAEA,aAA6B;AAC3B,aAAO,CAAC,GAAG,MAAM,MAAM,QAAQ,OAAO;AAAA,IACxC;AAAA,IAEA,eAAqB;AACnB,4BAAsB;AACtB,4BAAsB;AACtB,YAAM,MAAM,UAAU,EAAE,GAAG,MAAM,MAAM,SAAS,SAAS,CAAC,EAAE;AAAA,IAC9D;AAAA,IAEA,UAAgB;AACd,mBAAa;AACb,eAAS,oBAAoB,SAAS,mBAAmB;AACzD,eAAS,oBAAoB,WAAW,iBAAiB,IAAI;AAC7D,eAAS,QAAQ;AACjB,aAAO,QAAQ;AACf,cAAQ,QAAQ;AAChB,gBAAU,QAAQ;AAClB,oBAAc,QAAQ;AACtB,mBAAa;AACb,4BAAsB;AACtB,qBAAe,QAAQ;AACvB,uBAAiB;AACjB,cAAQ,QAAQ;AAChB,qBAAe,QAAQ;AACvB,kBAAY,QAAQ;AACpB,qBAAe,QAAQ;AACvB,mBAAa,QAAQ;AACrB,eAAS,gBAAgB,MAAM,eAAe,mBAAmB;AAAA,IACnE;AAAA,EACF;AAGA,MAAI,MAAM,MAAM,QAAQ,SAAS;AAC/B,aAAS,MAAM;AAAA,EACjB;AAGA,QAAM,MAAM,UAAU,EAAE,GAAG,MAAM,MAAM,SAAS,SAAS,MAAM;AAG/D,QAAM,UAAU,CAAC,OAAO,QAAQ;AAC9B,QAAI,QAAQ,WAAW;AACrB,UAAI,MAAM,QAAQ,SAAS;AACzB,iBAAS,MAAM;AAAA,MACjB,OAAO;AACL,iBAAS,KAAK;AACd,qBAAa;AAAA,MACf;AAAA,IACF;AACA,QAAI,QAAQ,WAAW;AACrB,wBAAkB;AAAA,IACpB;AAAA,EACF,CAAC;AAED,SAAO;AACT;;;AC/kBA,IAAM,kBAAkB;AAEjB,SAAS,aAAa,SAAkC;AAC7D,QAAM,aAAa,iBAAiB,OAAO;AAC3C,QAAM,EAAE,UAAU,MAAM,OAAO,IAAI,cAAc,OAAO;AACxD,QAAM,OAAO,YAAY,OAAO;AAChC,QAAM,WAAW,iBAAiB,OAAO;AAEzC,QAAM,aAAa,qBAAqB,QAAQ,SAAS;AAEzD,QAAM,iBAAwC,WAAW,MAAM,IAAI,CAAC,UAAU;AAC5E,UAAM,MAAM,0BAA0B,MAAM,IAAI;AAChD,WAAO;AAAA,MACL,MAAM,MAAM;AAAA,MACZ,UAAU,IAAI;AAAA,MACd,MAAM,IAAI;AAAA,MACV,QAAQ,IAAI;AAAA,IACd;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,eAAe,WAAW;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,YAAY,SAA0B;AAC7C,QAAM,OAAO,QAAQ;AACrB,MAAI,KAAK,UAAU,gBAAiB,QAAO;AAC3C,SAAO,KAAK,MAAM,GAAG,eAAe,IAAI;AAC1C;AAEA,SAAS,iBAAiB,SAA0B;AAClD,QAAM,QAAkB,CAAC;AACzB,MAAI,UAA0B;AAE9B,SAAO,WAAW,YAAY,SAAS,iBAAiB;AACtD,QAAI,WAAW,QAAQ,QAAQ,YAAY;AAE3C,QAAI,QAAQ,IAAI;AACd,kBAAY,IAAI,QAAQ,EAAE;AAC1B,YAAM,QAAQ,QAAQ;AACtB;AAAA,IACF;AAEA,UAAM,YAAY,QAAQ,aAAa,OAAO;AAC9C,QAAI,WAAW;AACb,YAAM,UAAU,UACb,KAAK,EACL,MAAM,KAAK,EACX,OAAO,OAAO,EACd,MAAM,GAAG,CAAC;AACb,UAAI,QAAQ,SAAS,GAAG;AACtB,oBAAY,MAAM,QAAQ,KAAK,GAAG;AAAA,MACpC;AAAA,IACF;AAGA,UAAM,SAAS,QAAQ;AACvB,QAAI,QAAQ;AACV,YAAM,WAAW,MAAM,KAAK,OAAO,QAAQ,EAAE;AAAA,QAC3C,CAAC,MAAM,EAAE,YAAY,QAAS;AAAA,MAChC;AACA,UAAI,SAAS,SAAS,GAAG;AACvB,cAAM,QAAQ,SAAS,QAAQ,OAAO,IAAI;AAC1C,oBAAY,gBAAgB,KAAK;AAAA,MACnC;AAAA,IACF;AAEA,UAAM,QAAQ,QAAQ;AACtB,cAAU,QAAQ;AAAA,EACpB;AAEA,SAAO,MAAM,KAAK,KAAK;AACzB;;;AC9EA,IAAI,WAAkC;AAO/B,SAAS,gBAAgB,SAAuD;AACrF,MAAI,SAAU,QAAO;AAGrB,MAAI,SAAS,YAAY,SAAS,OAAO,cAAc,eAAe,CAAC,WAAW;AAChF,eAAW,cAAc;AACzB,WAAO;AAAA,EACT;AAEA,aAAW,KAAK,OAAO;AACvB,WAAS,qBAAqB,CAAC,OAAO,iBAAiB,EAAE,CAAC;AAC1D,WAAS,kBAAkB,CAAC,OAAO,cAAc,EAAE,CAAC;AAEpD,SAAO;AACT;AAEO,SAAS,oBAA2C;AACzD,SAAO;AACT;AAEO,SAAS,0BAA0B,QAAsB;AAC9D,YAAU,eAAe,MAAM;AACjC;AAEO,SAAS,qBAA2B;AACzC,YAAU,QAAQ;AAClB,aAAW;AACb;AAEA,SAAS,gBAAgC;AACvC,SAAO;AAAA,IACL,WAAW;AAAA,IAAC;AAAA,IACZ,aAAa;AAAA,IAAC;AAAA,IACd,SAAS;AAAA,IAAC;AAAA,IACV,WAAW;AAAE,aAAO;AAAA,IAAO;AAAA,IAC3B,aAAa;AAAA,IAAC;AAAA,IACd,iBAAiB;AAAA,IAAC;AAAA,IAClB,mBAAmB;AAAA,IAAC;AAAA,IACpB,uBAAuB;AAAA,IAAC;AAAA,IACxB,oBAAoB;AAAA,IAAC;AAAA,IACrB,cAAc;AAAA,IAAC;AAAA,IACf,cAAc;AAAA,IAAC;AAAA,IACf,eAAe;AAAA,IAAC;AAAA,IAChB,aAAa;AAAE,aAAO,CAAC;AAAA,IAAG;AAAA,IAC1B,eAAe;AAAA,IAAC;AAAA,IAChB,UAAU;AAAA,IAAC;AAAA,EACb;AACF;;;AC7DA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAIA,IAAM,mBAAmB,IAAI,eAA+B,kBAAkB;AAE9E,SAAS,mBACd,SACsB;AACtB,SAAO,yBAAyB;AAAA,IAC9B;AAAA,MACE,SAAS;AAAA,MACT,YAAY,MAAM,gBAAgB,OAAO;AAAA,IAC3C;AAAA,IACA,8BAA8B,MAAM,gBAAgB,OAAO,CAAC;AAAA,EAC9D,CAAC;AACH;","names":["injectStyles","injectStyles","STYLE_ID","STYLE_ID","injectStyles","STYLE_ID","injectStyles","STYLE_ID","injectStyles","POPOVER_ID","STYLE_ID","injectStyles","injectStyles","STYLE_ID"]}
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (let key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
-
}
|
|
18
|
-
return to;
|
|
19
|
-
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
|
|
30
|
-
// src/builder/builders/application/index.ts
|
|
31
|
-
var application_exports = {};
|
|
32
|
-
__export(application_exports, {
|
|
33
|
-
default: () => application_default
|
|
34
|
-
});
|
|
35
|
-
module.exports = __toCommonJS(application_exports);
|
|
36
|
-
var import_architect = require("@angular-devkit/architect");
|
|
37
|
-
var import_build = require("@angular/build");
|
|
38
|
-
|
|
39
|
-
// src/esbuild-plugin/scan.ts
|
|
40
|
-
var import_typescript = __toESM(require("typescript"), 1);
|
|
41
|
-
var import_path = __toESM(require("path"), 1);
|
|
42
|
-
var import_fs = __toESM(require("fs"), 1);
|
|
43
|
-
function scanComponentSources(rootDir) {
|
|
44
|
-
const sourceMap = {};
|
|
45
|
-
const files = findComponentFiles(rootDir);
|
|
46
|
-
for (const filePath of files) {
|
|
47
|
-
const content = import_fs.default.readFileSync(filePath, "utf8");
|
|
48
|
-
if (!content.includes("@Component")) continue;
|
|
49
|
-
const relativePath = import_path.default.relative(rootDir, filePath).replace(/\\/g, "/");
|
|
50
|
-
const components = extractComponents(content, filePath);
|
|
51
|
-
for (const comp of components) {
|
|
52
|
-
sourceMap[comp.name] = { file: relativePath, line: comp.line };
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return sourceMap;
|
|
56
|
-
}
|
|
57
|
-
function extractComponents(code, filePath) {
|
|
58
|
-
const sourceFile = import_typescript.default.createSourceFile(
|
|
59
|
-
filePath,
|
|
60
|
-
code,
|
|
61
|
-
import_typescript.default.ScriptTarget.Latest,
|
|
62
|
-
true,
|
|
63
|
-
import_typescript.default.ScriptKind.TS
|
|
64
|
-
);
|
|
65
|
-
const results = [];
|
|
66
|
-
function visit(node) {
|
|
67
|
-
if (import_typescript.default.isClassDeclaration(node) && node.name) {
|
|
68
|
-
const decorators = import_typescript.default.getDecorators(node);
|
|
69
|
-
if (!decorators) return;
|
|
70
|
-
const hasComponent = decorators.some((d) => {
|
|
71
|
-
if (!import_typescript.default.isCallExpression(d.expression)) return false;
|
|
72
|
-
if (!import_typescript.default.isIdentifier(d.expression.expression)) return false;
|
|
73
|
-
return d.expression.expression.text === "Component";
|
|
74
|
-
});
|
|
75
|
-
if (hasComponent) {
|
|
76
|
-
const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
77
|
-
results.push({ name: node.name.text, line: line + 1 });
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
import_typescript.default.forEachChild(node, visit);
|
|
81
|
-
}
|
|
82
|
-
visit(sourceFile);
|
|
83
|
-
return results;
|
|
84
|
-
}
|
|
85
|
-
function findComponentFiles(rootDir) {
|
|
86
|
-
const results = [];
|
|
87
|
-
const srcDir = import_path.default.join(rootDir, "src");
|
|
88
|
-
if (!import_fs.default.existsSync(srcDir)) return results;
|
|
89
|
-
walk(srcDir, results);
|
|
90
|
-
return results;
|
|
91
|
-
}
|
|
92
|
-
function walk(dir, results) {
|
|
93
|
-
let entries;
|
|
94
|
-
try {
|
|
95
|
-
entries = import_fs.default.readdirSync(dir, { withFileTypes: true });
|
|
96
|
-
} catch {
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
for (const entry of entries) {
|
|
100
|
-
if (entry.name === "node_modules" || entry.name.startsWith(".")) continue;
|
|
101
|
-
const fullPath = import_path.default.join(dir, entry.name);
|
|
102
|
-
if (entry.isDirectory()) {
|
|
103
|
-
walk(fullPath, results);
|
|
104
|
-
} else if (entry.name.endsWith(".component.ts")) {
|
|
105
|
-
results.push(fullPath);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// src/esbuild-plugin/plugin.ts
|
|
111
|
-
function angularGrabEsbuildPlugin(options) {
|
|
112
|
-
return {
|
|
113
|
-
name: "angular-grab",
|
|
114
|
-
setup(build) {
|
|
115
|
-
if (options?.enabled === false) return;
|
|
116
|
-
const rootDir = options?.rootDir || process.cwd();
|
|
117
|
-
const sourceMap = scanComponentSources(rootDir);
|
|
118
|
-
if (Object.keys(sourceMap).length === 0) return;
|
|
119
|
-
const json = JSON.stringify(sourceMap);
|
|
120
|
-
const banner = build.initialOptions.banner || {};
|
|
121
|
-
const existing = typeof banner === "object" ? banner.js || "" : "";
|
|
122
|
-
build.initialOptions.banner = {
|
|
123
|
-
...typeof banner === "object" ? banner : {},
|
|
124
|
-
js: `globalThis.__ANGULAR_GRAB_SOURCE_MAP__=${json};${existing}`
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// src/esbuild-plugin/transform.ts
|
|
131
|
-
var import_typescript2 = __toESM(require("typescript"), 1);
|
|
132
|
-
|
|
133
|
-
// src/builder/builders/application/index.ts
|
|
134
|
-
var application_default = (0, import_architect.createBuilder)(async function* (options, context) {
|
|
135
|
-
const isProduction = !!options.optimization;
|
|
136
|
-
yield* (0, import_build.buildApplication)(options, context, {
|
|
137
|
-
codePlugins: [angularGrabEsbuildPlugin({
|
|
138
|
-
rootDir: context.workspaceRoot,
|
|
139
|
-
enabled: !isProduction
|
|
140
|
-
})]
|
|
141
|
-
});
|
|
142
|
-
});
|
|
143
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/builder/builders/application/index.ts","../../../../src/esbuild-plugin/scan.ts","../../../../src/esbuild-plugin/plugin.ts","../../../../src/esbuild-plugin/transform.ts"],"sourcesContent":["import { createBuilder } from '@angular-devkit/architect';\nimport { buildApplication } from '@angular/build';\nimport { angularGrabEsbuildPlugin } from '../../../esbuild-plugin';\n\nexport default createBuilder(async function* (options: any, context) {\n const isProduction = !!options.optimization;\n yield* buildApplication(options, context, {\n codePlugins: [angularGrabEsbuildPlugin({\n rootDir: context.workspaceRoot,\n enabled: !isProduction,\n })],\n });\n});\n","import ts from 'typescript';\nimport path from 'path';\nimport fs from 'fs';\n\nexport interface ComponentSourceInfo {\n file: string;\n line: number;\n}\n\nexport type SourceMap = Record<string, ComponentSourceInfo>;\n\n/**\n * Scans the project for `.component.ts` files and extracts component\n * class names with their source locations. Returns a map of\n * `{ ComponentName: { file, line } }`.\n */\nexport function scanComponentSources(rootDir: string): SourceMap {\n const sourceMap: SourceMap = {};\n const files = findComponentFiles(rootDir);\n\n for (const filePath of files) {\n const content = fs.readFileSync(filePath, 'utf8');\n if (!content.includes('@Component')) continue;\n\n const relativePath = path.relative(rootDir, filePath).replace(/\\\\/g, '/');\n const components = extractComponents(content, filePath);\n\n for (const comp of components) {\n sourceMap[comp.name] = { file: relativePath, line: comp.line };\n }\n }\n\n return sourceMap;\n}\n\ninterface ComponentInfo {\n name: string;\n line: number;\n}\n\nfunction extractComponents(code: string, filePath: string): ComponentInfo[] {\n const sourceFile = ts.createSourceFile(\n filePath,\n code,\n ts.ScriptTarget.Latest,\n true,\n ts.ScriptKind.TS,\n );\n\n const results: ComponentInfo[] = [];\n\n function visit(node: ts.Node): void {\n if (ts.isClassDeclaration(node) && node.name) {\n const decorators = ts.getDecorators(node);\n if (!decorators) return;\n\n const hasComponent = decorators.some((d) => {\n if (!ts.isCallExpression(d.expression)) return false;\n if (!ts.isIdentifier(d.expression.expression)) return false;\n return d.expression.expression.text === 'Component';\n });\n\n if (hasComponent) {\n const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n results.push({ name: node.name.text, line: line + 1 });\n }\n }\n\n ts.forEachChild(node, visit);\n }\n\n visit(sourceFile);\n return results;\n}\n\nfunction findComponentFiles(rootDir: string): string[] {\n const results: string[] = [];\n const srcDir = path.join(rootDir, 'src');\n\n if (!fs.existsSync(srcDir)) return results;\n\n walk(srcDir, results);\n return results;\n}\n\nfunction walk(dir: string, results: string[]): void {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (entry.name === 'node_modules' || entry.name.startsWith('.')) continue;\n\n const fullPath = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n walk(fullPath, results);\n } else if (entry.name.endsWith('.component.ts')) {\n results.push(fullPath);\n }\n }\n}\n","import type { Plugin } from 'esbuild';\nimport { scanComponentSources } from './scan';\n\nexport function angularGrabEsbuildPlugin(options?: {\n rootDir?: string;\n /** Set to false to disable the transform (e.g., in production). Default: true */\n enabled?: boolean;\n}): Plugin {\n return {\n name: 'angular-grab',\n setup(build) {\n if (options?.enabled === false) return;\n\n const rootDir = options?.rootDir || process.cwd();\n const sourceMap = scanComponentSources(rootDir);\n\n if (Object.keys(sourceMap).length === 0) return;\n\n // Inject the source map as a global variable via banner\n const json = JSON.stringify(sourceMap);\n const banner = build.initialOptions.banner || {};\n const existing = typeof banner === 'object' ? (banner.js || '') : '';\n build.initialOptions.banner = {\n ...(typeof banner === 'object' ? banner : {}),\n js: `globalThis.__ANGULAR_GRAB_SOURCE_MAP__=${json};${existing}`,\n };\n },\n };\n}\n","import ts from 'typescript';\nimport path from 'path';\n\nexport interface TransformResult {\n code: string;\n}\n\ninterface Edit {\n pos: number;\n end: number;\n text: string;\n}\n\nexport function transformAngularComponent(\n code: string,\n filePath: string,\n rootDir: string,\n): TransformResult | null {\n const sourceFile = ts.createSourceFile(\n filePath,\n code,\n ts.ScriptTarget.Latest,\n true,\n ts.ScriptKind.TS,\n );\n\n const relativePath = path.relative(rootDir, filePath).replace(/\\\\/g, '/').replace(/'/g, \"\\\\'\");\n const edits: Edit[] = [];\n\n visitNode(sourceFile);\n\n if (edits.length === 0) return null;\n\n // Apply edits in reverse order to preserve positions\n edits.sort((a, b) => b.pos - a.pos);\n\n let result = code;\n for (const edit of edits) {\n result = result.slice(0, edit.pos) + edit.text + result.slice(edit.end);\n }\n\n return { code: result };\n\n function visitNode(node: ts.Node): void {\n if (ts.isClassDeclaration(node)) {\n processClassDeclaration(node);\n }\n ts.forEachChild(node, visitNode);\n }\n\n function processClassDeclaration(classNode: ts.ClassDeclaration): void {\n const decorators = ts.getDecorators(classNode);\n if (!decorators) return;\n\n for (const decorator of decorators) {\n if (!ts.isCallExpression(decorator.expression)) continue;\n\n const expr = decorator.expression;\n if (!ts.isIdentifier(expr.expression)) continue;\n if (expr.expression.text !== 'Component') continue;\n\n processComponentDecorator(expr);\n }\n }\n\n function processComponentDecorator(callExpr: ts.CallExpression): void {\n if (callExpr.arguments.length === 0) {\n // Empty decorator call: @Component() — add host arg\n const line = sourceFile.getLineAndCharacterOfPosition(callExpr.getStart()).line;\n const sourceAttr = `'data-ng-source': '${relativePath}:${line}:0'`;\n const insertText = `{ host: { ${sourceAttr} } }`;\n\n const openParen = callExpr.getStart() + callExpr.expression.getText().length;\n // Find the actual position of the opening paren\n const parenPos = code.indexOf('(', openParen);\n const closeParenPos = code.indexOf(')', parenPos);\n\n edits.push({\n pos: parenPos + 1,\n end: closeParenPos,\n text: insertText,\n });\n return;\n }\n\n const arg = callExpr.arguments[0];\n if (!ts.isObjectLiteralExpression(arg)) return;\n\n const line = sourceFile.getLineAndCharacterOfPosition(callExpr.getStart()).line;\n const sourceAttr = `'data-ng-source': '${relativePath}:${line}:0'`;\n\n // Check if host property already exists\n const hostProp = arg.properties.find(\n (p) => ts.isPropertyAssignment(p) && ts.isIdentifier(p.name) && p.name.text === 'host',\n ) as ts.PropertyAssignment | undefined;\n\n if (hostProp) {\n // Host property exists — inject into it\n if (!ts.isObjectLiteralExpression(hostProp.initializer)) return;\n\n const hostObj = hostProp.initializer;\n\n // Check for existing data-ng-source (idempotent)\n const hasExisting = hostObj.properties.some(\n (p) =>\n ts.isPropertyAssignment(p) &&\n ((ts.isStringLiteral(p.name) && p.name.text === 'data-ng-source') ||\n (ts.isIdentifier(p.name) && p.name.text === 'data-ng-source')),\n );\n\n if (hasExisting) return;\n\n // Insert into existing host object\n if (hostObj.properties.length > 0) {\n const lastProp = hostObj.properties[hostObj.properties.length - 1];\n edits.push({\n pos: lastProp.getEnd(),\n end: lastProp.getEnd(),\n text: `, ${sourceAttr}`,\n });\n } else {\n // Empty host object: host: {}\n const openBrace = hostObj.getStart();\n const closeBrace = hostObj.getEnd();\n edits.push({\n pos: openBrace + 1,\n end: closeBrace - 1,\n text: ` ${sourceAttr} `,\n });\n }\n } else {\n // No host property — add one\n if (arg.properties.length > 0) {\n const lastProp = arg.properties[arg.properties.length - 1];\n edits.push({\n pos: lastProp.getEnd(),\n end: lastProp.getEnd(),\n text: `, host: { ${sourceAttr} }`,\n });\n } else {\n // Empty object literal: @Component({})\n const openBrace = arg.getStart();\n const closeBrace = arg.getEnd();\n edits.push({\n pos: openBrace + 1,\n end: closeBrace - 1,\n text: ` host: { ${sourceAttr} } `,\n });\n }\n }\n }\n}\n"],"mappings":"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","names":["fs","path","ts","import_typescript"]}
|