@ui-context-kit/overlay 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-2Q7HLV4J.js → chunk-3TRECS2R.js} +2 -2
- package/dist/chunk-3TRECS2R.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/inject.cjs +1 -1
- package/dist/inject.cjs.map +1 -1
- package/dist/inject.js +1 -1
- package/dist/react.cjs +1 -1
- package/dist/react.cjs.map +1 -1
- package/package.json +15 -9
- package/dist/chunk-2Q7HLV4J.js.map +0 -1
|
@@ -547,7 +547,7 @@ function createSelectionHandler(opts) {
|
|
|
547
547
|
var DEFAULT_SERVER_PORT = 19638;
|
|
548
548
|
var serverUrl = "";
|
|
549
549
|
function initTransport(url) {
|
|
550
|
-
serverUrl = url || `http
|
|
550
|
+
serverUrl = url || `http://127.0.0.1:${DEFAULT_SERVER_PORT}`;
|
|
551
551
|
}
|
|
552
552
|
function sendContext(context) {
|
|
553
553
|
return new Promise((resolve) => {
|
|
@@ -815,4 +815,4 @@ function initUIContext(options = {}) {
|
|
|
815
815
|
export {
|
|
816
816
|
initUIContext
|
|
817
817
|
};
|
|
818
|
-
//# sourceMappingURL=chunk-
|
|
818
|
+
//# sourceMappingURL=chunk-3TRECS2R.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ui/overlay.ts","../src/ui/toast.ts","../src/ui/toolbar.ts","../src/fiber-walker.ts","../src/context-extractor.ts","../src/screenshot.ts","../src/selection.ts","../src/transport.ts","../src/ui/onboarding.ts","../src/index.ts"],"sourcesContent":["let hostEl: HTMLDivElement | null = null;\nlet shadowRoot: ShadowRoot | null = null;\nlet highlightEl: HTMLDivElement | null = null;\n\nexport function createOverlay(): { highlight: (rect: DOMRect | null, label?: string) => void; destroy: () => void } {\n hostEl = document.createElement('div');\n hostEl.id = 'ui-context-host';\n hostEl.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;pointer-events:none;';\n document.body.appendChild(hostEl);\n\n shadowRoot = hostEl.attachShadow({ mode: 'open' });\n\n const style = document.createElement('style');\n style.textContent = `\n .highlight {\n position: fixed;\n border: 2px solid #3b82f6;\n background: rgba(59, 130, 246, 0.1);\n pointer-events: none;\n transition: all 0.1s ease;\n border-radius: 4px;\n z-index: 2147483647;\n }\n .highlight-label {\n position: absolute;\n top: -24px;\n left: -2px;\n background: #3b82f6;\n color: white;\n font-size: 11px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n padding: 2px 6px;\n border-radius: 3px 3px 0 0;\n white-space: nowrap;\n pointer-events: none;\n }\n `;\n shadowRoot.appendChild(style);\n\n highlightEl = document.createElement('div');\n highlightEl.className = 'highlight';\n highlightEl.style.display = 'none';\n\n const labelEl = document.createElement('div');\n labelEl.className = 'highlight-label';\n highlightEl.appendChild(labelEl);\n\n shadowRoot.appendChild(highlightEl);\n\n return {\n highlight(rect: DOMRect | null, label?: string) {\n if (!rect || !highlightEl) {\n if (highlightEl) highlightEl.style.display = 'none';\n return;\n }\n highlightEl.style.display = 'block';\n highlightEl.style.top = rect.top + 'px';\n highlightEl.style.left = rect.left + 'px';\n highlightEl.style.width = rect.width + 'px';\n highlightEl.style.height = rect.height + 'px';\n const lbl = highlightEl.querySelector('.highlight-label') as HTMLDivElement;\n if (lbl && label) {\n lbl.textContent = label;\n lbl.style.display = 'block';\n } else if (lbl) {\n lbl.style.display = 'none';\n }\n },\n destroy() {\n hostEl?.remove();\n hostEl = null;\n shadowRoot = null;\n highlightEl = null;\n },\n };\n}\n","let toastContainer: HTMLDivElement | null = null;\nlet toastShadow: ShadowRoot | null = null;\n\nfunction ensureContainer() {\n if (toastContainer) return;\n toastContainer = document.createElement('div');\n toastContainer.id = 'ui-context-toast';\n toastContainer.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;pointer-events:none;';\n document.body.appendChild(toastContainer);\n toastShadow = toastContainer.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = `\n .toast {\n position: fixed;\n bottom: 24px;\n right: 24px;\n background: #1e293b;\n color: #f1f5f9;\n padding: 12px 20px;\n border-radius: 8px;\n font-size: 13px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.3);\n pointer-events: auto;\n animation: slideIn 0.3s ease, fadeOut 0.3s ease 2.7s;\n z-index: 2147483647;\n }\n @keyframes slideIn { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }\n @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } }\n `;\n toastShadow.appendChild(style);\n}\n\nexport function showToast(message: string, duration = 3000) {\n ensureContainer();\n if (!toastShadow) return;\n const el = document.createElement('div');\n el.className = 'toast';\n el.textContent = message;\n toastShadow.appendChild(el);\n setTimeout(() => el.remove(), duration);\n}\n","export function createToolbar(opts: {\n onCapture: () => void;\n onCaptureAll?: () => void;\n onClose: () => void;\n onFreeze?: () => void;\n}): { el: HTMLElement; destroy: () => void; updateBadge: (count: number) => void; updateFreezeState: (frozen: boolean) => void } {\n const host = document.createElement('div');\n host.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;';\n document.body.appendChild(host);\n\n const shadow = host.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = `\n .toolbar {\n position: fixed;\n bottom: 24px;\n left: 50%;\n transform: translateX(-50%);\n background: #1e293b;\n border: 1px solid #334155;\n border-radius: 12px;\n padding: 8px 12px;\n display: flex;\n gap: 6px;\n align-items: center;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 4px 20px rgba(0,0,0,0.4);\n }\n .toolbar-btn {\n background: #3b82f6;\n color: white;\n border: none;\n padding: 6px 14px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n }\n .toolbar-btn:hover { background: #2563eb; }\n .toolbar-btn.secondary { background: #475569; }\n .toolbar-btn.secondary:hover { background: #64748b; }\n .toolbar-btn.freeze { background: #475569; }\n .toolbar-btn.freeze:hover { background: #64748b; }\n .toolbar-btn.freeze.active { background: #f59e0b; color: #1e293b; }\n .toolbar-btn.freeze.active:hover { background: #d97706; }\n .toolbar-label {\n color: #94a3b8;\n font-size: 12px;\n padding: 0 4px;\n }\n .badge {\n display: inline-block;\n background: #f59e0b;\n color: #1e293b;\n font-size: 10px;\n font-weight: 700;\n padding: 1px 5px;\n border-radius: 10px;\n margin-left: 4px;\n }\n .badge.hidden { display: none; }\n .divider {\n width: 1px;\n height: 20px;\n background: #334155;\n }\n `;\n shadow.appendChild(style);\n\n const toolbar = document.createElement('div');\n toolbar.className = 'toolbar';\n toolbar.innerHTML = `\n <span class=\"toolbar-label\">UI Context</span>\n <div class=\"divider\"></div>\n <button class=\"toolbar-btn capture\">Capture</button>\n <button class=\"toolbar-btn secondary capture-all\" style=\"display:none\">Capture All <span class=\"badge hidden\">0</span></button>\n <div class=\"divider\"></div>\n <button class=\"toolbar-btn freeze\" title=\"Freeze DOM (Ctrl+Shift+F)\">Freeze</button>\n <button class=\"toolbar-btn secondary close\">\\u2715</button>\n `;\n shadow.appendChild(toolbar);\n\n const captureBtn = toolbar.querySelector('.capture') as HTMLButtonElement;\n const captureAllBtn = toolbar.querySelector('.capture-all') as HTMLButtonElement;\n const freezeBtn = toolbar.querySelector('.freeze') as HTMLButtonElement;\n const closeBtn = toolbar.querySelector('.close') as HTMLButtonElement;\n const badge = toolbar.querySelector('.badge') as HTMLSpanElement;\n\n captureBtn.addEventListener('click', opts.onCapture);\n captureAllBtn.addEventListener('click', () => opts.onCaptureAll?.());\n freezeBtn.addEventListener('click', () => opts.onFreeze?.());\n closeBtn.addEventListener('click', opts.onClose);\n\n return {\n el: host,\n destroy() { host.remove(); },\n updateBadge(count: number) {\n if (count > 0) {\n captureAllBtn.style.display = '';\n badge.textContent = String(count);\n badge.classList.remove('hidden');\n } else {\n captureAllBtn.style.display = 'none';\n badge.classList.add('hidden');\n }\n },\n updateFreezeState(frozen: boolean) {\n if (frozen) {\n freezeBtn.classList.add('active');\n freezeBtn.textContent = 'Frozen';\n } else {\n freezeBtn.classList.remove('active');\n freezeBtn.textContent = 'Freeze';\n }\n },\n };\n}\n","export function extractComponentHierarchy(el: HTMLElement): string[] {\n const fiber = getFiber(el);\n if (!fiber) return [];\n\n const hierarchy: string[] = [];\n let current = fiber;\n\n while (current) {\n if (typeof current.type === 'function' || typeof current.type === 'object') {\n const name = typeof current.type === 'function'\n ? current.type.displayName || current.type.name\n : current.type?.displayName || current.type?.render?.displayName || current.type?.render?.name;\n if (name && !name.startsWith('_') && name !== 'Fragment') {\n hierarchy.unshift(name);\n }\n }\n current = current.return;\n }\n\n return hierarchy;\n}\n\nfunction getFiber(el: HTMLElement): any {\n const key = Object.keys(el).find(\n k => k.startsWith('__reactFiber$') || k.startsWith('__reactInternalInstance$')\n );\n return key ? (el as any)[key] : null;\n}\n","import { ElementContext, SourceLocation } from './types';\nimport { extractComponentHierarchy } from './fiber-walker';\n\nconst STYLE_PROPERTIES = [\n 'padding', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft',\n 'margin', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft',\n 'backgroundColor', 'color', 'fontSize', 'fontWeight', 'fontFamily',\n 'borderRadius', 'display', 'flexDirection', 'justifyContent', 'alignItems',\n 'gap', 'width', 'height', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight',\n 'overflow', 'position', 'zIndex', 'opacity', 'border', 'boxShadow',\n 'lineHeight', 'letterSpacing', 'textAlign',\n];\n\nexport function extractSource(el: HTMLElement): SourceLocation | null {\n const file = el.getAttribute('data-source-file');\n const line = el.getAttribute('data-source-line');\n const col = el.getAttribute('data-source-col');\n if (!file || !line) return null;\n return {\n file,\n line: parseInt(line, 10),\n col: parseInt(col || '0', 10),\n component: el.getAttribute('data-source-component') || undefined,\n };\n}\n\nexport function extractContext(el: HTMLElement): ElementContext {\n const computed = getComputedStyle(el);\n const rect = el.getBoundingClientRect();\n const styles: Record<string, string> = {};\n for (const prop of STYLE_PROPERTIES) {\n const value = computed.getPropertyValue(\n prop.replace(/[A-Z]/g, m => '-' + m.toLowerCase())\n );\n if (value && value !== 'none' && value !== 'normal' && value !== 'auto' && value !== '0px' && value !== 'rgba(0, 0, 0, 0)') {\n styles[prop] = value;\n }\n }\n\n return {\n source: extractSource(el),\n tagName: el.tagName.toLowerCase(),\n classes: typeof el.className === 'string' ? el.className : '',\n computedStyles: styles,\n dimensions: { width: rect.width, height: rect.height, x: rect.x, y: rect.y },\n componentHierarchy: extractComponentHierarchy(el),\n url: window.location.href,\n };\n}\n","export async function captureElementScreenshot(el: HTMLElement): Promise<string | undefined> {\n try {\n // Use native canvas approach - works well for most elements\n // without requiring external dependencies like html2canvas\n const rect = el.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) return undefined;\n\n const canvas = document.createElement('canvas');\n const dpr = window.devicePixelRatio || 1;\n const padding = 8; // visual padding around element\n\n const captureWidth = Math.ceil(rect.width + padding * 2);\n const captureHeight = Math.ceil(rect.height + padding * 2);\n\n canvas.width = captureWidth * dpr;\n canvas.height = captureHeight * dpr;\n canvas.style.width = captureWidth + 'px';\n canvas.style.height = captureHeight + 'px';\n\n const ctx = canvas.getContext('2d');\n if (!ctx) return undefined;\n\n ctx.scale(dpr, dpr);\n\n // Try using html-to-image approach via SVG foreignObject\n const screenshot = await captureViaSvgForeignObject(el, rect, ctx, canvas, padding);\n if (screenshot) return screenshot;\n\n // Fallback: capture visible viewport area containing the element\n return await captureViaRange(el, rect, canvas, ctx, padding);\n } catch {\n return undefined;\n }\n}\n\nasync function captureViaSvgForeignObject(\n el: HTMLElement,\n rect: DOMRect,\n ctx: CanvasRenderingContext2D,\n canvas: HTMLCanvasElement,\n padding: number,\n): Promise<string | undefined> {\n try {\n // Clone the element to avoid modifying the original\n const clone = el.cloneNode(true) as HTMLElement;\n\n // Copy computed styles inline\n copyComputedStyles(el, clone);\n\n const width = Math.ceil(rect.width + padding * 2);\n const height = Math.ceil(rect.height + padding * 2);\n\n const svgNs = 'http://www.w3.org/2000/svg';\n const svg = document.createElementNS(svgNs, 'svg');\n svg.setAttribute('width', String(width));\n svg.setAttribute('height', String(height));\n svg.setAttribute('xmlns', svgNs);\n\n const foreignObject = document.createElementNS(svgNs, 'foreignObject');\n foreignObject.setAttribute('width', '100%');\n foreignObject.setAttribute('height', '100%');\n\n const container = document.createElement('div');\n container.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml');\n container.style.cssText = `\n width: ${width}px;\n height: ${height}px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: white;\n padding: ${padding}px;\n box-sizing: border-box;\n `;\n container.appendChild(clone);\n foreignObject.appendChild(container);\n svg.appendChild(foreignObject);\n\n const svgString = new XMLSerializer().serializeToString(svg);\n const svgBlob = new Blob([svgString], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(svgBlob);\n\n return new Promise<string | undefined>((resolve) => {\n const img = new Image();\n img.onload = () => {\n ctx.drawImage(img, 0, 0);\n URL.revokeObjectURL(url);\n try {\n resolve(canvas.toDataURL('image/png'));\n } catch {\n resolve(undefined);\n }\n };\n img.onerror = () => {\n URL.revokeObjectURL(url);\n resolve(undefined);\n };\n img.src = url;\n });\n } catch {\n return undefined;\n }\n}\n\nasync function captureViaRange(\n _el: HTMLElement,\n rect: DOMRect,\n canvas: HTMLCanvasElement,\n ctx: CanvasRenderingContext2D,\n padding: number,\n): Promise<string | undefined> {\n // Fallback: draw a placeholder with element info\n try {\n const width = canvas.width / (window.devicePixelRatio || 1);\n const height = canvas.height / (window.devicePixelRatio || 1);\n\n ctx.fillStyle = '#f8fafc';\n ctx.fillRect(0, 0, width, height);\n ctx.strokeStyle = '#3b82f6';\n ctx.lineWidth = 2;\n ctx.strokeRect(padding, padding, rect.width, rect.height);\n\n ctx.fillStyle = '#64748b';\n ctx.font = '11px -apple-system, BlinkMacSystemFont, sans-serif';\n ctx.fillText(\n `${Math.round(rect.width)} x ${Math.round(rect.height)}px`,\n padding + 4,\n padding + rect.height / 2 + 4,\n );\n\n return canvas.toDataURL('image/png');\n } catch {\n return undefined;\n }\n}\n\nfunction copyComputedStyles(source: HTMLElement, target: HTMLElement): void {\n const computed = getComputedStyle(source);\n const important = [\n 'display', 'width', 'height', 'padding', 'margin', 'border',\n 'border-radius', 'background', 'background-color', 'color',\n 'font-size', 'font-weight', 'font-family', 'line-height',\n 'text-align', 'box-shadow', 'opacity', 'flex-direction',\n 'justify-content', 'align-items', 'gap', 'overflow',\n ];\n for (const prop of important) {\n target.style.setProperty(prop, computed.getPropertyValue(prop));\n }\n\n // Recurse for children\n const sourceChildren = source.children;\n const targetChildren = target.children;\n for (let i = 0; i < sourceChildren.length && i < targetChildren.length; i++) {\n if (sourceChildren[i] instanceof HTMLElement && targetChildren[i] instanceof HTMLElement) {\n copyComputedStyles(sourceChildren[i] as HTMLElement, targetChildren[i] as HTMLElement);\n }\n }\n}\n","import { extractContext } from './context-extractor';\nimport { captureElementScreenshot } from './screenshot';\nimport { ElementContext } from './types';\n\ntype SelectionCallback = (context: ElementContext) => void;\ntype MultiSelectionCallback = (contexts: ElementContext[]) => void;\n\nexport function createSelectionHandler(opts: {\n onHover: (el: HTMLElement | null) => void;\n onSelect: SelectionCallback;\n onMultiSelect?: MultiSelectionCallback;\n onSelectionChange?: (count: number) => void;\n}) {\n let isActive = false;\n let selectedEl: HTMLElement | null = null;\n const multiSelected: Set<HTMLElement> = new Set();\n\n function handleMouseMove(e: MouseEvent) {\n if (!isActive) return;\n const target = e.target as HTMLElement;\n if (target.id === 'ui-context-host' || target.id === 'ui-context-toast' || target.closest('#ui-context-host')) return;\n opts.onHover(target);\n }\n\n function handleClick(e: MouseEvent) {\n if (!isActive) return;\n e.preventDefault();\n e.stopPropagation();\n\n const target = e.target as HTMLElement;\n if (target.id === 'ui-context-host' || target.closest('#ui-context-host')) return;\n\n // Shift+Click: add to multi-selection\n if (e.shiftKey) {\n if (multiSelected.has(target)) {\n multiSelected.delete(target);\n target.style.outline = '';\n } else {\n multiSelected.add(target);\n target.style.outline = '2px dashed #f59e0b';\n }\n opts.onSelectionChange?.(multiSelected.size);\n return;\n }\n\n selectedEl = target;\n const context = extractContext(target);\n\n captureElementScreenshot(target).then(screenshot => {\n if (screenshot) context.screenshotDataUrl = screenshot;\n opts.onSelect(context);\n });\n }\n\n return {\n activate() {\n isActive = true;\n document.addEventListener('mousemove', handleMouseMove, true);\n document.addEventListener('click', handleClick, true);\n document.body.style.cursor = 'crosshair';\n },\n deactivate() {\n isActive = false;\n selectedEl = null;\n // Clear multi-selection outlines\n for (const el of multiSelected) {\n el.style.outline = '';\n }\n multiSelected.clear();\n document.removeEventListener('mousemove', handleMouseMove, true);\n document.removeEventListener('click', handleClick, true);\n document.body.style.cursor = '';\n opts.onHover(null);\n },\n get isActive() { return isActive; },\n get selectedElement() { return selectedEl; },\n get multiSelectedElements() { return multiSelected; },\n get multiSelectedCount() { return multiSelected.size; },\n\n async captureMultiSelection(): Promise<ElementContext[]> {\n const contexts: ElementContext[] = [];\n for (const el of multiSelected) {\n const ctx = extractContext(el);\n const screenshot = await captureElementScreenshot(el);\n if (screenshot) ctx.screenshotDataUrl = screenshot;\n contexts.push(ctx);\n }\n return contexts;\n },\n\n clearMultiSelection() {\n for (const el of multiSelected) {\n el.style.outline = '';\n }\n multiSelected.clear();\n opts.onSelectionChange?.(0);\n },\n };\n}\n","import { ElementContext } from './types';\n\nconst DEFAULT_SERVER_PORT = 19638;\n\nlet serverUrl = '';\n\nexport function initTransport(url?: string) {\n serverUrl = url || `http://127.0.0.1:${DEFAULT_SERVER_PORT}`;\n}\n\nexport function sendContext(context: ElementContext | ElementContext[]): Promise<boolean> {\n return new Promise((resolve) => {\n try {\n // Strategy 1: Vite HMR WebSocket (for Vite projects)\n if (typeof import.meta !== 'undefined' && (import.meta as any).hot) {\n (import.meta as any).hot.send('ui-context:capture', context);\n resolve(true);\n return;\n }\n\n // Strategy 2: HTTP POST to standalone context server (for Next.js projects)\n fetch(`${serverUrl}/capture`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(context),\n })\n .then((res) => res.json())\n .then((result) => resolve(result.success === true))\n .catch(() => resolve(false));\n } catch {\n resolve(false);\n }\n });\n}\n","const STORAGE_KEY = 'ui-context-kit-onboarding-dismissed';\n\nexport function showOnboarding(shortcut: string): void {\n // Don't show if already dismissed\n try {\n if (localStorage.getItem(STORAGE_KEY)) return;\n } catch {\n return; // localStorage not available\n }\n\n const host = document.createElement('div');\n host.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483646;';\n document.body.appendChild(host);\n\n const shadow = host.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = `\n .banner {\n position: fixed;\n bottom: 20px;\n left: 50%;\n transform: translateX(-50%);\n background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);\n border: 1px solid #334155;\n border-radius: 12px;\n padding: 12px 20px;\n display: flex;\n gap: 12px;\n align-items: center;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 8px 32px rgba(0,0,0,0.4);\n animation: slideUp 0.4s ease;\n max-width: 480px;\n }\n @keyframes slideUp {\n from { opacity: 0; transform: translateX(-50%) translateY(20px); }\n to { opacity: 1; transform: translateX(-50%) translateY(0); }\n }\n .icon {\n font-size: 20px;\n flex-shrink: 0;\n }\n .text {\n color: #e2e8f0;\n font-size: 13px;\n line-height: 1.4;\n }\n .text strong {\n color: #60a5fa;\n }\n .kbd {\n display: inline-block;\n background: #334155;\n color: #e2e8f0;\n padding: 1px 6px;\n border-radius: 4px;\n font-size: 12px;\n font-family: monospace;\n border: 1px solid #475569;\n }\n .close-btn {\n background: none;\n border: none;\n color: #64748b;\n cursor: pointer;\n padding: 4px;\n font-size: 16px;\n flex-shrink: 0;\n }\n .close-btn:hover { color: #94a3b8; }\n `;\n shadow.appendChild(style);\n\n const shortcutDisplay = shortcut.split('+').map(k =>\n k.charAt(0).toUpperCase() + k.slice(1)\n ).join(' + ');\n\n const banner = document.createElement('div');\n banner.className = 'banner';\n banner.innerHTML = `\n <span class=\"icon\">\\u{1F3AF}</span>\n <span class=\"text\">\n <strong>UI Context Kit</strong> is ready!\n Press <kbd class=\"kbd\">${shortcutDisplay}</kbd> to select any UI element and capture its context for AI.\n Use <strong>Shift+Click</strong> for multi-select, <strong>Ctrl+Shift+F</strong> to freeze state.\n </span>\n <button class=\"close-btn\" title=\"Dismiss\">\\u2715</button>\n `;\n shadow.appendChild(banner);\n\n banner.querySelector('.close-btn')!.addEventListener('click', () => {\n host.remove();\n try {\n localStorage.setItem(STORAGE_KEY, '1');\n } catch { /* ignore */ }\n });\n\n // Auto-dismiss after 8 seconds\n setTimeout(() => {\n if (host.parentNode) {\n banner.style.transition = 'opacity 0.3s ease';\n banner.style.opacity = '0';\n setTimeout(() => host.remove(), 300);\n }\n }, 8000);\n}\n","import { createOverlay } from './ui/overlay';\nimport { showToast } from './ui/toast';\nimport { createToolbar } from './ui/toolbar';\nimport { createSelectionHandler } from './selection';\nimport { sendContext, initTransport } from './transport';\nimport { extractContext, extractSource } from './context-extractor';\nimport { showOnboarding } from './ui/onboarding';\nimport type { ElementContext } from './types';\n\nexport type { ElementContext, SourceLocation } from './types';\n\nexport interface UIContextOptions {\n shortcut?: string;\n wsUrl?: string;\n}\n\nexport function initUIContext(options: UIContextOptions = {}) {\n const { shortcut = 'alt+x' } = options;\n\n initTransport(options.wsUrl);\n\n let overlay: ReturnType<typeof createOverlay> | null = null;\n let toolbar: ReturnType<typeof createToolbar> | null = null;\n let isFrozen = false;\n let frozenObservers: MutationObserver[] = [];\n\n const selection = createSelectionHandler({\n onHover(el) {\n if (!el) {\n overlay?.highlight(null);\n return;\n }\n const rect = el.getBoundingClientRect();\n const source = extractSource(el);\n const label = source\n ? `${source.component || el.tagName.toLowerCase()} \\u00b7 ${source.file}:${source.line}`\n : el.tagName.toLowerCase();\n overlay?.highlight(rect, label);\n },\n async onSelect(context: ElementContext) {\n showToast('Capturing context...');\n const success = await sendContext(context);\n if (success) {\n showToast('Context captured!');\n } else {\n showToast('Failed to send context. Is the dev server running?');\n }\n },\n onSelectionChange(count) {\n toolbar?.updateBadge(count);\n },\n });\n\n function activate() {\n if (selection.isActive) return;\n overlay = createOverlay();\n toolbar = createToolbar({\n onCapture() {\n if (selection.selectedElement) {\n const context = extractContext(selection.selectedElement);\n sendContext(context);\n }\n },\n async onCaptureAll() {\n if (selection.multiSelectedCount === 0) {\n showToast('No elements selected. Use Shift+Click to select multiple.');\n return;\n }\n showToast(`Capturing ${selection.multiSelectedCount} elements...`);\n const contexts = await selection.captureMultiSelection();\n const success = await sendContext(contexts);\n if (success) {\n showToast(`${contexts.length} elements captured!`);\n selection.clearMultiSelection();\n } else {\n showToast('Failed to send context. Is the dev server running?');\n }\n },\n onClose() { deactivate(); },\n onFreeze() { toggleFreeze(); },\n });\n selection.activate();\n showToast('UI Context active \\u2014 click to capture, Shift+click for multi-select');\n }\n\n function deactivate() {\n if (isFrozen) unfreezeDOM();\n selection.deactivate();\n overlay?.destroy();\n toolbar?.destroy();\n overlay = null;\n toolbar = null;\n }\n\n function toggleFreeze() {\n if (isFrozen) {\n unfreezeDOM();\n showToast('DOM unfrozen');\n } else {\n freezeDOM();\n showToast('DOM frozen \\u2014 hover states preserved');\n }\n toolbar?.updateFreezeState(isFrozen);\n }\n\n function freezeDOM() {\n isFrozen = true;\n // Disconnect all existing MutationObservers by creating a blocking one\n // This prevents DOM updates (dropdowns closing, tooltips hiding, etc.)\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n // Revert added/removed nodes\n for (const node of mutation.addedNodes) {\n if (node instanceof HTMLElement && !node.id?.includes('ui-context')) {\n node.remove();\n }\n }\n // Revert attribute changes\n if (mutation.type === 'attributes' && mutation.target instanceof HTMLElement) {\n if (!mutation.target.id?.includes('ui-context')) {\n const old = mutation.oldValue;\n if (old !== null) {\n mutation.target.setAttribute(mutation.attributeName!, old);\n }\n }\n }\n }\n });\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeOldValue: true,\n });\n frozenObservers.push(observer);\n }\n\n function unfreezeDOM() {\n isFrozen = false;\n for (const obs of frozenObservers) {\n obs.disconnect();\n }\n frozenObservers = [];\n }\n\n // Register keyboard shortcuts\n document.addEventListener('keydown', (e) => {\n // Main shortcut (Alt+X)\n const keys = shortcut.split('+');\n const needsAlt = keys.includes('alt');\n const needsCtrl = keys.includes('ctrl');\n const needsShift = keys.includes('shift');\n const mainKey = keys[keys.length - 1].toLowerCase();\n const mainCode = /^[a-z]$/.test(mainKey) ? 'Key' + mainKey.toUpperCase() : /^[0-9]$/.test(mainKey) ? 'Digit' + mainKey : '';\n\n if (\n e.altKey === needsAlt &&\n e.ctrlKey === needsCtrl &&\n e.shiftKey === needsShift &&\n (mainCode ? e.code === mainCode : e.key.toLowerCase() === mainKey)\n ) {\n e.preventDefault();\n if (selection.isActive) {\n deactivate();\n } else {\n activate();\n }\n return;\n }\n\n // Freeze shortcut: Ctrl+Shift+F (only when active)\n if (selection.isActive && e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'f') {\n e.preventDefault();\n toggleFreeze();\n }\n });\n\n // Show onboarding on first use\n showOnboarding(shortcut);\n\n return { activate, deactivate };\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.cjs
CHANGED
|
@@ -574,7 +574,7 @@ var import_meta = {};
|
|
|
574
574
|
var DEFAULT_SERVER_PORT = 19638;
|
|
575
575
|
var serverUrl = "";
|
|
576
576
|
function initTransport(url) {
|
|
577
|
-
serverUrl = url || `http
|
|
577
|
+
serverUrl = url || `http://127.0.0.1:${DEFAULT_SERVER_PORT}`;
|
|
578
578
|
}
|
|
579
579
|
function sendContext(context) {
|
|
580
580
|
return new Promise((resolve) => {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/ui/overlay.ts","../src/ui/toast.ts","../src/ui/toolbar.ts","../src/fiber-walker.ts","../src/context-extractor.ts","../src/screenshot.ts","../src/selection.ts","../src/transport.ts","../src/ui/onboarding.ts"],"sourcesContent":["import { createOverlay } from './ui/overlay';\nimport { showToast } from './ui/toast';\nimport { createToolbar } from './ui/toolbar';\nimport { createSelectionHandler } from './selection';\nimport { sendContext, initTransport } from './transport';\nimport { extractContext, extractSource } from './context-extractor';\nimport { showOnboarding } from './ui/onboarding';\nimport type { ElementContext } from './types';\n\nexport type { ElementContext, SourceLocation } from './types';\n\nexport interface UIContextOptions {\n shortcut?: string;\n wsUrl?: string;\n}\n\nexport function initUIContext(options: UIContextOptions = {}) {\n const { shortcut = 'alt+x' } = options;\n\n initTransport(options.wsUrl);\n\n let overlay: ReturnType<typeof createOverlay> | null = null;\n let toolbar: ReturnType<typeof createToolbar> | null = null;\n let isFrozen = false;\n let frozenObservers: MutationObserver[] = [];\n\n const selection = createSelectionHandler({\n onHover(el) {\n if (!el) {\n overlay?.highlight(null);\n return;\n }\n const rect = el.getBoundingClientRect();\n const source = extractSource(el);\n const label = source\n ? `${source.component || el.tagName.toLowerCase()} \\u00b7 ${source.file}:${source.line}`\n : el.tagName.toLowerCase();\n overlay?.highlight(rect, label);\n },\n async onSelect(context: ElementContext) {\n showToast('Capturing context...');\n const success = await sendContext(context);\n if (success) {\n showToast('Context captured!');\n } else {\n showToast('Failed to send context. Is the dev server running?');\n }\n },\n onSelectionChange(count) {\n toolbar?.updateBadge(count);\n },\n });\n\n function activate() {\n if (selection.isActive) return;\n overlay = createOverlay();\n toolbar = createToolbar({\n onCapture() {\n if (selection.selectedElement) {\n const context = extractContext(selection.selectedElement);\n sendContext(context);\n }\n },\n async onCaptureAll() {\n if (selection.multiSelectedCount === 0) {\n showToast('No elements selected. Use Shift+Click to select multiple.');\n return;\n }\n showToast(`Capturing ${selection.multiSelectedCount} elements...`);\n const contexts = await selection.captureMultiSelection();\n const success = await sendContext(contexts);\n if (success) {\n showToast(`${contexts.length} elements captured!`);\n selection.clearMultiSelection();\n } else {\n showToast('Failed to send context. Is the dev server running?');\n }\n },\n onClose() { deactivate(); },\n onFreeze() { toggleFreeze(); },\n });\n selection.activate();\n showToast('UI Context active \\u2014 click to capture, Shift+click for multi-select');\n }\n\n function deactivate() {\n if (isFrozen) unfreezeDOM();\n selection.deactivate();\n overlay?.destroy();\n toolbar?.destroy();\n overlay = null;\n toolbar = null;\n }\n\n function toggleFreeze() {\n if (isFrozen) {\n unfreezeDOM();\n showToast('DOM unfrozen');\n } else {\n freezeDOM();\n showToast('DOM frozen \\u2014 hover states preserved');\n }\n toolbar?.updateFreezeState(isFrozen);\n }\n\n function freezeDOM() {\n isFrozen = true;\n // Disconnect all existing MutationObservers by creating a blocking one\n // This prevents DOM updates (dropdowns closing, tooltips hiding, etc.)\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n // Revert added/removed nodes\n for (const node of mutation.addedNodes) {\n if (node instanceof HTMLElement && !node.id?.includes('ui-context')) {\n node.remove();\n }\n }\n // Revert attribute changes\n if (mutation.type === 'attributes' && mutation.target instanceof HTMLElement) {\n if (!mutation.target.id?.includes('ui-context')) {\n const old = mutation.oldValue;\n if (old !== null) {\n mutation.target.setAttribute(mutation.attributeName!, old);\n }\n }\n }\n }\n });\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeOldValue: true,\n });\n frozenObservers.push(observer);\n }\n\n function unfreezeDOM() {\n isFrozen = false;\n for (const obs of frozenObservers) {\n obs.disconnect();\n }\n frozenObservers = [];\n }\n\n // Register keyboard shortcuts\n document.addEventListener('keydown', (e) => {\n // Main shortcut (Alt+X)\n const keys = shortcut.split('+');\n const needsAlt = keys.includes('alt');\n const needsCtrl = keys.includes('ctrl');\n const needsShift = keys.includes('shift');\n const mainKey = keys[keys.length - 1].toLowerCase();\n const mainCode = /^[a-z]$/.test(mainKey) ? 'Key' + mainKey.toUpperCase() : /^[0-9]$/.test(mainKey) ? 'Digit' + mainKey : '';\n\n if (\n e.altKey === needsAlt &&\n e.ctrlKey === needsCtrl &&\n e.shiftKey === needsShift &&\n (mainCode ? e.code === mainCode : e.key.toLowerCase() === mainKey)\n ) {\n e.preventDefault();\n if (selection.isActive) {\n deactivate();\n } else {\n activate();\n }\n return;\n }\n\n // Freeze shortcut: Ctrl+Shift+F (only when active)\n if (selection.isActive && e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'f') {\n e.preventDefault();\n toggleFreeze();\n }\n });\n\n // Show onboarding on first use\n showOnboarding(shortcut);\n\n return { activate, deactivate };\n}\n","let hostEl: HTMLDivElement | null = null;\nlet shadowRoot: ShadowRoot | null = null;\nlet highlightEl: HTMLDivElement | null = null;\n\nexport function createOverlay(): { highlight: (rect: DOMRect | null, label?: string) => void; destroy: () => void } {\n hostEl = document.createElement('div');\n hostEl.id = 'ui-context-host';\n hostEl.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;pointer-events:none;';\n document.body.appendChild(hostEl);\n\n shadowRoot = hostEl.attachShadow({ mode: 'open' });\n\n const style = document.createElement('style');\n style.textContent = `\n .highlight {\n position: fixed;\n border: 2px solid #3b82f6;\n background: rgba(59, 130, 246, 0.1);\n pointer-events: none;\n transition: all 0.1s ease;\n border-radius: 4px;\n z-index: 2147483647;\n }\n .highlight-label {\n position: absolute;\n top: -24px;\n left: -2px;\n background: #3b82f6;\n color: white;\n font-size: 11px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n padding: 2px 6px;\n border-radius: 3px 3px 0 0;\n white-space: nowrap;\n pointer-events: none;\n }\n `;\n shadowRoot.appendChild(style);\n\n highlightEl = document.createElement('div');\n highlightEl.className = 'highlight';\n highlightEl.style.display = 'none';\n\n const labelEl = document.createElement('div');\n labelEl.className = 'highlight-label';\n highlightEl.appendChild(labelEl);\n\n shadowRoot.appendChild(highlightEl);\n\n return {\n highlight(rect: DOMRect | null, label?: string) {\n if (!rect || !highlightEl) {\n if (highlightEl) highlightEl.style.display = 'none';\n return;\n }\n highlightEl.style.display = 'block';\n highlightEl.style.top = rect.top + 'px';\n highlightEl.style.left = rect.left + 'px';\n highlightEl.style.width = rect.width + 'px';\n highlightEl.style.height = rect.height + 'px';\n const lbl = highlightEl.querySelector('.highlight-label') as HTMLDivElement;\n if (lbl && label) {\n lbl.textContent = label;\n lbl.style.display = 'block';\n } else if (lbl) {\n lbl.style.display = 'none';\n }\n },\n destroy() {\n hostEl?.remove();\n hostEl = null;\n shadowRoot = null;\n highlightEl = null;\n },\n };\n}\n","let toastContainer: HTMLDivElement | null = null;\nlet toastShadow: ShadowRoot | null = null;\n\nfunction ensureContainer() {\n if (toastContainer) return;\n toastContainer = document.createElement('div');\n toastContainer.id = 'ui-context-toast';\n toastContainer.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;pointer-events:none;';\n document.body.appendChild(toastContainer);\n toastShadow = toastContainer.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = `\n .toast {\n position: fixed;\n bottom: 24px;\n right: 24px;\n background: #1e293b;\n color: #f1f5f9;\n padding: 12px 20px;\n border-radius: 8px;\n font-size: 13px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.3);\n pointer-events: auto;\n animation: slideIn 0.3s ease, fadeOut 0.3s ease 2.7s;\n z-index: 2147483647;\n }\n @keyframes slideIn { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }\n @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } }\n `;\n toastShadow.appendChild(style);\n}\n\nexport function showToast(message: string, duration = 3000) {\n ensureContainer();\n if (!toastShadow) return;\n const el = document.createElement('div');\n el.className = 'toast';\n el.textContent = message;\n toastShadow.appendChild(el);\n setTimeout(() => el.remove(), duration);\n}\n","export function createToolbar(opts: {\n onCapture: () => void;\n onCaptureAll?: () => void;\n onClose: () => void;\n onFreeze?: () => void;\n}): { el: HTMLElement; destroy: () => void; updateBadge: (count: number) => void; updateFreezeState: (frozen: boolean) => void } {\n const host = document.createElement('div');\n host.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;';\n document.body.appendChild(host);\n\n const shadow = host.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = `\n .toolbar {\n position: fixed;\n bottom: 24px;\n left: 50%;\n transform: translateX(-50%);\n background: #1e293b;\n border: 1px solid #334155;\n border-radius: 12px;\n padding: 8px 12px;\n display: flex;\n gap: 6px;\n align-items: center;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 4px 20px rgba(0,0,0,0.4);\n }\n .toolbar-btn {\n background: #3b82f6;\n color: white;\n border: none;\n padding: 6px 14px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n }\n .toolbar-btn:hover { background: #2563eb; }\n .toolbar-btn.secondary { background: #475569; }\n .toolbar-btn.secondary:hover { background: #64748b; }\n .toolbar-btn.freeze { background: #475569; }\n .toolbar-btn.freeze:hover { background: #64748b; }\n .toolbar-btn.freeze.active { background: #f59e0b; color: #1e293b; }\n .toolbar-btn.freeze.active:hover { background: #d97706; }\n .toolbar-label {\n color: #94a3b8;\n font-size: 12px;\n padding: 0 4px;\n }\n .badge {\n display: inline-block;\n background: #f59e0b;\n color: #1e293b;\n font-size: 10px;\n font-weight: 700;\n padding: 1px 5px;\n border-radius: 10px;\n margin-left: 4px;\n }\n .badge.hidden { display: none; }\n .divider {\n width: 1px;\n height: 20px;\n background: #334155;\n }\n `;\n shadow.appendChild(style);\n\n const toolbar = document.createElement('div');\n toolbar.className = 'toolbar';\n toolbar.innerHTML = `\n <span class=\"toolbar-label\">UI Context</span>\n <div class=\"divider\"></div>\n <button class=\"toolbar-btn capture\">Capture</button>\n <button class=\"toolbar-btn secondary capture-all\" style=\"display:none\">Capture All <span class=\"badge hidden\">0</span></button>\n <div class=\"divider\"></div>\n <button class=\"toolbar-btn freeze\" title=\"Freeze DOM (Ctrl+Shift+F)\">Freeze</button>\n <button class=\"toolbar-btn secondary close\">\\u2715</button>\n `;\n shadow.appendChild(toolbar);\n\n const captureBtn = toolbar.querySelector('.capture') as HTMLButtonElement;\n const captureAllBtn = toolbar.querySelector('.capture-all') as HTMLButtonElement;\n const freezeBtn = toolbar.querySelector('.freeze') as HTMLButtonElement;\n const closeBtn = toolbar.querySelector('.close') as HTMLButtonElement;\n const badge = toolbar.querySelector('.badge') as HTMLSpanElement;\n\n captureBtn.addEventListener('click', opts.onCapture);\n captureAllBtn.addEventListener('click', () => opts.onCaptureAll?.());\n freezeBtn.addEventListener('click', () => opts.onFreeze?.());\n closeBtn.addEventListener('click', opts.onClose);\n\n return {\n el: host,\n destroy() { host.remove(); },\n updateBadge(count: number) {\n if (count > 0) {\n captureAllBtn.style.display = '';\n badge.textContent = String(count);\n badge.classList.remove('hidden');\n } else {\n captureAllBtn.style.display = 'none';\n badge.classList.add('hidden');\n }\n },\n updateFreezeState(frozen: boolean) {\n if (frozen) {\n freezeBtn.classList.add('active');\n freezeBtn.textContent = 'Frozen';\n } else {\n freezeBtn.classList.remove('active');\n freezeBtn.textContent = 'Freeze';\n }\n },\n };\n}\n","export function extractComponentHierarchy(el: HTMLElement): string[] {\n const fiber = getFiber(el);\n if (!fiber) return [];\n\n const hierarchy: string[] = [];\n let current = fiber;\n\n while (current) {\n if (typeof current.type === 'function' || typeof current.type === 'object') {\n const name = typeof current.type === 'function'\n ? current.type.displayName || current.type.name\n : current.type?.displayName || current.type?.render?.displayName || current.type?.render?.name;\n if (name && !name.startsWith('_') && name !== 'Fragment') {\n hierarchy.unshift(name);\n }\n }\n current = current.return;\n }\n\n return hierarchy;\n}\n\nfunction getFiber(el: HTMLElement): any {\n const key = Object.keys(el).find(\n k => k.startsWith('__reactFiber$') || k.startsWith('__reactInternalInstance$')\n );\n return key ? (el as any)[key] : null;\n}\n","import { ElementContext, SourceLocation } from './types';\nimport { extractComponentHierarchy } from './fiber-walker';\n\nconst STYLE_PROPERTIES = [\n 'padding', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft',\n 'margin', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft',\n 'backgroundColor', 'color', 'fontSize', 'fontWeight', 'fontFamily',\n 'borderRadius', 'display', 'flexDirection', 'justifyContent', 'alignItems',\n 'gap', 'width', 'height', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight',\n 'overflow', 'position', 'zIndex', 'opacity', 'border', 'boxShadow',\n 'lineHeight', 'letterSpacing', 'textAlign',\n];\n\nexport function extractSource(el: HTMLElement): SourceLocation | null {\n const file = el.getAttribute('data-source-file');\n const line = el.getAttribute('data-source-line');\n const col = el.getAttribute('data-source-col');\n if (!file || !line) return null;\n return {\n file,\n line: parseInt(line, 10),\n col: parseInt(col || '0', 10),\n component: el.getAttribute('data-source-component') || undefined,\n };\n}\n\nexport function extractContext(el: HTMLElement): ElementContext {\n const computed = getComputedStyle(el);\n const rect = el.getBoundingClientRect();\n const styles: Record<string, string> = {};\n for (const prop of STYLE_PROPERTIES) {\n const value = computed.getPropertyValue(\n prop.replace(/[A-Z]/g, m => '-' + m.toLowerCase())\n );\n if (value && value !== 'none' && value !== 'normal' && value !== 'auto' && value !== '0px' && value !== 'rgba(0, 0, 0, 0)') {\n styles[prop] = value;\n }\n }\n\n return {\n source: extractSource(el),\n tagName: el.tagName.toLowerCase(),\n classes: typeof el.className === 'string' ? el.className : '',\n computedStyles: styles,\n dimensions: { width: rect.width, height: rect.height, x: rect.x, y: rect.y },\n componentHierarchy: extractComponentHierarchy(el),\n url: window.location.href,\n };\n}\n","export async function captureElementScreenshot(el: HTMLElement): Promise<string | undefined> {\n try {\n // Use native canvas approach - works well for most elements\n // without requiring external dependencies like html2canvas\n const rect = el.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) return undefined;\n\n const canvas = document.createElement('canvas');\n const dpr = window.devicePixelRatio || 1;\n const padding = 8; // visual padding around element\n\n const captureWidth = Math.ceil(rect.width + padding * 2);\n const captureHeight = Math.ceil(rect.height + padding * 2);\n\n canvas.width = captureWidth * dpr;\n canvas.height = captureHeight * dpr;\n canvas.style.width = captureWidth + 'px';\n canvas.style.height = captureHeight + 'px';\n\n const ctx = canvas.getContext('2d');\n if (!ctx) return undefined;\n\n ctx.scale(dpr, dpr);\n\n // Try using html-to-image approach via SVG foreignObject\n const screenshot = await captureViaSvgForeignObject(el, rect, ctx, canvas, padding);\n if (screenshot) return screenshot;\n\n // Fallback: capture visible viewport area containing the element\n return await captureViaRange(el, rect, canvas, ctx, padding);\n } catch {\n return undefined;\n }\n}\n\nasync function captureViaSvgForeignObject(\n el: HTMLElement,\n rect: DOMRect,\n ctx: CanvasRenderingContext2D,\n canvas: HTMLCanvasElement,\n padding: number,\n): Promise<string | undefined> {\n try {\n // Clone the element to avoid modifying the original\n const clone = el.cloneNode(true) as HTMLElement;\n\n // Copy computed styles inline\n copyComputedStyles(el, clone);\n\n const width = Math.ceil(rect.width + padding * 2);\n const height = Math.ceil(rect.height + padding * 2);\n\n const svgNs = 'http://www.w3.org/2000/svg';\n const svg = document.createElementNS(svgNs, 'svg');\n svg.setAttribute('width', String(width));\n svg.setAttribute('height', String(height));\n svg.setAttribute('xmlns', svgNs);\n\n const foreignObject = document.createElementNS(svgNs, 'foreignObject');\n foreignObject.setAttribute('width', '100%');\n foreignObject.setAttribute('height', '100%');\n\n const container = document.createElement('div');\n container.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml');\n container.style.cssText = `\n width: ${width}px;\n height: ${height}px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: white;\n padding: ${padding}px;\n box-sizing: border-box;\n `;\n container.appendChild(clone);\n foreignObject.appendChild(container);\n svg.appendChild(foreignObject);\n\n const svgString = new XMLSerializer().serializeToString(svg);\n const svgBlob = new Blob([svgString], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(svgBlob);\n\n return new Promise<string | undefined>((resolve) => {\n const img = new Image();\n img.onload = () => {\n ctx.drawImage(img, 0, 0);\n URL.revokeObjectURL(url);\n try {\n resolve(canvas.toDataURL('image/png'));\n } catch {\n resolve(undefined);\n }\n };\n img.onerror = () => {\n URL.revokeObjectURL(url);\n resolve(undefined);\n };\n img.src = url;\n });\n } catch {\n return undefined;\n }\n}\n\nasync function captureViaRange(\n _el: HTMLElement,\n rect: DOMRect,\n canvas: HTMLCanvasElement,\n ctx: CanvasRenderingContext2D,\n padding: number,\n): Promise<string | undefined> {\n // Fallback: draw a placeholder with element info\n try {\n const width = canvas.width / (window.devicePixelRatio || 1);\n const height = canvas.height / (window.devicePixelRatio || 1);\n\n ctx.fillStyle = '#f8fafc';\n ctx.fillRect(0, 0, width, height);\n ctx.strokeStyle = '#3b82f6';\n ctx.lineWidth = 2;\n ctx.strokeRect(padding, padding, rect.width, rect.height);\n\n ctx.fillStyle = '#64748b';\n ctx.font = '11px -apple-system, BlinkMacSystemFont, sans-serif';\n ctx.fillText(\n `${Math.round(rect.width)} x ${Math.round(rect.height)}px`,\n padding + 4,\n padding + rect.height / 2 + 4,\n );\n\n return canvas.toDataURL('image/png');\n } catch {\n return undefined;\n }\n}\n\nfunction copyComputedStyles(source: HTMLElement, target: HTMLElement): void {\n const computed = getComputedStyle(source);\n const important = [\n 'display', 'width', 'height', 'padding', 'margin', 'border',\n 'border-radius', 'background', 'background-color', 'color',\n 'font-size', 'font-weight', 'font-family', 'line-height',\n 'text-align', 'box-shadow', 'opacity', 'flex-direction',\n 'justify-content', 'align-items', 'gap', 'overflow',\n ];\n for (const prop of important) {\n target.style.setProperty(prop, computed.getPropertyValue(prop));\n }\n\n // Recurse for children\n const sourceChildren = source.children;\n const targetChildren = target.children;\n for (let i = 0; i < sourceChildren.length && i < targetChildren.length; i++) {\n if (sourceChildren[i] instanceof HTMLElement && targetChildren[i] instanceof HTMLElement) {\n copyComputedStyles(sourceChildren[i] as HTMLElement, targetChildren[i] as HTMLElement);\n }\n }\n}\n","import { extractContext } from './context-extractor';\nimport { captureElementScreenshot } from './screenshot';\nimport { ElementContext } from './types';\n\ntype SelectionCallback = (context: ElementContext) => void;\ntype MultiSelectionCallback = (contexts: ElementContext[]) => void;\n\nexport function createSelectionHandler(opts: {\n onHover: (el: HTMLElement | null) => void;\n onSelect: SelectionCallback;\n onMultiSelect?: MultiSelectionCallback;\n onSelectionChange?: (count: number) => void;\n}) {\n let isActive = false;\n let selectedEl: HTMLElement | null = null;\n const multiSelected: Set<HTMLElement> = new Set();\n\n function handleMouseMove(e: MouseEvent) {\n if (!isActive) return;\n const target = e.target as HTMLElement;\n if (target.id === 'ui-context-host' || target.id === 'ui-context-toast' || target.closest('#ui-context-host')) return;\n opts.onHover(target);\n }\n\n function handleClick(e: MouseEvent) {\n if (!isActive) return;\n e.preventDefault();\n e.stopPropagation();\n\n const target = e.target as HTMLElement;\n if (target.id === 'ui-context-host' || target.closest('#ui-context-host')) return;\n\n // Shift+Click: add to multi-selection\n if (e.shiftKey) {\n if (multiSelected.has(target)) {\n multiSelected.delete(target);\n target.style.outline = '';\n } else {\n multiSelected.add(target);\n target.style.outline = '2px dashed #f59e0b';\n }\n opts.onSelectionChange?.(multiSelected.size);\n return;\n }\n\n selectedEl = target;\n const context = extractContext(target);\n\n captureElementScreenshot(target).then(screenshot => {\n if (screenshot) context.screenshotDataUrl = screenshot;\n opts.onSelect(context);\n });\n }\n\n return {\n activate() {\n isActive = true;\n document.addEventListener('mousemove', handleMouseMove, true);\n document.addEventListener('click', handleClick, true);\n document.body.style.cursor = 'crosshair';\n },\n deactivate() {\n isActive = false;\n selectedEl = null;\n // Clear multi-selection outlines\n for (const el of multiSelected) {\n el.style.outline = '';\n }\n multiSelected.clear();\n document.removeEventListener('mousemove', handleMouseMove, true);\n document.removeEventListener('click', handleClick, true);\n document.body.style.cursor = '';\n opts.onHover(null);\n },\n get isActive() { return isActive; },\n get selectedElement() { return selectedEl; },\n get multiSelectedElements() { return multiSelected; },\n get multiSelectedCount() { return multiSelected.size; },\n\n async captureMultiSelection(): Promise<ElementContext[]> {\n const contexts: ElementContext[] = [];\n for (const el of multiSelected) {\n const ctx = extractContext(el);\n const screenshot = await captureElementScreenshot(el);\n if (screenshot) ctx.screenshotDataUrl = screenshot;\n contexts.push(ctx);\n }\n return contexts;\n },\n\n clearMultiSelection() {\n for (const el of multiSelected) {\n el.style.outline = '';\n }\n multiSelected.clear();\n opts.onSelectionChange?.(0);\n },\n };\n}\n","import { ElementContext } from './types';\n\nconst DEFAULT_SERVER_PORT = 19638;\n\nlet serverUrl = '';\n\nexport function initTransport(url?: string) {\n serverUrl = url || `http://${location.hostname}:${DEFAULT_SERVER_PORT}`;\n}\n\nexport function sendContext(context: ElementContext | ElementContext[]): Promise<boolean> {\n return new Promise((resolve) => {\n try {\n // Strategy 1: Vite HMR WebSocket (for Vite projects)\n if (typeof import.meta !== 'undefined' && (import.meta as any).hot) {\n (import.meta as any).hot.send('ui-context:capture', context);\n resolve(true);\n return;\n }\n\n // Strategy 2: HTTP POST to standalone context server (for Next.js projects)\n fetch(`${serverUrl}/capture`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(context),\n })\n .then((res) => res.json())\n .then((result) => resolve(result.success === true))\n .catch(() => resolve(false));\n } catch {\n resolve(false);\n }\n });\n}\n","const STORAGE_KEY = 'ui-context-kit-onboarding-dismissed';\n\nexport function showOnboarding(shortcut: string): void {\n // Don't show if already dismissed\n try {\n if (localStorage.getItem(STORAGE_KEY)) return;\n } catch {\n return; // localStorage not available\n }\n\n const host = document.createElement('div');\n host.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483646;';\n document.body.appendChild(host);\n\n const shadow = host.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = `\n .banner {\n position: fixed;\n bottom: 20px;\n left: 50%;\n transform: translateX(-50%);\n background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);\n border: 1px solid #334155;\n border-radius: 12px;\n padding: 12px 20px;\n display: flex;\n gap: 12px;\n align-items: center;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 8px 32px rgba(0,0,0,0.4);\n animation: slideUp 0.4s ease;\n max-width: 480px;\n }\n @keyframes slideUp {\n from { opacity: 0; transform: translateX(-50%) translateY(20px); }\n to { opacity: 1; transform: translateX(-50%) translateY(0); }\n }\n .icon {\n font-size: 20px;\n flex-shrink: 0;\n }\n .text {\n color: #e2e8f0;\n font-size: 13px;\n line-height: 1.4;\n }\n .text strong {\n color: #60a5fa;\n }\n .kbd {\n display: inline-block;\n background: #334155;\n color: #e2e8f0;\n padding: 1px 6px;\n border-radius: 4px;\n font-size: 12px;\n font-family: monospace;\n border: 1px solid #475569;\n }\n .close-btn {\n background: none;\n border: none;\n color: #64748b;\n cursor: pointer;\n padding: 4px;\n font-size: 16px;\n flex-shrink: 0;\n }\n .close-btn:hover { color: #94a3b8; }\n `;\n shadow.appendChild(style);\n\n const shortcutDisplay = shortcut.split('+').map(k =>\n k.charAt(0).toUpperCase() + k.slice(1)\n ).join(' + ');\n\n const banner = document.createElement('div');\n banner.className = 'banner';\n banner.innerHTML = `\n <span class=\"icon\">\\u{1F3AF}</span>\n <span class=\"text\">\n <strong>UI Context Kit</strong> is ready!\n Press <kbd class=\"kbd\">${shortcutDisplay}</kbd> to select any UI element and capture its context for AI.\n Use <strong>Shift+Click</strong> for multi-select, <strong>Ctrl+Shift+F</strong> to freeze state.\n </span>\n <button class=\"close-btn\" title=\"Dismiss\">\\u2715</button>\n `;\n shadow.appendChild(banner);\n\n banner.querySelector('.close-btn')!.addEventListener('click', () => {\n host.remove();\n try {\n localStorage.setItem(STORAGE_KEY, '1');\n } catch { /* ignore */ }\n });\n\n // Auto-dismiss after 8 seconds\n setTimeout(() => {\n if (host.parentNode) {\n banner.style.transition = 'opacity 0.3s ease';\n banner.style.opacity = '0';\n setTimeout(() => host.remove(), 300);\n }\n }, 8000);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAI,SAAgC;AACpC,IAAI,aAAgC;AACpC,IAAI,cAAqC;AAElC,SAAS,gBAAoG;AAClH,WAAS,SAAS,cAAc,KAAK;AACrC,SAAO,KAAK;AACZ,SAAO,MAAM,UAAU;AACvB,WAAS,KAAK,YAAY,MAAM;AAEhC,eAAa,OAAO,aAAa,EAAE,MAAM,OAAO,CAAC;AAEjD,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAwBpB,aAAW,YAAY,KAAK;AAE5B,gBAAc,SAAS,cAAc,KAAK;AAC1C,cAAY,YAAY;AACxB,cAAY,MAAM,UAAU;AAE5B,QAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,UAAQ,YAAY;AACpB,cAAY,YAAY,OAAO;AAE/B,aAAW,YAAY,WAAW;AAElC,SAAO;AAAA,IACL,UAAU,MAAsB,OAAgB;AAC9C,UAAI,CAAC,QAAQ,CAAC,aAAa;AACzB,YAAI,YAAa,aAAY,MAAM,UAAU;AAC7C;AAAA,MACF;AACA,kBAAY,MAAM,UAAU;AAC5B,kBAAY,MAAM,MAAM,KAAK,MAAM;AACnC,kBAAY,MAAM,OAAO,KAAK,OAAO;AACrC,kBAAY,MAAM,QAAQ,KAAK,QAAQ;AACvC,kBAAY,MAAM,SAAS,KAAK,SAAS;AACzC,YAAM,MAAM,YAAY,cAAc,kBAAkB;AACxD,UAAI,OAAO,OAAO;AAChB,YAAI,cAAc;AAClB,YAAI,MAAM,UAAU;AAAA,MACtB,WAAW,KAAK;AACd,YAAI,MAAM,UAAU;AAAA,MACtB;AAAA,IACF;AAAA,IACA,UAAU;AACR,cAAQ,OAAO;AACf,eAAS;AACT,mBAAa;AACb,oBAAc;AAAA,IAChB;AAAA,EACF;AACF;;;AC3EA,IAAI,iBAAwC;AAC5C,IAAI,cAAiC;AAErC,SAAS,kBAAkB;AACzB,MAAI,eAAgB;AACpB,mBAAiB,SAAS,cAAc,KAAK;AAC7C,iBAAe,KAAK;AACpB,iBAAe,MAAM,UAAU;AAC/B,WAAS,KAAK,YAAY,cAAc;AACxC,gBAAc,eAAe,aAAa,EAAE,MAAM,OAAO,CAAC;AAC1D,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmBpB,cAAY,YAAY,KAAK;AAC/B;AAEO,SAAS,UAAU,SAAiB,WAAW,KAAM;AAC1D,kBAAgB;AAChB,MAAI,CAAC,YAAa;AAClB,QAAM,KAAK,SAAS,cAAc,KAAK;AACvC,KAAG,YAAY;AACf,KAAG,cAAc;AACjB,cAAY,YAAY,EAAE;AAC1B,aAAW,MAAM,GAAG,OAAO,GAAG,QAAQ;AACxC;;;ACzCO,SAAS,cAAc,MAKmG;AAC/H,QAAM,OAAO,SAAS,cAAc,KAAK;AACzC,OAAK,MAAM,UAAU;AACrB,WAAS,KAAK,YAAY,IAAI;AAE9B,QAAM,SAAS,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AACjD,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM,cAAc;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAwDpB,SAAO,YAAY,KAAK;AAExB,QAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,UAAQ,YAAY;AACpB,UAAQ,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASpB,SAAO,YAAY,OAAO;AAE1B,QAAM,aAAa,QAAQ,cAAc,UAAU;AACnD,QAAM,gBAAgB,QAAQ,cAAc,cAAc;AAC1D,QAAM,YAAY,QAAQ,cAAc,SAAS;AACjD,QAAM,WAAW,QAAQ,cAAc,QAAQ;AAC/C,QAAM,QAAQ,QAAQ,cAAc,QAAQ;AAE5C,aAAW,iBAAiB,SAAS,KAAK,SAAS;AACnD,gBAAc,iBAAiB,SAAS,MAAM,KAAK,eAAe,CAAC;AACnE,YAAU,iBAAiB,SAAS,MAAM,KAAK,WAAW,CAAC;AAC3D,WAAS,iBAAiB,SAAS,KAAK,OAAO;AAE/C,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,UAAU;AAAE,WAAK,OAAO;AAAA,IAAG;AAAA,IAC3B,YAAY,OAAe;AACzB,UAAI,QAAQ,GAAG;AACb,sBAAc,MAAM,UAAU;AAC9B,cAAM,cAAc,OAAO,KAAK;AAChC,cAAM,UAAU,OAAO,QAAQ;AAAA,MACjC,OAAO;AACL,sBAAc,MAAM,UAAU;AAC9B,cAAM,UAAU,IAAI,QAAQ;AAAA,MAC9B;AAAA,IACF;AAAA,IACA,kBAAkB,QAAiB;AACjC,UAAI,QAAQ;AACV,kBAAU,UAAU,IAAI,QAAQ;AAChC,kBAAU,cAAc;AAAA,MAC1B,OAAO;AACL,kBAAU,UAAU,OAAO,QAAQ;AACnC,kBAAU,cAAc;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AACF;;;ACrHO,SAAS,0BAA0B,IAA2B;AACnE,QAAM,QAAQ,SAAS,EAAE;AACzB,MAAI,CAAC,MAAO,QAAO,CAAC;AAEpB,QAAM,YAAsB,CAAC;AAC7B,MAAI,UAAU;AAEd,SAAO,SAAS;AACd,QAAI,OAAO,QAAQ,SAAS,cAAc,OAAO,QAAQ,SAAS,UAAU;AAC1E,YAAM,OAAO,OAAO,QAAQ,SAAS,aACjC,QAAQ,KAAK,eAAe,QAAQ,KAAK,OACzC,QAAQ,MAAM,eAAe,QAAQ,MAAM,QAAQ,eAAe,QAAQ,MAAM,QAAQ;AAC5F,UAAI,QAAQ,CAAC,KAAK,WAAW,GAAG,KAAK,SAAS,YAAY;AACxD,kBAAU,QAAQ,IAAI;AAAA,MACxB;AAAA,IACF;AACA,cAAU,QAAQ;AAAA,EACpB;AAEA,SAAO;AACT;AAEA,SAAS,SAAS,IAAsB;AACtC,QAAM,MAAM,OAAO,KAAK,EAAE,EAAE;AAAA,IAC1B,OAAK,EAAE,WAAW,eAAe,KAAK,EAAE,WAAW,0BAA0B;AAAA,EAC/E;AACA,SAAO,MAAO,GAAW,GAAG,IAAI;AAClC;;;ACxBA,IAAM,mBAAmB;AAAA,EACvB;AAAA,EAAW;AAAA,EAAc;AAAA,EAAgB;AAAA,EAAiB;AAAA,EAC1D;AAAA,EAAU;AAAA,EAAa;AAAA,EAAe;AAAA,EAAgB;AAAA,EACtD;AAAA,EAAmB;AAAA,EAAS;AAAA,EAAY;AAAA,EAAc;AAAA,EACtD;AAAA,EAAgB;AAAA,EAAW;AAAA,EAAiB;AAAA,EAAkB;AAAA,EAC9D;AAAA,EAAO;AAAA,EAAS;AAAA,EAAU;AAAA,EAAY;AAAA,EAAa;AAAA,EAAY;AAAA,EAC/D;AAAA,EAAY;AAAA,EAAY;AAAA,EAAU;AAAA,EAAW;AAAA,EAAU;AAAA,EACvD;AAAA,EAAc;AAAA,EAAiB;AACjC;AAEO,SAAS,cAAc,IAAwC;AACpE,QAAM,OAAO,GAAG,aAAa,kBAAkB;AAC/C,QAAM,OAAO,GAAG,aAAa,kBAAkB;AAC/C,QAAM,MAAM,GAAG,aAAa,iBAAiB;AAC7C,MAAI,CAAC,QAAQ,CAAC,KAAM,QAAO;AAC3B,SAAO;AAAA,IACL;AAAA,IACA,MAAM,SAAS,MAAM,EAAE;AAAA,IACvB,KAAK,SAAS,OAAO,KAAK,EAAE;AAAA,IAC5B,WAAW,GAAG,aAAa,uBAAuB,KAAK;AAAA,EACzD;AACF;AAEO,SAAS,eAAe,IAAiC;AAC9D,QAAM,WAAW,iBAAiB,EAAE;AACpC,QAAM,OAAO,GAAG,sBAAsB;AACtC,QAAM,SAAiC,CAAC;AACxC,aAAW,QAAQ,kBAAkB;AACnC,UAAM,QAAQ,SAAS;AAAA,MACrB,KAAK,QAAQ,UAAU,OAAK,MAAM,EAAE,YAAY,CAAC;AAAA,IACnD;AACA,QAAI,SAAS,UAAU,UAAU,UAAU,YAAY,UAAU,UAAU,UAAU,SAAS,UAAU,oBAAoB;AAC1H,aAAO,IAAI,IAAI;AAAA,IACjB;AAAA,EACF;AAEA,SAAO;AAAA,IACL,QAAQ,cAAc,EAAE;AAAA,IACxB,SAAS,GAAG,QAAQ,YAAY;AAAA,IAChC,SAAS,OAAO,GAAG,cAAc,WAAW,GAAG,YAAY;AAAA,IAC3D,gBAAgB;AAAA,IAChB,YAAY,EAAE,OAAO,KAAK,OAAO,QAAQ,KAAK,QAAQ,GAAG,KAAK,GAAG,GAAG,KAAK,EAAE;AAAA,IAC3E,oBAAoB,0BAA0B,EAAE;AAAA,IAChD,KAAK,OAAO,SAAS;AAAA,EACvB;AACF;;;AChDA,eAAsB,yBAAyB,IAA8C;AAC3F,MAAI;AAGF,UAAM,OAAO,GAAG,sBAAsB;AACtC,QAAI,KAAK,UAAU,KAAK,KAAK,WAAW,EAAG,QAAO;AAElD,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,UAAM,MAAM,OAAO,oBAAoB;AACvC,UAAM,UAAU;AAEhB,UAAM,eAAe,KAAK,KAAK,KAAK,QAAQ,UAAU,CAAC;AACvD,UAAM,gBAAgB,KAAK,KAAK,KAAK,SAAS,UAAU,CAAC;AAEzD,WAAO,QAAQ,eAAe;AAC9B,WAAO,SAAS,gBAAgB;AAChC,WAAO,MAAM,QAAQ,eAAe;AACpC,WAAO,MAAM,SAAS,gBAAgB;AAEtC,UAAM,MAAM,OAAO,WAAW,IAAI;AAClC,QAAI,CAAC,IAAK,QAAO;AAEjB,QAAI,MAAM,KAAK,GAAG;AAGlB,UAAM,aAAa,MAAM,2BAA2B,IAAI,MAAM,KAAK,QAAQ,OAAO;AAClF,QAAI,WAAY,QAAO;AAGvB,WAAO,MAAM,gBAAgB,IAAI,MAAM,QAAQ,KAAK,OAAO;AAAA,EAC7D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,2BACb,IACA,MACA,KACA,QACA,SAC6B;AAC7B,MAAI;AAEF,UAAM,QAAQ,GAAG,UAAU,IAAI;AAG/B,uBAAmB,IAAI,KAAK;AAE5B,UAAM,QAAQ,KAAK,KAAK,KAAK,QAAQ,UAAU,CAAC;AAChD,UAAM,SAAS,KAAK,KAAK,KAAK,SAAS,UAAU,CAAC;AAElD,UAAM,QAAQ;AACd,UAAM,MAAM,SAAS,gBAAgB,OAAO,KAAK;AACjD,QAAI,aAAa,SAAS,OAAO,KAAK,CAAC;AACvC,QAAI,aAAa,UAAU,OAAO,MAAM,CAAC;AACzC,QAAI,aAAa,SAAS,KAAK;AAE/B,UAAM,gBAAgB,SAAS,gBAAgB,OAAO,eAAe;AACrE,kBAAc,aAAa,SAAS,MAAM;AAC1C,kBAAc,aAAa,UAAU,MAAM;AAE3C,UAAM,YAAY,SAAS,cAAc,KAAK;AAC9C,cAAU,aAAa,SAAS,8BAA8B;AAC9D,cAAU,MAAM,UAAU;AAAA,eACf,KAAK;AAAA,gBACJ,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA,iBAKL,OAAO;AAAA;AAAA;AAGpB,cAAU,YAAY,KAAK;AAC3B,kBAAc,YAAY,SAAS;AACnC,QAAI,YAAY,aAAa;AAE7B,UAAM,YAAY,IAAI,cAAc,EAAE,kBAAkB,GAAG;AAC3D,UAAM,UAAU,IAAI,KAAK,CAAC,SAAS,GAAG,EAAE,MAAM,8BAA8B,CAAC;AAC7E,UAAM,MAAM,IAAI,gBAAgB,OAAO;AAEvC,WAAO,IAAI,QAA4B,CAAC,YAAY;AAClD,YAAM,MAAM,IAAI,MAAM;AACtB,UAAI,SAAS,MAAM;AACjB,YAAI,UAAU,KAAK,GAAG,CAAC;AACvB,YAAI,gBAAgB,GAAG;AACvB,YAAI;AACF,kBAAQ,OAAO,UAAU,WAAW,CAAC;AAAA,QACvC,QAAQ;AACN,kBAAQ,MAAS;AAAA,QACnB;AAAA,MACF;AACA,UAAI,UAAU,MAAM;AAClB,YAAI,gBAAgB,GAAG;AACvB,gBAAQ,MAAS;AAAA,MACnB;AACA,UAAI,MAAM;AAAA,IACZ,CAAC;AAAA,EACH,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,gBACb,KACA,MACA,QACA,KACA,SAC6B;AAE7B,MAAI;AACF,UAAM,QAAQ,OAAO,SAAS,OAAO,oBAAoB;AACzD,UAAM,SAAS,OAAO,UAAU,OAAO,oBAAoB;AAE3D,QAAI,YAAY;AAChB,QAAI,SAAS,GAAG,GAAG,OAAO,MAAM;AAChC,QAAI,cAAc;AAClB,QAAI,YAAY;AAChB,QAAI,WAAW,SAAS,SAAS,KAAK,OAAO,KAAK,MAAM;AAExD,QAAI,YAAY;AAChB,QAAI,OAAO;AACX,QAAI;AAAA,MACF,GAAG,KAAK,MAAM,KAAK,KAAK,CAAC,MAAM,KAAK,MAAM,KAAK,MAAM,CAAC;AAAA,MACtD,UAAU;AAAA,MACV,UAAU,KAAK,SAAS,IAAI;AAAA,IAC9B;AAEA,WAAO,OAAO,UAAU,WAAW;AAAA,EACrC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,mBAAmB,QAAqB,QAA2B;AAC1E,QAAM,WAAW,iBAAiB,MAAM;AACxC,QAAM,YAAY;AAAA,IAChB;AAAA,IAAW;AAAA,IAAS;AAAA,IAAU;AAAA,IAAW;AAAA,IAAU;AAAA,IACnD;AAAA,IAAiB;AAAA,IAAc;AAAA,IAAoB;AAAA,IACnD;AAAA,IAAa;AAAA,IAAe;AAAA,IAAe;AAAA,IAC3C;AAAA,IAAc;AAAA,IAAc;AAAA,IAAW;AAAA,IACvC;AAAA,IAAmB;AAAA,IAAe;AAAA,IAAO;AAAA,EAC3C;AACA,aAAW,QAAQ,WAAW;AAC5B,WAAO,MAAM,YAAY,MAAM,SAAS,iBAAiB,IAAI,CAAC;AAAA,EAChE;AAGA,QAAM,iBAAiB,OAAO;AAC9B,QAAM,iBAAiB,OAAO;AAC9B,WAAS,IAAI,GAAG,IAAI,eAAe,UAAU,IAAI,eAAe,QAAQ,KAAK;AAC3E,QAAI,eAAe,CAAC,aAAa,eAAe,eAAe,CAAC,aAAa,aAAa;AACxF,yBAAmB,eAAe,CAAC,GAAkB,eAAe,CAAC,CAAgB;AAAA,IACvF;AAAA,EACF;AACF;;;ACtJO,SAAS,uBAAuB,MAKpC;AACD,MAAI,WAAW;AACf,MAAI,aAAiC;AACrC,QAAM,gBAAkC,oBAAI,IAAI;AAEhD,WAAS,gBAAgB,GAAe;AACtC,QAAI,CAAC,SAAU;AACf,UAAM,SAAS,EAAE;AACjB,QAAI,OAAO,OAAO,qBAAqB,OAAO,OAAO,sBAAsB,OAAO,QAAQ,kBAAkB,EAAG;AAC/G,SAAK,QAAQ,MAAM;AAAA,EACrB;AAEA,WAAS,YAAY,GAAe;AAClC,QAAI,CAAC,SAAU;AACf,MAAE,eAAe;AACjB,MAAE,gBAAgB;AAElB,UAAM,SAAS,EAAE;AACjB,QAAI,OAAO,OAAO,qBAAqB,OAAO,QAAQ,kBAAkB,EAAG;AAG3E,QAAI,EAAE,UAAU;AACd,UAAI,cAAc,IAAI,MAAM,GAAG;AAC7B,sBAAc,OAAO,MAAM;AAC3B,eAAO,MAAM,UAAU;AAAA,MACzB,OAAO;AACL,sBAAc,IAAI,MAAM;AACxB,eAAO,MAAM,UAAU;AAAA,MACzB;AACA,WAAK,oBAAoB,cAAc,IAAI;AAC3C;AAAA,IACF;AAEA,iBAAa;AACb,UAAM,UAAU,eAAe,MAAM;AAErC,6BAAyB,MAAM,EAAE,KAAK,gBAAc;AAClD,UAAI,WAAY,SAAQ,oBAAoB;AAC5C,WAAK,SAAS,OAAO;AAAA,IACvB,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,WAAW;AACT,iBAAW;AACX,eAAS,iBAAiB,aAAa,iBAAiB,IAAI;AAC5D,eAAS,iBAAiB,SAAS,aAAa,IAAI;AACpD,eAAS,KAAK,MAAM,SAAS;AAAA,IAC/B;AAAA,IACA,aAAa;AACX,iBAAW;AACX,mBAAa;AAEb,iBAAW,MAAM,eAAe;AAC9B,WAAG,MAAM,UAAU;AAAA,MACrB;AACA,oBAAc,MAAM;AACpB,eAAS,oBAAoB,aAAa,iBAAiB,IAAI;AAC/D,eAAS,oBAAoB,SAAS,aAAa,IAAI;AACvD,eAAS,KAAK,MAAM,SAAS;AAC7B,WAAK,QAAQ,IAAI;AAAA,IACnB;AAAA,IACA,IAAI,WAAW;AAAE,aAAO;AAAA,IAAU;AAAA,IAClC,IAAI,kBAAkB;AAAE,aAAO;AAAA,IAAY;AAAA,IAC3C,IAAI,wBAAwB;AAAE,aAAO;AAAA,IAAe;AAAA,IACpD,IAAI,qBAAqB;AAAE,aAAO,cAAc;AAAA,IAAM;AAAA,IAEtD,MAAM,wBAAmD;AACvD,YAAM,WAA6B,CAAC;AACpC,iBAAW,MAAM,eAAe;AAC9B,cAAM,MAAM,eAAe,EAAE;AAC7B,cAAM,aAAa,MAAM,yBAAyB,EAAE;AACpD,YAAI,WAAY,KAAI,oBAAoB;AACxC,iBAAS,KAAK,GAAG;AAAA,MACnB;AACA,aAAO;AAAA,IACT;AAAA,IAEA,sBAAsB;AACpB,iBAAW,MAAM,eAAe;AAC9B,WAAG,MAAM,UAAU;AAAA,MACrB;AACA,oBAAc,MAAM;AACpB,WAAK,oBAAoB,CAAC;AAAA,IAC5B;AAAA,EACF;AACF;;;AClGA;AAEA,IAAM,sBAAsB;AAE5B,IAAI,YAAY;AAET,SAAS,cAAc,KAAc;AAC1C,cAAY,OAAO,UAAU,SAAS,QAAQ,IAAI,mBAAmB;AACvE;AAEO,SAAS,YAAY,SAA8D;AACxF,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,QAAI;AAEF,UAAI,OAAO,gBAAgB,eAAgB,YAAoB,KAAK;AAClE,QAAC,YAAoB,IAAI,KAAK,sBAAsB,OAAO;AAC3D,gBAAQ,IAAI;AACZ;AAAA,MACF;AAGA,YAAM,GAAG,SAAS,YAAY;AAAA,QAC5B,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,OAAO;AAAA,MAC9B,CAAC,EACE,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,EACxB,KAAK,CAAC,WAAW,QAAQ,OAAO,YAAY,IAAI,CAAC,EACjD,MAAM,MAAM,QAAQ,KAAK,CAAC;AAAA,IAC/B,QAAQ;AACN,cAAQ,KAAK;AAAA,IACf;AAAA,EACF,CAAC;AACH;;;ACjCA,IAAM,cAAc;AAEb,SAAS,eAAe,UAAwB;AAErD,MAAI;AACF,QAAI,aAAa,QAAQ,WAAW,EAAG;AAAA,EACzC,QAAQ;AACN;AAAA,EACF;AAEA,QAAM,OAAO,SAAS,cAAc,KAAK;AACzC,OAAK,MAAM,UAAU;AACrB,WAAS,KAAK,YAAY,IAAI;AAE9B,QAAM,SAAS,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AACjD,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM,cAAc;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuDpB,SAAO,YAAY,KAAK;AAExB,QAAM,kBAAkB,SAAS,MAAM,GAAG,EAAE;AAAA,IAAI,OAC9C,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC;AAAA,EACvC,EAAE,KAAK,KAAK;AAEZ,QAAM,SAAS,SAAS,cAAc,KAAK;AAC3C,SAAO,YAAY;AACnB,SAAO,YAAY;AAAA;AAAA;AAAA;AAAA,+BAIU,eAAe;AAAA;AAAA;AAAA;AAAA;AAK5C,SAAO,YAAY,MAAM;AAEzB,SAAO,cAAc,YAAY,EAAG,iBAAiB,SAAS,MAAM;AAClE,SAAK,OAAO;AACZ,QAAI;AACF,mBAAa,QAAQ,aAAa,GAAG;AAAA,IACvC,QAAQ;AAAA,IAAe;AAAA,EACzB,CAAC;AAGD,aAAW,MAAM;AACf,QAAI,KAAK,YAAY;AACnB,aAAO,MAAM,aAAa;AAC1B,aAAO,MAAM,UAAU;AACvB,iBAAW,MAAM,KAAK,OAAO,GAAG,GAAG;AAAA,IACrC;AAAA,EACF,GAAG,GAAI;AACT;;;ATzFO,SAAS,cAAc,UAA4B,CAAC,GAAG;AAC5D,QAAM,EAAE,WAAW,QAAQ,IAAI;AAE/B,gBAAc,QAAQ,KAAK;AAE3B,MAAI,UAAmD;AACvD,MAAI,UAAmD;AACvD,MAAI,WAAW;AACf,MAAI,kBAAsC,CAAC;AAE3C,QAAM,YAAY,uBAAuB;AAAA,IACvC,QAAQ,IAAI;AACV,UAAI,CAAC,IAAI;AACP,iBAAS,UAAU,IAAI;AACvB;AAAA,MACF;AACA,YAAM,OAAO,GAAG,sBAAsB;AACtC,YAAM,SAAS,cAAc,EAAE;AAC/B,YAAM,QAAQ,SACV,GAAG,OAAO,aAAa,GAAG,QAAQ,YAAY,CAAC,SAAW,OAAO,IAAI,IAAI,OAAO,IAAI,KACpF,GAAG,QAAQ,YAAY;AAC3B,eAAS,UAAU,MAAM,KAAK;AAAA,IAChC;AAAA,IACA,MAAM,SAAS,SAAyB;AACtC,gBAAU,sBAAsB;AAChC,YAAM,UAAU,MAAM,YAAY,OAAO;AACzC,UAAI,SAAS;AACX,kBAAU,mBAAmB;AAAA,MAC/B,OAAO;AACL,kBAAU,oDAAoD;AAAA,MAChE;AAAA,IACF;AAAA,IACA,kBAAkB,OAAO;AACvB,eAAS,YAAY,KAAK;AAAA,IAC5B;AAAA,EACF,CAAC;AAED,WAAS,WAAW;AAClB,QAAI,UAAU,SAAU;AACxB,cAAU,cAAc;AACxB,cAAU,cAAc;AAAA,MACtB,YAAY;AACV,YAAI,UAAU,iBAAiB;AAC7B,gBAAM,UAAU,eAAe,UAAU,eAAe;AACxD,sBAAY,OAAO;AAAA,QACrB;AAAA,MACF;AAAA,MACA,MAAM,eAAe;AACnB,YAAI,UAAU,uBAAuB,GAAG;AACtC,oBAAU,2DAA2D;AACrE;AAAA,QACF;AACA,kBAAU,aAAa,UAAU,kBAAkB,cAAc;AACjE,cAAM,WAAW,MAAM,UAAU,sBAAsB;AACvD,cAAM,UAAU,MAAM,YAAY,QAAQ;AAC1C,YAAI,SAAS;AACX,oBAAU,GAAG,SAAS,MAAM,qBAAqB;AACjD,oBAAU,oBAAoB;AAAA,QAChC,OAAO;AACL,oBAAU,oDAAoD;AAAA,QAChE;AAAA,MACF;AAAA,MACA,UAAU;AAAE,mBAAW;AAAA,MAAG;AAAA,MAC1B,WAAW;AAAE,qBAAa;AAAA,MAAG;AAAA,IAC/B,CAAC;AACD,cAAU,SAAS;AACnB,cAAU,yEAAyE;AAAA,EACrF;AAEA,WAAS,aAAa;AACpB,QAAI,SAAU,aAAY;AAC1B,cAAU,WAAW;AACrB,aAAS,QAAQ;AACjB,aAAS,QAAQ;AACjB,cAAU;AACV,cAAU;AAAA,EACZ;AAEA,WAAS,eAAe;AACtB,QAAI,UAAU;AACZ,kBAAY;AACZ,gBAAU,cAAc;AAAA,IAC1B,OAAO;AACL,gBAAU;AACV,gBAAU,0CAA0C;AAAA,IACtD;AACA,aAAS,kBAAkB,QAAQ;AAAA,EACrC;AAEA,WAAS,YAAY;AACnB,eAAW;AAGX,UAAM,WAAW,IAAI,iBAAiB,CAAC,cAAc;AACnD,iBAAW,YAAY,WAAW;AAEhC,mBAAW,QAAQ,SAAS,YAAY;AACtC,cAAI,gBAAgB,eAAe,CAAC,KAAK,IAAI,SAAS,YAAY,GAAG;AACnE,iBAAK,OAAO;AAAA,UACd;AAAA,QACF;AAEA,YAAI,SAAS,SAAS,gBAAgB,SAAS,kBAAkB,aAAa;AAC5E,cAAI,CAAC,SAAS,OAAO,IAAI,SAAS,YAAY,GAAG;AAC/C,kBAAM,MAAM,SAAS;AACrB,gBAAI,QAAQ,MAAM;AAChB,uBAAS,OAAO,aAAa,SAAS,eAAgB,GAAG;AAAA,YAC3D;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AACD,aAAS,QAAQ,SAAS,MAAM;AAAA,MAC9B,WAAW;AAAA,MACX,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,mBAAmB;AAAA,IACrB,CAAC;AACD,oBAAgB,KAAK,QAAQ;AAAA,EAC/B;AAEA,WAAS,cAAc;AACrB,eAAW;AACX,eAAW,OAAO,iBAAiB;AACjC,UAAI,WAAW;AAAA,IACjB;AACA,sBAAkB,CAAC;AAAA,EACrB;AAGA,WAAS,iBAAiB,WAAW,CAAC,MAAM;AAE1C,UAAM,OAAO,SAAS,MAAM,GAAG;AAC/B,UAAM,WAAW,KAAK,SAAS,KAAK;AACpC,UAAM,YAAY,KAAK,SAAS,MAAM;AACtC,UAAM,aAAa,KAAK,SAAS,OAAO;AACxC,UAAM,UAAU,KAAK,KAAK,SAAS,CAAC,EAAE,YAAY;AAClD,UAAM,WAAW,UAAU,KAAK,OAAO,IAAI,QAAQ,QAAQ,YAAY,IAAI,UAAU,KAAK,OAAO,IAAI,UAAU,UAAU;AAEzH,QACE,EAAE,WAAW,YACb,EAAE,YAAY,aACd,EAAE,aAAa,eACd,WAAW,EAAE,SAAS,WAAW,EAAE,IAAI,YAAY,MAAM,UAC1D;AACA,QAAE,eAAe;AACjB,UAAI,UAAU,UAAU;AACtB,mBAAW;AAAA,MACb,OAAO;AACL,iBAAS;AAAA,MACX;AACA;AAAA,IACF;AAGA,QAAI,UAAU,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,IAAI,YAAY,MAAM,KAAK;AAChF,QAAE,eAAe;AACjB,mBAAa;AAAA,IACf;AAAA,EACF,CAAC;AAGD,iBAAe,QAAQ;AAEvB,SAAO,EAAE,UAAU,WAAW;AAChC;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/ui/overlay.ts","../src/ui/toast.ts","../src/ui/toolbar.ts","../src/fiber-walker.ts","../src/context-extractor.ts","../src/screenshot.ts","../src/selection.ts","../src/transport.ts","../src/ui/onboarding.ts"],"sourcesContent":["import { createOverlay } from './ui/overlay';\nimport { showToast } from './ui/toast';\nimport { createToolbar } from './ui/toolbar';\nimport { createSelectionHandler } from './selection';\nimport { sendContext, initTransport } from './transport';\nimport { extractContext, extractSource } from './context-extractor';\nimport { showOnboarding } from './ui/onboarding';\nimport type { ElementContext } from './types';\n\nexport type { ElementContext, SourceLocation } from './types';\n\nexport interface UIContextOptions {\n shortcut?: string;\n wsUrl?: string;\n}\n\nexport function initUIContext(options: UIContextOptions = {}) {\n const { shortcut = 'alt+x' } = options;\n\n initTransport(options.wsUrl);\n\n let overlay: ReturnType<typeof createOverlay> | null = null;\n let toolbar: ReturnType<typeof createToolbar> | null = null;\n let isFrozen = false;\n let frozenObservers: MutationObserver[] = [];\n\n const selection = createSelectionHandler({\n onHover(el) {\n if (!el) {\n overlay?.highlight(null);\n return;\n }\n const rect = el.getBoundingClientRect();\n const source = extractSource(el);\n const label = source\n ? `${source.component || el.tagName.toLowerCase()} \\u00b7 ${source.file}:${source.line}`\n : el.tagName.toLowerCase();\n overlay?.highlight(rect, label);\n },\n async onSelect(context: ElementContext) {\n showToast('Capturing context...');\n const success = await sendContext(context);\n if (success) {\n showToast('Context captured!');\n } else {\n showToast('Failed to send context. Is the dev server running?');\n }\n },\n onSelectionChange(count) {\n toolbar?.updateBadge(count);\n },\n });\n\n function activate() {\n if (selection.isActive) return;\n overlay = createOverlay();\n toolbar = createToolbar({\n onCapture() {\n if (selection.selectedElement) {\n const context = extractContext(selection.selectedElement);\n sendContext(context);\n }\n },\n async onCaptureAll() {\n if (selection.multiSelectedCount === 0) {\n showToast('No elements selected. Use Shift+Click to select multiple.');\n return;\n }\n showToast(`Capturing ${selection.multiSelectedCount} elements...`);\n const contexts = await selection.captureMultiSelection();\n const success = await sendContext(contexts);\n if (success) {\n showToast(`${contexts.length} elements captured!`);\n selection.clearMultiSelection();\n } else {\n showToast('Failed to send context. Is the dev server running?');\n }\n },\n onClose() { deactivate(); },\n onFreeze() { toggleFreeze(); },\n });\n selection.activate();\n showToast('UI Context active \\u2014 click to capture, Shift+click for multi-select');\n }\n\n function deactivate() {\n if (isFrozen) unfreezeDOM();\n selection.deactivate();\n overlay?.destroy();\n toolbar?.destroy();\n overlay = null;\n toolbar = null;\n }\n\n function toggleFreeze() {\n if (isFrozen) {\n unfreezeDOM();\n showToast('DOM unfrozen');\n } else {\n freezeDOM();\n showToast('DOM frozen \\u2014 hover states preserved');\n }\n toolbar?.updateFreezeState(isFrozen);\n }\n\n function freezeDOM() {\n isFrozen = true;\n // Disconnect all existing MutationObservers by creating a blocking one\n // This prevents DOM updates (dropdowns closing, tooltips hiding, etc.)\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n // Revert added/removed nodes\n for (const node of mutation.addedNodes) {\n if (node instanceof HTMLElement && !node.id?.includes('ui-context')) {\n node.remove();\n }\n }\n // Revert attribute changes\n if (mutation.type === 'attributes' && mutation.target instanceof HTMLElement) {\n if (!mutation.target.id?.includes('ui-context')) {\n const old = mutation.oldValue;\n if (old !== null) {\n mutation.target.setAttribute(mutation.attributeName!, old);\n }\n }\n }\n }\n });\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeOldValue: true,\n });\n frozenObservers.push(observer);\n }\n\n function unfreezeDOM() {\n isFrozen = false;\n for (const obs of frozenObservers) {\n obs.disconnect();\n }\n frozenObservers = [];\n }\n\n // Register keyboard shortcuts\n document.addEventListener('keydown', (e) => {\n // Main shortcut (Alt+X)\n const keys = shortcut.split('+');\n const needsAlt = keys.includes('alt');\n const needsCtrl = keys.includes('ctrl');\n const needsShift = keys.includes('shift');\n const mainKey = keys[keys.length - 1].toLowerCase();\n const mainCode = /^[a-z]$/.test(mainKey) ? 'Key' + mainKey.toUpperCase() : /^[0-9]$/.test(mainKey) ? 'Digit' + mainKey : '';\n\n if (\n e.altKey === needsAlt &&\n e.ctrlKey === needsCtrl &&\n e.shiftKey === needsShift &&\n (mainCode ? e.code === mainCode : e.key.toLowerCase() === mainKey)\n ) {\n e.preventDefault();\n if (selection.isActive) {\n deactivate();\n } else {\n activate();\n }\n return;\n }\n\n // Freeze shortcut: Ctrl+Shift+F (only when active)\n if (selection.isActive && e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'f') {\n e.preventDefault();\n toggleFreeze();\n }\n });\n\n // Show onboarding on first use\n showOnboarding(shortcut);\n\n return { activate, deactivate };\n}\n","let hostEl: HTMLDivElement | null = null;\nlet shadowRoot: ShadowRoot | null = null;\nlet highlightEl: HTMLDivElement | null = null;\n\nexport function createOverlay(): { highlight: (rect: DOMRect | null, label?: string) => void; destroy: () => void } {\n hostEl = document.createElement('div');\n hostEl.id = 'ui-context-host';\n hostEl.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;pointer-events:none;';\n document.body.appendChild(hostEl);\n\n shadowRoot = hostEl.attachShadow({ mode: 'open' });\n\n const style = document.createElement('style');\n style.textContent = `\n .highlight {\n position: fixed;\n border: 2px solid #3b82f6;\n background: rgba(59, 130, 246, 0.1);\n pointer-events: none;\n transition: all 0.1s ease;\n border-radius: 4px;\n z-index: 2147483647;\n }\n .highlight-label {\n position: absolute;\n top: -24px;\n left: -2px;\n background: #3b82f6;\n color: white;\n font-size: 11px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n padding: 2px 6px;\n border-radius: 3px 3px 0 0;\n white-space: nowrap;\n pointer-events: none;\n }\n `;\n shadowRoot.appendChild(style);\n\n highlightEl = document.createElement('div');\n highlightEl.className = 'highlight';\n highlightEl.style.display = 'none';\n\n const labelEl = document.createElement('div');\n labelEl.className = 'highlight-label';\n highlightEl.appendChild(labelEl);\n\n shadowRoot.appendChild(highlightEl);\n\n return {\n highlight(rect: DOMRect | null, label?: string) {\n if (!rect || !highlightEl) {\n if (highlightEl) highlightEl.style.display = 'none';\n return;\n }\n highlightEl.style.display = 'block';\n highlightEl.style.top = rect.top + 'px';\n highlightEl.style.left = rect.left + 'px';\n highlightEl.style.width = rect.width + 'px';\n highlightEl.style.height = rect.height + 'px';\n const lbl = highlightEl.querySelector('.highlight-label') as HTMLDivElement;\n if (lbl && label) {\n lbl.textContent = label;\n lbl.style.display = 'block';\n } else if (lbl) {\n lbl.style.display = 'none';\n }\n },\n destroy() {\n hostEl?.remove();\n hostEl = null;\n shadowRoot = null;\n highlightEl = null;\n },\n };\n}\n","let toastContainer: HTMLDivElement | null = null;\nlet toastShadow: ShadowRoot | null = null;\n\nfunction ensureContainer() {\n if (toastContainer) return;\n toastContainer = document.createElement('div');\n toastContainer.id = 'ui-context-toast';\n toastContainer.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;pointer-events:none;';\n document.body.appendChild(toastContainer);\n toastShadow = toastContainer.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = `\n .toast {\n position: fixed;\n bottom: 24px;\n right: 24px;\n background: #1e293b;\n color: #f1f5f9;\n padding: 12px 20px;\n border-radius: 8px;\n font-size: 13px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.3);\n pointer-events: auto;\n animation: slideIn 0.3s ease, fadeOut 0.3s ease 2.7s;\n z-index: 2147483647;\n }\n @keyframes slideIn { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }\n @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } }\n `;\n toastShadow.appendChild(style);\n}\n\nexport function showToast(message: string, duration = 3000) {\n ensureContainer();\n if (!toastShadow) return;\n const el = document.createElement('div');\n el.className = 'toast';\n el.textContent = message;\n toastShadow.appendChild(el);\n setTimeout(() => el.remove(), duration);\n}\n","export function createToolbar(opts: {\n onCapture: () => void;\n onCaptureAll?: () => void;\n onClose: () => void;\n onFreeze?: () => void;\n}): { el: HTMLElement; destroy: () => void; updateBadge: (count: number) => void; updateFreezeState: (frozen: boolean) => void } {\n const host = document.createElement('div');\n host.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;';\n document.body.appendChild(host);\n\n const shadow = host.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = `\n .toolbar {\n position: fixed;\n bottom: 24px;\n left: 50%;\n transform: translateX(-50%);\n background: #1e293b;\n border: 1px solid #334155;\n border-radius: 12px;\n padding: 8px 12px;\n display: flex;\n gap: 6px;\n align-items: center;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 4px 20px rgba(0,0,0,0.4);\n }\n .toolbar-btn {\n background: #3b82f6;\n color: white;\n border: none;\n padding: 6px 14px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n }\n .toolbar-btn:hover { background: #2563eb; }\n .toolbar-btn.secondary { background: #475569; }\n .toolbar-btn.secondary:hover { background: #64748b; }\n .toolbar-btn.freeze { background: #475569; }\n .toolbar-btn.freeze:hover { background: #64748b; }\n .toolbar-btn.freeze.active { background: #f59e0b; color: #1e293b; }\n .toolbar-btn.freeze.active:hover { background: #d97706; }\n .toolbar-label {\n color: #94a3b8;\n font-size: 12px;\n padding: 0 4px;\n }\n .badge {\n display: inline-block;\n background: #f59e0b;\n color: #1e293b;\n font-size: 10px;\n font-weight: 700;\n padding: 1px 5px;\n border-radius: 10px;\n margin-left: 4px;\n }\n .badge.hidden { display: none; }\n .divider {\n width: 1px;\n height: 20px;\n background: #334155;\n }\n `;\n shadow.appendChild(style);\n\n const toolbar = document.createElement('div');\n toolbar.className = 'toolbar';\n toolbar.innerHTML = `\n <span class=\"toolbar-label\">UI Context</span>\n <div class=\"divider\"></div>\n <button class=\"toolbar-btn capture\">Capture</button>\n <button class=\"toolbar-btn secondary capture-all\" style=\"display:none\">Capture All <span class=\"badge hidden\">0</span></button>\n <div class=\"divider\"></div>\n <button class=\"toolbar-btn freeze\" title=\"Freeze DOM (Ctrl+Shift+F)\">Freeze</button>\n <button class=\"toolbar-btn secondary close\">\\u2715</button>\n `;\n shadow.appendChild(toolbar);\n\n const captureBtn = toolbar.querySelector('.capture') as HTMLButtonElement;\n const captureAllBtn = toolbar.querySelector('.capture-all') as HTMLButtonElement;\n const freezeBtn = toolbar.querySelector('.freeze') as HTMLButtonElement;\n const closeBtn = toolbar.querySelector('.close') as HTMLButtonElement;\n const badge = toolbar.querySelector('.badge') as HTMLSpanElement;\n\n captureBtn.addEventListener('click', opts.onCapture);\n captureAllBtn.addEventListener('click', () => opts.onCaptureAll?.());\n freezeBtn.addEventListener('click', () => opts.onFreeze?.());\n closeBtn.addEventListener('click', opts.onClose);\n\n return {\n el: host,\n destroy() { host.remove(); },\n updateBadge(count: number) {\n if (count > 0) {\n captureAllBtn.style.display = '';\n badge.textContent = String(count);\n badge.classList.remove('hidden');\n } else {\n captureAllBtn.style.display = 'none';\n badge.classList.add('hidden');\n }\n },\n updateFreezeState(frozen: boolean) {\n if (frozen) {\n freezeBtn.classList.add('active');\n freezeBtn.textContent = 'Frozen';\n } else {\n freezeBtn.classList.remove('active');\n freezeBtn.textContent = 'Freeze';\n }\n },\n };\n}\n","export function extractComponentHierarchy(el: HTMLElement): string[] {\n const fiber = getFiber(el);\n if (!fiber) return [];\n\n const hierarchy: string[] = [];\n let current = fiber;\n\n while (current) {\n if (typeof current.type === 'function' || typeof current.type === 'object') {\n const name = typeof current.type === 'function'\n ? current.type.displayName || current.type.name\n : current.type?.displayName || current.type?.render?.displayName || current.type?.render?.name;\n if (name && !name.startsWith('_') && name !== 'Fragment') {\n hierarchy.unshift(name);\n }\n }\n current = current.return;\n }\n\n return hierarchy;\n}\n\nfunction getFiber(el: HTMLElement): any {\n const key = Object.keys(el).find(\n k => k.startsWith('__reactFiber$') || k.startsWith('__reactInternalInstance$')\n );\n return key ? (el as any)[key] : null;\n}\n","import { ElementContext, SourceLocation } from './types';\nimport { extractComponentHierarchy } from './fiber-walker';\n\nconst STYLE_PROPERTIES = [\n 'padding', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft',\n 'margin', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft',\n 'backgroundColor', 'color', 'fontSize', 'fontWeight', 'fontFamily',\n 'borderRadius', 'display', 'flexDirection', 'justifyContent', 'alignItems',\n 'gap', 'width', 'height', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight',\n 'overflow', 'position', 'zIndex', 'opacity', 'border', 'boxShadow',\n 'lineHeight', 'letterSpacing', 'textAlign',\n];\n\nexport function extractSource(el: HTMLElement): SourceLocation | null {\n const file = el.getAttribute('data-source-file');\n const line = el.getAttribute('data-source-line');\n const col = el.getAttribute('data-source-col');\n if (!file || !line) return null;\n return {\n file,\n line: parseInt(line, 10),\n col: parseInt(col || '0', 10),\n component: el.getAttribute('data-source-component') || undefined,\n };\n}\n\nexport function extractContext(el: HTMLElement): ElementContext {\n const computed = getComputedStyle(el);\n const rect = el.getBoundingClientRect();\n const styles: Record<string, string> = {};\n for (const prop of STYLE_PROPERTIES) {\n const value = computed.getPropertyValue(\n prop.replace(/[A-Z]/g, m => '-' + m.toLowerCase())\n );\n if (value && value !== 'none' && value !== 'normal' && value !== 'auto' && value !== '0px' && value !== 'rgba(0, 0, 0, 0)') {\n styles[prop] = value;\n }\n }\n\n return {\n source: extractSource(el),\n tagName: el.tagName.toLowerCase(),\n classes: typeof el.className === 'string' ? el.className : '',\n computedStyles: styles,\n dimensions: { width: rect.width, height: rect.height, x: rect.x, y: rect.y },\n componentHierarchy: extractComponentHierarchy(el),\n url: window.location.href,\n };\n}\n","export async function captureElementScreenshot(el: HTMLElement): Promise<string | undefined> {\n try {\n // Use native canvas approach - works well for most elements\n // without requiring external dependencies like html2canvas\n const rect = el.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) return undefined;\n\n const canvas = document.createElement('canvas');\n const dpr = window.devicePixelRatio || 1;\n const padding = 8; // visual padding around element\n\n const captureWidth = Math.ceil(rect.width + padding * 2);\n const captureHeight = Math.ceil(rect.height + padding * 2);\n\n canvas.width = captureWidth * dpr;\n canvas.height = captureHeight * dpr;\n canvas.style.width = captureWidth + 'px';\n canvas.style.height = captureHeight + 'px';\n\n const ctx = canvas.getContext('2d');\n if (!ctx) return undefined;\n\n ctx.scale(dpr, dpr);\n\n // Try using html-to-image approach via SVG foreignObject\n const screenshot = await captureViaSvgForeignObject(el, rect, ctx, canvas, padding);\n if (screenshot) return screenshot;\n\n // Fallback: capture visible viewport area containing the element\n return await captureViaRange(el, rect, canvas, ctx, padding);\n } catch {\n return undefined;\n }\n}\n\nasync function captureViaSvgForeignObject(\n el: HTMLElement,\n rect: DOMRect,\n ctx: CanvasRenderingContext2D,\n canvas: HTMLCanvasElement,\n padding: number,\n): Promise<string | undefined> {\n try {\n // Clone the element to avoid modifying the original\n const clone = el.cloneNode(true) as HTMLElement;\n\n // Copy computed styles inline\n copyComputedStyles(el, clone);\n\n const width = Math.ceil(rect.width + padding * 2);\n const height = Math.ceil(rect.height + padding * 2);\n\n const svgNs = 'http://www.w3.org/2000/svg';\n const svg = document.createElementNS(svgNs, 'svg');\n svg.setAttribute('width', String(width));\n svg.setAttribute('height', String(height));\n svg.setAttribute('xmlns', svgNs);\n\n const foreignObject = document.createElementNS(svgNs, 'foreignObject');\n foreignObject.setAttribute('width', '100%');\n foreignObject.setAttribute('height', '100%');\n\n const container = document.createElement('div');\n container.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml');\n container.style.cssText = `\n width: ${width}px;\n height: ${height}px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: white;\n padding: ${padding}px;\n box-sizing: border-box;\n `;\n container.appendChild(clone);\n foreignObject.appendChild(container);\n svg.appendChild(foreignObject);\n\n const svgString = new XMLSerializer().serializeToString(svg);\n const svgBlob = new Blob([svgString], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(svgBlob);\n\n return new Promise<string | undefined>((resolve) => {\n const img = new Image();\n img.onload = () => {\n ctx.drawImage(img, 0, 0);\n URL.revokeObjectURL(url);\n try {\n resolve(canvas.toDataURL('image/png'));\n } catch {\n resolve(undefined);\n }\n };\n img.onerror = () => {\n URL.revokeObjectURL(url);\n resolve(undefined);\n };\n img.src = url;\n });\n } catch {\n return undefined;\n }\n}\n\nasync function captureViaRange(\n _el: HTMLElement,\n rect: DOMRect,\n canvas: HTMLCanvasElement,\n ctx: CanvasRenderingContext2D,\n padding: number,\n): Promise<string | undefined> {\n // Fallback: draw a placeholder with element info\n try {\n const width = canvas.width / (window.devicePixelRatio || 1);\n const height = canvas.height / (window.devicePixelRatio || 1);\n\n ctx.fillStyle = '#f8fafc';\n ctx.fillRect(0, 0, width, height);\n ctx.strokeStyle = '#3b82f6';\n ctx.lineWidth = 2;\n ctx.strokeRect(padding, padding, rect.width, rect.height);\n\n ctx.fillStyle = '#64748b';\n ctx.font = '11px -apple-system, BlinkMacSystemFont, sans-serif';\n ctx.fillText(\n `${Math.round(rect.width)} x ${Math.round(rect.height)}px`,\n padding + 4,\n padding + rect.height / 2 + 4,\n );\n\n return canvas.toDataURL('image/png');\n } catch {\n return undefined;\n }\n}\n\nfunction copyComputedStyles(source: HTMLElement, target: HTMLElement): void {\n const computed = getComputedStyle(source);\n const important = [\n 'display', 'width', 'height', 'padding', 'margin', 'border',\n 'border-radius', 'background', 'background-color', 'color',\n 'font-size', 'font-weight', 'font-family', 'line-height',\n 'text-align', 'box-shadow', 'opacity', 'flex-direction',\n 'justify-content', 'align-items', 'gap', 'overflow',\n ];\n for (const prop of important) {\n target.style.setProperty(prop, computed.getPropertyValue(prop));\n }\n\n // Recurse for children\n const sourceChildren = source.children;\n const targetChildren = target.children;\n for (let i = 0; i < sourceChildren.length && i < targetChildren.length; i++) {\n if (sourceChildren[i] instanceof HTMLElement && targetChildren[i] instanceof HTMLElement) {\n copyComputedStyles(sourceChildren[i] as HTMLElement, targetChildren[i] as HTMLElement);\n }\n }\n}\n","import { extractContext } from './context-extractor';\nimport { captureElementScreenshot } from './screenshot';\nimport { ElementContext } from './types';\n\ntype SelectionCallback = (context: ElementContext) => void;\ntype MultiSelectionCallback = (contexts: ElementContext[]) => void;\n\nexport function createSelectionHandler(opts: {\n onHover: (el: HTMLElement | null) => void;\n onSelect: SelectionCallback;\n onMultiSelect?: MultiSelectionCallback;\n onSelectionChange?: (count: number) => void;\n}) {\n let isActive = false;\n let selectedEl: HTMLElement | null = null;\n const multiSelected: Set<HTMLElement> = new Set();\n\n function handleMouseMove(e: MouseEvent) {\n if (!isActive) return;\n const target = e.target as HTMLElement;\n if (target.id === 'ui-context-host' || target.id === 'ui-context-toast' || target.closest('#ui-context-host')) return;\n opts.onHover(target);\n }\n\n function handleClick(e: MouseEvent) {\n if (!isActive) return;\n e.preventDefault();\n e.stopPropagation();\n\n const target = e.target as HTMLElement;\n if (target.id === 'ui-context-host' || target.closest('#ui-context-host')) return;\n\n // Shift+Click: add to multi-selection\n if (e.shiftKey) {\n if (multiSelected.has(target)) {\n multiSelected.delete(target);\n target.style.outline = '';\n } else {\n multiSelected.add(target);\n target.style.outline = '2px dashed #f59e0b';\n }\n opts.onSelectionChange?.(multiSelected.size);\n return;\n }\n\n selectedEl = target;\n const context = extractContext(target);\n\n captureElementScreenshot(target).then(screenshot => {\n if (screenshot) context.screenshotDataUrl = screenshot;\n opts.onSelect(context);\n });\n }\n\n return {\n activate() {\n isActive = true;\n document.addEventListener('mousemove', handleMouseMove, true);\n document.addEventListener('click', handleClick, true);\n document.body.style.cursor = 'crosshair';\n },\n deactivate() {\n isActive = false;\n selectedEl = null;\n // Clear multi-selection outlines\n for (const el of multiSelected) {\n el.style.outline = '';\n }\n multiSelected.clear();\n document.removeEventListener('mousemove', handleMouseMove, true);\n document.removeEventListener('click', handleClick, true);\n document.body.style.cursor = '';\n opts.onHover(null);\n },\n get isActive() { return isActive; },\n get selectedElement() { return selectedEl; },\n get multiSelectedElements() { return multiSelected; },\n get multiSelectedCount() { return multiSelected.size; },\n\n async captureMultiSelection(): Promise<ElementContext[]> {\n const contexts: ElementContext[] = [];\n for (const el of multiSelected) {\n const ctx = extractContext(el);\n const screenshot = await captureElementScreenshot(el);\n if (screenshot) ctx.screenshotDataUrl = screenshot;\n contexts.push(ctx);\n }\n return contexts;\n },\n\n clearMultiSelection() {\n for (const el of multiSelected) {\n el.style.outline = '';\n }\n multiSelected.clear();\n opts.onSelectionChange?.(0);\n },\n };\n}\n","import { ElementContext } from './types';\n\nconst DEFAULT_SERVER_PORT = 19638;\n\nlet serverUrl = '';\n\nexport function initTransport(url?: string) {\n serverUrl = url || `http://127.0.0.1:${DEFAULT_SERVER_PORT}`;\n}\n\nexport function sendContext(context: ElementContext | ElementContext[]): Promise<boolean> {\n return new Promise((resolve) => {\n try {\n // Strategy 1: Vite HMR WebSocket (for Vite projects)\n if (typeof import.meta !== 'undefined' && (import.meta as any).hot) {\n (import.meta as any).hot.send('ui-context:capture', context);\n resolve(true);\n return;\n }\n\n // Strategy 2: HTTP POST to standalone context server (for Next.js projects)\n fetch(`${serverUrl}/capture`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(context),\n })\n .then((res) => res.json())\n .then((result) => resolve(result.success === true))\n .catch(() => resolve(false));\n } catch {\n resolve(false);\n }\n });\n}\n","const STORAGE_KEY = 'ui-context-kit-onboarding-dismissed';\n\nexport function showOnboarding(shortcut: string): void {\n // Don't show if already dismissed\n try {\n if (localStorage.getItem(STORAGE_KEY)) return;\n } catch {\n return; // localStorage not available\n }\n\n const host = document.createElement('div');\n host.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483646;';\n document.body.appendChild(host);\n\n const shadow = host.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = `\n .banner {\n position: fixed;\n bottom: 20px;\n left: 50%;\n transform: translateX(-50%);\n background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);\n border: 1px solid #334155;\n border-radius: 12px;\n padding: 12px 20px;\n display: flex;\n gap: 12px;\n align-items: center;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 8px 32px rgba(0,0,0,0.4);\n animation: slideUp 0.4s ease;\n max-width: 480px;\n }\n @keyframes slideUp {\n from { opacity: 0; transform: translateX(-50%) translateY(20px); }\n to { opacity: 1; transform: translateX(-50%) translateY(0); }\n }\n .icon {\n font-size: 20px;\n flex-shrink: 0;\n }\n .text {\n color: #e2e8f0;\n font-size: 13px;\n line-height: 1.4;\n }\n .text strong {\n color: #60a5fa;\n }\n .kbd {\n display: inline-block;\n background: #334155;\n color: #e2e8f0;\n padding: 1px 6px;\n border-radius: 4px;\n font-size: 12px;\n font-family: monospace;\n border: 1px solid #475569;\n }\n .close-btn {\n background: none;\n border: none;\n color: #64748b;\n cursor: pointer;\n padding: 4px;\n font-size: 16px;\n flex-shrink: 0;\n }\n .close-btn:hover { color: #94a3b8; }\n `;\n shadow.appendChild(style);\n\n const shortcutDisplay = shortcut.split('+').map(k =>\n k.charAt(0).toUpperCase() + k.slice(1)\n ).join(' + ');\n\n const banner = document.createElement('div');\n banner.className = 'banner';\n banner.innerHTML = `\n <span class=\"icon\">\\u{1F3AF}</span>\n <span class=\"text\">\n <strong>UI Context Kit</strong> is ready!\n Press <kbd class=\"kbd\">${shortcutDisplay}</kbd> to select any UI element and capture its context for AI.\n Use <strong>Shift+Click</strong> for multi-select, <strong>Ctrl+Shift+F</strong> to freeze state.\n </span>\n <button class=\"close-btn\" title=\"Dismiss\">\\u2715</button>\n `;\n shadow.appendChild(banner);\n\n banner.querySelector('.close-btn')!.addEventListener('click', () => {\n host.remove();\n try {\n localStorage.setItem(STORAGE_KEY, '1');\n } catch { /* ignore */ }\n });\n\n // Auto-dismiss after 8 seconds\n setTimeout(() => {\n if (host.parentNode) {\n banner.style.transition = 'opacity 0.3s ease';\n banner.style.opacity = '0';\n setTimeout(() => host.remove(), 300);\n }\n }, 8000);\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.js
CHANGED
package/dist/inject.cjs
CHANGED
|
@@ -550,7 +550,7 @@ var import_meta = {};
|
|
|
550
550
|
var DEFAULT_SERVER_PORT = 19638;
|
|
551
551
|
var serverUrl = "";
|
|
552
552
|
function initTransport(url) {
|
|
553
|
-
serverUrl = url || `http
|
|
553
|
+
serverUrl = url || `http://127.0.0.1:${DEFAULT_SERVER_PORT}`;
|
|
554
554
|
}
|
|
555
555
|
function sendContext(context) {
|
|
556
556
|
return new Promise((resolve) => {
|
package/dist/inject.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ui/overlay.ts","../src/ui/toast.ts","../src/ui/toolbar.ts","../src/fiber-walker.ts","../src/context-extractor.ts","../src/screenshot.ts","../src/selection.ts","../src/transport.ts","../src/ui/onboarding.ts","../src/index.ts","../src/inject.ts"],"sourcesContent":["let hostEl: HTMLDivElement | null = null;\nlet shadowRoot: ShadowRoot | null = null;\nlet highlightEl: HTMLDivElement | null = null;\n\nexport function createOverlay(): { highlight: (rect: DOMRect | null, label?: string) => void; destroy: () => void } {\n hostEl = document.createElement('div');\n hostEl.id = 'ui-context-host';\n hostEl.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;pointer-events:none;';\n document.body.appendChild(hostEl);\n\n shadowRoot = hostEl.attachShadow({ mode: 'open' });\n\n const style = document.createElement('style');\n style.textContent = `\n .highlight {\n position: fixed;\n border: 2px solid #3b82f6;\n background: rgba(59, 130, 246, 0.1);\n pointer-events: none;\n transition: all 0.1s ease;\n border-radius: 4px;\n z-index: 2147483647;\n }\n .highlight-label {\n position: absolute;\n top: -24px;\n left: -2px;\n background: #3b82f6;\n color: white;\n font-size: 11px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n padding: 2px 6px;\n border-radius: 3px 3px 0 0;\n white-space: nowrap;\n pointer-events: none;\n }\n `;\n shadowRoot.appendChild(style);\n\n highlightEl = document.createElement('div');\n highlightEl.className = 'highlight';\n highlightEl.style.display = 'none';\n\n const labelEl = document.createElement('div');\n labelEl.className = 'highlight-label';\n highlightEl.appendChild(labelEl);\n\n shadowRoot.appendChild(highlightEl);\n\n return {\n highlight(rect: DOMRect | null, label?: string) {\n if (!rect || !highlightEl) {\n if (highlightEl) highlightEl.style.display = 'none';\n return;\n }\n highlightEl.style.display = 'block';\n highlightEl.style.top = rect.top + 'px';\n highlightEl.style.left = rect.left + 'px';\n highlightEl.style.width = rect.width + 'px';\n highlightEl.style.height = rect.height + 'px';\n const lbl = highlightEl.querySelector('.highlight-label') as HTMLDivElement;\n if (lbl && label) {\n lbl.textContent = label;\n lbl.style.display = 'block';\n } else if (lbl) {\n lbl.style.display = 'none';\n }\n },\n destroy() {\n hostEl?.remove();\n hostEl = null;\n shadowRoot = null;\n highlightEl = null;\n },\n };\n}\n","let toastContainer: HTMLDivElement | null = null;\nlet toastShadow: ShadowRoot | null = null;\n\nfunction ensureContainer() {\n if (toastContainer) return;\n toastContainer = document.createElement('div');\n toastContainer.id = 'ui-context-toast';\n toastContainer.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;pointer-events:none;';\n document.body.appendChild(toastContainer);\n toastShadow = toastContainer.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = `\n .toast {\n position: fixed;\n bottom: 24px;\n right: 24px;\n background: #1e293b;\n color: #f1f5f9;\n padding: 12px 20px;\n border-radius: 8px;\n font-size: 13px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.3);\n pointer-events: auto;\n animation: slideIn 0.3s ease, fadeOut 0.3s ease 2.7s;\n z-index: 2147483647;\n }\n @keyframes slideIn { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }\n @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } }\n `;\n toastShadow.appendChild(style);\n}\n\nexport function showToast(message: string, duration = 3000) {\n ensureContainer();\n if (!toastShadow) return;\n const el = document.createElement('div');\n el.className = 'toast';\n el.textContent = message;\n toastShadow.appendChild(el);\n setTimeout(() => el.remove(), duration);\n}\n","export function createToolbar(opts: {\n onCapture: () => void;\n onCaptureAll?: () => void;\n onClose: () => void;\n onFreeze?: () => void;\n}): { el: HTMLElement; destroy: () => void; updateBadge: (count: number) => void; updateFreezeState: (frozen: boolean) => void } {\n const host = document.createElement('div');\n host.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;';\n document.body.appendChild(host);\n\n const shadow = host.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = `\n .toolbar {\n position: fixed;\n bottom: 24px;\n left: 50%;\n transform: translateX(-50%);\n background: #1e293b;\n border: 1px solid #334155;\n border-radius: 12px;\n padding: 8px 12px;\n display: flex;\n gap: 6px;\n align-items: center;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 4px 20px rgba(0,0,0,0.4);\n }\n .toolbar-btn {\n background: #3b82f6;\n color: white;\n border: none;\n padding: 6px 14px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n }\n .toolbar-btn:hover { background: #2563eb; }\n .toolbar-btn.secondary { background: #475569; }\n .toolbar-btn.secondary:hover { background: #64748b; }\n .toolbar-btn.freeze { background: #475569; }\n .toolbar-btn.freeze:hover { background: #64748b; }\n .toolbar-btn.freeze.active { background: #f59e0b; color: #1e293b; }\n .toolbar-btn.freeze.active:hover { background: #d97706; }\n .toolbar-label {\n color: #94a3b8;\n font-size: 12px;\n padding: 0 4px;\n }\n .badge {\n display: inline-block;\n background: #f59e0b;\n color: #1e293b;\n font-size: 10px;\n font-weight: 700;\n padding: 1px 5px;\n border-radius: 10px;\n margin-left: 4px;\n }\n .badge.hidden { display: none; }\n .divider {\n width: 1px;\n height: 20px;\n background: #334155;\n }\n `;\n shadow.appendChild(style);\n\n const toolbar = document.createElement('div');\n toolbar.className = 'toolbar';\n toolbar.innerHTML = `\n <span class=\"toolbar-label\">UI Context</span>\n <div class=\"divider\"></div>\n <button class=\"toolbar-btn capture\">Capture</button>\n <button class=\"toolbar-btn secondary capture-all\" style=\"display:none\">Capture All <span class=\"badge hidden\">0</span></button>\n <div class=\"divider\"></div>\n <button class=\"toolbar-btn freeze\" title=\"Freeze DOM (Ctrl+Shift+F)\">Freeze</button>\n <button class=\"toolbar-btn secondary close\">\\u2715</button>\n `;\n shadow.appendChild(toolbar);\n\n const captureBtn = toolbar.querySelector('.capture') as HTMLButtonElement;\n const captureAllBtn = toolbar.querySelector('.capture-all') as HTMLButtonElement;\n const freezeBtn = toolbar.querySelector('.freeze') as HTMLButtonElement;\n const closeBtn = toolbar.querySelector('.close') as HTMLButtonElement;\n const badge = toolbar.querySelector('.badge') as HTMLSpanElement;\n\n captureBtn.addEventListener('click', opts.onCapture);\n captureAllBtn.addEventListener('click', () => opts.onCaptureAll?.());\n freezeBtn.addEventListener('click', () => opts.onFreeze?.());\n closeBtn.addEventListener('click', opts.onClose);\n\n return {\n el: host,\n destroy() { host.remove(); },\n updateBadge(count: number) {\n if (count > 0) {\n captureAllBtn.style.display = '';\n badge.textContent = String(count);\n badge.classList.remove('hidden');\n } else {\n captureAllBtn.style.display = 'none';\n badge.classList.add('hidden');\n }\n },\n updateFreezeState(frozen: boolean) {\n if (frozen) {\n freezeBtn.classList.add('active');\n freezeBtn.textContent = 'Frozen';\n } else {\n freezeBtn.classList.remove('active');\n freezeBtn.textContent = 'Freeze';\n }\n },\n };\n}\n","export function extractComponentHierarchy(el: HTMLElement): string[] {\n const fiber = getFiber(el);\n if (!fiber) return [];\n\n const hierarchy: string[] = [];\n let current = fiber;\n\n while (current) {\n if (typeof current.type === 'function' || typeof current.type === 'object') {\n const name = typeof current.type === 'function'\n ? current.type.displayName || current.type.name\n : current.type?.displayName || current.type?.render?.displayName || current.type?.render?.name;\n if (name && !name.startsWith('_') && name !== 'Fragment') {\n hierarchy.unshift(name);\n }\n }\n current = current.return;\n }\n\n return hierarchy;\n}\n\nfunction getFiber(el: HTMLElement): any {\n const key = Object.keys(el).find(\n k => k.startsWith('__reactFiber$') || k.startsWith('__reactInternalInstance$')\n );\n return key ? (el as any)[key] : null;\n}\n","import { ElementContext, SourceLocation } from './types';\nimport { extractComponentHierarchy } from './fiber-walker';\n\nconst STYLE_PROPERTIES = [\n 'padding', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft',\n 'margin', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft',\n 'backgroundColor', 'color', 'fontSize', 'fontWeight', 'fontFamily',\n 'borderRadius', 'display', 'flexDirection', 'justifyContent', 'alignItems',\n 'gap', 'width', 'height', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight',\n 'overflow', 'position', 'zIndex', 'opacity', 'border', 'boxShadow',\n 'lineHeight', 'letterSpacing', 'textAlign',\n];\n\nexport function extractSource(el: HTMLElement): SourceLocation | null {\n const file = el.getAttribute('data-source-file');\n const line = el.getAttribute('data-source-line');\n const col = el.getAttribute('data-source-col');\n if (!file || !line) return null;\n return {\n file,\n line: parseInt(line, 10),\n col: parseInt(col || '0', 10),\n component: el.getAttribute('data-source-component') || undefined,\n };\n}\n\nexport function extractContext(el: HTMLElement): ElementContext {\n const computed = getComputedStyle(el);\n const rect = el.getBoundingClientRect();\n const styles: Record<string, string> = {};\n for (const prop of STYLE_PROPERTIES) {\n const value = computed.getPropertyValue(\n prop.replace(/[A-Z]/g, m => '-' + m.toLowerCase())\n );\n if (value && value !== 'none' && value !== 'normal' && value !== 'auto' && value !== '0px' && value !== 'rgba(0, 0, 0, 0)') {\n styles[prop] = value;\n }\n }\n\n return {\n source: extractSource(el),\n tagName: el.tagName.toLowerCase(),\n classes: typeof el.className === 'string' ? el.className : '',\n computedStyles: styles,\n dimensions: { width: rect.width, height: rect.height, x: rect.x, y: rect.y },\n componentHierarchy: extractComponentHierarchy(el),\n url: window.location.href,\n };\n}\n","export async function captureElementScreenshot(el: HTMLElement): Promise<string | undefined> {\n try {\n // Use native canvas approach - works well for most elements\n // without requiring external dependencies like html2canvas\n const rect = el.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) return undefined;\n\n const canvas = document.createElement('canvas');\n const dpr = window.devicePixelRatio || 1;\n const padding = 8; // visual padding around element\n\n const captureWidth = Math.ceil(rect.width + padding * 2);\n const captureHeight = Math.ceil(rect.height + padding * 2);\n\n canvas.width = captureWidth * dpr;\n canvas.height = captureHeight * dpr;\n canvas.style.width = captureWidth + 'px';\n canvas.style.height = captureHeight + 'px';\n\n const ctx = canvas.getContext('2d');\n if (!ctx) return undefined;\n\n ctx.scale(dpr, dpr);\n\n // Try using html-to-image approach via SVG foreignObject\n const screenshot = await captureViaSvgForeignObject(el, rect, ctx, canvas, padding);\n if (screenshot) return screenshot;\n\n // Fallback: capture visible viewport area containing the element\n return await captureViaRange(el, rect, canvas, ctx, padding);\n } catch {\n return undefined;\n }\n}\n\nasync function captureViaSvgForeignObject(\n el: HTMLElement,\n rect: DOMRect,\n ctx: CanvasRenderingContext2D,\n canvas: HTMLCanvasElement,\n padding: number,\n): Promise<string | undefined> {\n try {\n // Clone the element to avoid modifying the original\n const clone = el.cloneNode(true) as HTMLElement;\n\n // Copy computed styles inline\n copyComputedStyles(el, clone);\n\n const width = Math.ceil(rect.width + padding * 2);\n const height = Math.ceil(rect.height + padding * 2);\n\n const svgNs = 'http://www.w3.org/2000/svg';\n const svg = document.createElementNS(svgNs, 'svg');\n svg.setAttribute('width', String(width));\n svg.setAttribute('height', String(height));\n svg.setAttribute('xmlns', svgNs);\n\n const foreignObject = document.createElementNS(svgNs, 'foreignObject');\n foreignObject.setAttribute('width', '100%');\n foreignObject.setAttribute('height', '100%');\n\n const container = document.createElement('div');\n container.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml');\n container.style.cssText = `\n width: ${width}px;\n height: ${height}px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: white;\n padding: ${padding}px;\n box-sizing: border-box;\n `;\n container.appendChild(clone);\n foreignObject.appendChild(container);\n svg.appendChild(foreignObject);\n\n const svgString = new XMLSerializer().serializeToString(svg);\n const svgBlob = new Blob([svgString], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(svgBlob);\n\n return new Promise<string | undefined>((resolve) => {\n const img = new Image();\n img.onload = () => {\n ctx.drawImage(img, 0, 0);\n URL.revokeObjectURL(url);\n try {\n resolve(canvas.toDataURL('image/png'));\n } catch {\n resolve(undefined);\n }\n };\n img.onerror = () => {\n URL.revokeObjectURL(url);\n resolve(undefined);\n };\n img.src = url;\n });\n } catch {\n return undefined;\n }\n}\n\nasync function captureViaRange(\n _el: HTMLElement,\n rect: DOMRect,\n canvas: HTMLCanvasElement,\n ctx: CanvasRenderingContext2D,\n padding: number,\n): Promise<string | undefined> {\n // Fallback: draw a placeholder with element info\n try {\n const width = canvas.width / (window.devicePixelRatio || 1);\n const height = canvas.height / (window.devicePixelRatio || 1);\n\n ctx.fillStyle = '#f8fafc';\n ctx.fillRect(0, 0, width, height);\n ctx.strokeStyle = '#3b82f6';\n ctx.lineWidth = 2;\n ctx.strokeRect(padding, padding, rect.width, rect.height);\n\n ctx.fillStyle = '#64748b';\n ctx.font = '11px -apple-system, BlinkMacSystemFont, sans-serif';\n ctx.fillText(\n `${Math.round(rect.width)} x ${Math.round(rect.height)}px`,\n padding + 4,\n padding + rect.height / 2 + 4,\n );\n\n return canvas.toDataURL('image/png');\n } catch {\n return undefined;\n }\n}\n\nfunction copyComputedStyles(source: HTMLElement, target: HTMLElement): void {\n const computed = getComputedStyle(source);\n const important = [\n 'display', 'width', 'height', 'padding', 'margin', 'border',\n 'border-radius', 'background', 'background-color', 'color',\n 'font-size', 'font-weight', 'font-family', 'line-height',\n 'text-align', 'box-shadow', 'opacity', 'flex-direction',\n 'justify-content', 'align-items', 'gap', 'overflow',\n ];\n for (const prop of important) {\n target.style.setProperty(prop, computed.getPropertyValue(prop));\n }\n\n // Recurse for children\n const sourceChildren = source.children;\n const targetChildren = target.children;\n for (let i = 0; i < sourceChildren.length && i < targetChildren.length; i++) {\n if (sourceChildren[i] instanceof HTMLElement && targetChildren[i] instanceof HTMLElement) {\n copyComputedStyles(sourceChildren[i] as HTMLElement, targetChildren[i] as HTMLElement);\n }\n }\n}\n","import { extractContext } from './context-extractor';\nimport { captureElementScreenshot } from './screenshot';\nimport { ElementContext } from './types';\n\ntype SelectionCallback = (context: ElementContext) => void;\ntype MultiSelectionCallback = (contexts: ElementContext[]) => void;\n\nexport function createSelectionHandler(opts: {\n onHover: (el: HTMLElement | null) => void;\n onSelect: SelectionCallback;\n onMultiSelect?: MultiSelectionCallback;\n onSelectionChange?: (count: number) => void;\n}) {\n let isActive = false;\n let selectedEl: HTMLElement | null = null;\n const multiSelected: Set<HTMLElement> = new Set();\n\n function handleMouseMove(e: MouseEvent) {\n if (!isActive) return;\n const target = e.target as HTMLElement;\n if (target.id === 'ui-context-host' || target.id === 'ui-context-toast' || target.closest('#ui-context-host')) return;\n opts.onHover(target);\n }\n\n function handleClick(e: MouseEvent) {\n if (!isActive) return;\n e.preventDefault();\n e.stopPropagation();\n\n const target = e.target as HTMLElement;\n if (target.id === 'ui-context-host' || target.closest('#ui-context-host')) return;\n\n // Shift+Click: add to multi-selection\n if (e.shiftKey) {\n if (multiSelected.has(target)) {\n multiSelected.delete(target);\n target.style.outline = '';\n } else {\n multiSelected.add(target);\n target.style.outline = '2px dashed #f59e0b';\n }\n opts.onSelectionChange?.(multiSelected.size);\n return;\n }\n\n selectedEl = target;\n const context = extractContext(target);\n\n captureElementScreenshot(target).then(screenshot => {\n if (screenshot) context.screenshotDataUrl = screenshot;\n opts.onSelect(context);\n });\n }\n\n return {\n activate() {\n isActive = true;\n document.addEventListener('mousemove', handleMouseMove, true);\n document.addEventListener('click', handleClick, true);\n document.body.style.cursor = 'crosshair';\n },\n deactivate() {\n isActive = false;\n selectedEl = null;\n // Clear multi-selection outlines\n for (const el of multiSelected) {\n el.style.outline = '';\n }\n multiSelected.clear();\n document.removeEventListener('mousemove', handleMouseMove, true);\n document.removeEventListener('click', handleClick, true);\n document.body.style.cursor = '';\n opts.onHover(null);\n },\n get isActive() { return isActive; },\n get selectedElement() { return selectedEl; },\n get multiSelectedElements() { return multiSelected; },\n get multiSelectedCount() { return multiSelected.size; },\n\n async captureMultiSelection(): Promise<ElementContext[]> {\n const contexts: ElementContext[] = [];\n for (const el of multiSelected) {\n const ctx = extractContext(el);\n const screenshot = await captureElementScreenshot(el);\n if (screenshot) ctx.screenshotDataUrl = screenshot;\n contexts.push(ctx);\n }\n return contexts;\n },\n\n clearMultiSelection() {\n for (const el of multiSelected) {\n el.style.outline = '';\n }\n multiSelected.clear();\n opts.onSelectionChange?.(0);\n },\n };\n}\n","import { ElementContext } from './types';\n\nconst DEFAULT_SERVER_PORT = 19638;\n\nlet serverUrl = '';\n\nexport function initTransport(url?: string) {\n serverUrl = url || `http://${location.hostname}:${DEFAULT_SERVER_PORT}`;\n}\n\nexport function sendContext(context: ElementContext | ElementContext[]): Promise<boolean> {\n return new Promise((resolve) => {\n try {\n // Strategy 1: Vite HMR WebSocket (for Vite projects)\n if (typeof import.meta !== 'undefined' && (import.meta as any).hot) {\n (import.meta as any).hot.send('ui-context:capture', context);\n resolve(true);\n return;\n }\n\n // Strategy 2: HTTP POST to standalone context server (for Next.js projects)\n fetch(`${serverUrl}/capture`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(context),\n })\n .then((res) => res.json())\n .then((result) => resolve(result.success === true))\n .catch(() => resolve(false));\n } catch {\n resolve(false);\n }\n });\n}\n","const STORAGE_KEY = 'ui-context-kit-onboarding-dismissed';\n\nexport function showOnboarding(shortcut: string): void {\n // Don't show if already dismissed\n try {\n if (localStorage.getItem(STORAGE_KEY)) return;\n } catch {\n return; // localStorage not available\n }\n\n const host = document.createElement('div');\n host.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483646;';\n document.body.appendChild(host);\n\n const shadow = host.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = `\n .banner {\n position: fixed;\n bottom: 20px;\n left: 50%;\n transform: translateX(-50%);\n background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);\n border: 1px solid #334155;\n border-radius: 12px;\n padding: 12px 20px;\n display: flex;\n gap: 12px;\n align-items: center;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 8px 32px rgba(0,0,0,0.4);\n animation: slideUp 0.4s ease;\n max-width: 480px;\n }\n @keyframes slideUp {\n from { opacity: 0; transform: translateX(-50%) translateY(20px); }\n to { opacity: 1; transform: translateX(-50%) translateY(0); }\n }\n .icon {\n font-size: 20px;\n flex-shrink: 0;\n }\n .text {\n color: #e2e8f0;\n font-size: 13px;\n line-height: 1.4;\n }\n .text strong {\n color: #60a5fa;\n }\n .kbd {\n display: inline-block;\n background: #334155;\n color: #e2e8f0;\n padding: 1px 6px;\n border-radius: 4px;\n font-size: 12px;\n font-family: monospace;\n border: 1px solid #475569;\n }\n .close-btn {\n background: none;\n border: none;\n color: #64748b;\n cursor: pointer;\n padding: 4px;\n font-size: 16px;\n flex-shrink: 0;\n }\n .close-btn:hover { color: #94a3b8; }\n `;\n shadow.appendChild(style);\n\n const shortcutDisplay = shortcut.split('+').map(k =>\n k.charAt(0).toUpperCase() + k.slice(1)\n ).join(' + ');\n\n const banner = document.createElement('div');\n banner.className = 'banner';\n banner.innerHTML = `\n <span class=\"icon\">\\u{1F3AF}</span>\n <span class=\"text\">\n <strong>UI Context Kit</strong> is ready!\n Press <kbd class=\"kbd\">${shortcutDisplay}</kbd> to select any UI element and capture its context for AI.\n Use <strong>Shift+Click</strong> for multi-select, <strong>Ctrl+Shift+F</strong> to freeze state.\n </span>\n <button class=\"close-btn\" title=\"Dismiss\">\\u2715</button>\n `;\n shadow.appendChild(banner);\n\n banner.querySelector('.close-btn')!.addEventListener('click', () => {\n host.remove();\n try {\n localStorage.setItem(STORAGE_KEY, '1');\n } catch { /* ignore */ }\n });\n\n // Auto-dismiss after 8 seconds\n setTimeout(() => {\n if (host.parentNode) {\n banner.style.transition = 'opacity 0.3s ease';\n banner.style.opacity = '0';\n setTimeout(() => host.remove(), 300);\n }\n }, 8000);\n}\n","import { createOverlay } from './ui/overlay';\nimport { showToast } from './ui/toast';\nimport { createToolbar } from './ui/toolbar';\nimport { createSelectionHandler } from './selection';\nimport { sendContext, initTransport } from './transport';\nimport { extractContext, extractSource } from './context-extractor';\nimport { showOnboarding } from './ui/onboarding';\nimport type { ElementContext } from './types';\n\nexport type { ElementContext, SourceLocation } from './types';\n\nexport interface UIContextOptions {\n shortcut?: string;\n wsUrl?: string;\n}\n\nexport function initUIContext(options: UIContextOptions = {}) {\n const { shortcut = 'alt+x' } = options;\n\n initTransport(options.wsUrl);\n\n let overlay: ReturnType<typeof createOverlay> | null = null;\n let toolbar: ReturnType<typeof createToolbar> | null = null;\n let isFrozen = false;\n let frozenObservers: MutationObserver[] = [];\n\n const selection = createSelectionHandler({\n onHover(el) {\n if (!el) {\n overlay?.highlight(null);\n return;\n }\n const rect = el.getBoundingClientRect();\n const source = extractSource(el);\n const label = source\n ? `${source.component || el.tagName.toLowerCase()} \\u00b7 ${source.file}:${source.line}`\n : el.tagName.toLowerCase();\n overlay?.highlight(rect, label);\n },\n async onSelect(context: ElementContext) {\n showToast('Capturing context...');\n const success = await sendContext(context);\n if (success) {\n showToast('Context captured!');\n } else {\n showToast('Failed to send context. Is the dev server running?');\n }\n },\n onSelectionChange(count) {\n toolbar?.updateBadge(count);\n },\n });\n\n function activate() {\n if (selection.isActive) return;\n overlay = createOverlay();\n toolbar = createToolbar({\n onCapture() {\n if (selection.selectedElement) {\n const context = extractContext(selection.selectedElement);\n sendContext(context);\n }\n },\n async onCaptureAll() {\n if (selection.multiSelectedCount === 0) {\n showToast('No elements selected. Use Shift+Click to select multiple.');\n return;\n }\n showToast(`Capturing ${selection.multiSelectedCount} elements...`);\n const contexts = await selection.captureMultiSelection();\n const success = await sendContext(contexts);\n if (success) {\n showToast(`${contexts.length} elements captured!`);\n selection.clearMultiSelection();\n } else {\n showToast('Failed to send context. Is the dev server running?');\n }\n },\n onClose() { deactivate(); },\n onFreeze() { toggleFreeze(); },\n });\n selection.activate();\n showToast('UI Context active \\u2014 click to capture, Shift+click for multi-select');\n }\n\n function deactivate() {\n if (isFrozen) unfreezeDOM();\n selection.deactivate();\n overlay?.destroy();\n toolbar?.destroy();\n overlay = null;\n toolbar = null;\n }\n\n function toggleFreeze() {\n if (isFrozen) {\n unfreezeDOM();\n showToast('DOM unfrozen');\n } else {\n freezeDOM();\n showToast('DOM frozen \\u2014 hover states preserved');\n }\n toolbar?.updateFreezeState(isFrozen);\n }\n\n function freezeDOM() {\n isFrozen = true;\n // Disconnect all existing MutationObservers by creating a blocking one\n // This prevents DOM updates (dropdowns closing, tooltips hiding, etc.)\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n // Revert added/removed nodes\n for (const node of mutation.addedNodes) {\n if (node instanceof HTMLElement && !node.id?.includes('ui-context')) {\n node.remove();\n }\n }\n // Revert attribute changes\n if (mutation.type === 'attributes' && mutation.target instanceof HTMLElement) {\n if (!mutation.target.id?.includes('ui-context')) {\n const old = mutation.oldValue;\n if (old !== null) {\n mutation.target.setAttribute(mutation.attributeName!, old);\n }\n }\n }\n }\n });\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeOldValue: true,\n });\n frozenObservers.push(observer);\n }\n\n function unfreezeDOM() {\n isFrozen = false;\n for (const obs of frozenObservers) {\n obs.disconnect();\n }\n frozenObservers = [];\n }\n\n // Register keyboard shortcuts\n document.addEventListener('keydown', (e) => {\n // Main shortcut (Alt+X)\n const keys = shortcut.split('+');\n const needsAlt = keys.includes('alt');\n const needsCtrl = keys.includes('ctrl');\n const needsShift = keys.includes('shift');\n const mainKey = keys[keys.length - 1].toLowerCase();\n const mainCode = /^[a-z]$/.test(mainKey) ? 'Key' + mainKey.toUpperCase() : /^[0-9]$/.test(mainKey) ? 'Digit' + mainKey : '';\n\n if (\n e.altKey === needsAlt &&\n e.ctrlKey === needsCtrl &&\n e.shiftKey === needsShift &&\n (mainCode ? e.code === mainCode : e.key.toLowerCase() === mainKey)\n ) {\n e.preventDefault();\n if (selection.isActive) {\n deactivate();\n } else {\n activate();\n }\n return;\n }\n\n // Freeze shortcut: Ctrl+Shift+F (only when active)\n if (selection.isActive && e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'f') {\n e.preventDefault();\n toggleFreeze();\n }\n });\n\n // Show onboarding on first use\n showOnboarding(shortcut);\n\n return { activate, deactivate };\n}\n","import { initUIContext } from './index';\n\n// Auto-initialize when loaded\nif (typeof window !== 'undefined') {\n (window as any).__uiContext = initUIContext();\n}\n"],"mappings":";;;AAAA,IAAI,SAAgC;AACpC,IAAI,aAAgC;AACpC,IAAI,cAAqC;AAElC,SAAS,gBAAoG;AAClH,WAAS,SAAS,cAAc,KAAK;AACrC,SAAO,KAAK;AACZ,SAAO,MAAM,UAAU;AACvB,WAAS,KAAK,YAAY,MAAM;AAEhC,eAAa,OAAO,aAAa,EAAE,MAAM,OAAO,CAAC;AAEjD,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAwBpB,aAAW,YAAY,KAAK;AAE5B,gBAAc,SAAS,cAAc,KAAK;AAC1C,cAAY,YAAY;AACxB,cAAY,MAAM,UAAU;AAE5B,QAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,UAAQ,YAAY;AACpB,cAAY,YAAY,OAAO;AAE/B,aAAW,YAAY,WAAW;AAElC,SAAO;AAAA,IACL,UAAU,MAAsB,OAAgB;AAC9C,UAAI,CAAC,QAAQ,CAAC,aAAa;AACzB,YAAI,YAAa,aAAY,MAAM,UAAU;AAC7C;AAAA,MACF;AACA,kBAAY,MAAM,UAAU;AAC5B,kBAAY,MAAM,MAAM,KAAK,MAAM;AACnC,kBAAY,MAAM,OAAO,KAAK,OAAO;AACrC,kBAAY,MAAM,QAAQ,KAAK,QAAQ;AACvC,kBAAY,MAAM,SAAS,KAAK,SAAS;AACzC,YAAM,MAAM,YAAY,cAAc,kBAAkB;AACxD,UAAI,OAAO,OAAO;AAChB,YAAI,cAAc;AAClB,YAAI,MAAM,UAAU;AAAA,MACtB,WAAW,KAAK;AACd,YAAI,MAAM,UAAU;AAAA,MACtB;AAAA,IACF;AAAA,IACA,UAAU;AACR,cAAQ,OAAO;AACf,eAAS;AACT,mBAAa;AACb,oBAAc;AAAA,IAChB;AAAA,EACF;AACF;;;AC3EA,IAAI,iBAAwC;AAC5C,IAAI,cAAiC;AAErC,SAAS,kBAAkB;AACzB,MAAI,eAAgB;AACpB,mBAAiB,SAAS,cAAc,KAAK;AAC7C,iBAAe,KAAK;AACpB,iBAAe,MAAM,UAAU;AAC/B,WAAS,KAAK,YAAY,cAAc;AACxC,gBAAc,eAAe,aAAa,EAAE,MAAM,OAAO,CAAC;AAC1D,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmBpB,cAAY,YAAY,KAAK;AAC/B;AAEO,SAAS,UAAU,SAAiB,WAAW,KAAM;AAC1D,kBAAgB;AAChB,MAAI,CAAC,YAAa;AAClB,QAAM,KAAK,SAAS,cAAc,KAAK;AACvC,KAAG,YAAY;AACf,KAAG,cAAc;AACjB,cAAY,YAAY,EAAE;AAC1B,aAAW,MAAM,GAAG,OAAO,GAAG,QAAQ;AACxC;;;ACzCO,SAAS,cAAc,MAKmG;AAC/H,QAAM,OAAO,SAAS,cAAc,KAAK;AACzC,OAAK,MAAM,UAAU;AACrB,WAAS,KAAK,YAAY,IAAI;AAE9B,QAAM,SAAS,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AACjD,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM,cAAc;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAwDpB,SAAO,YAAY,KAAK;AAExB,QAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,UAAQ,YAAY;AACpB,UAAQ,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASpB,SAAO,YAAY,OAAO;AAE1B,QAAM,aAAa,QAAQ,cAAc,UAAU;AACnD,QAAM,gBAAgB,QAAQ,cAAc,cAAc;AAC1D,QAAM,YAAY,QAAQ,cAAc,SAAS;AACjD,QAAM,WAAW,QAAQ,cAAc,QAAQ;AAC/C,QAAM,QAAQ,QAAQ,cAAc,QAAQ;AAE5C,aAAW,iBAAiB,SAAS,KAAK,SAAS;AACnD,gBAAc,iBAAiB,SAAS,MAAM,KAAK,eAAe,CAAC;AACnE,YAAU,iBAAiB,SAAS,MAAM,KAAK,WAAW,CAAC;AAC3D,WAAS,iBAAiB,SAAS,KAAK,OAAO;AAE/C,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,UAAU;AAAE,WAAK,OAAO;AAAA,IAAG;AAAA,IAC3B,YAAY,OAAe;AACzB,UAAI,QAAQ,GAAG;AACb,sBAAc,MAAM,UAAU;AAC9B,cAAM,cAAc,OAAO,KAAK;AAChC,cAAM,UAAU,OAAO,QAAQ;AAAA,MACjC,OAAO;AACL,sBAAc,MAAM,UAAU;AAC9B,cAAM,UAAU,IAAI,QAAQ;AAAA,MAC9B;AAAA,IACF;AAAA,IACA,kBAAkB,QAAiB;AACjC,UAAI,QAAQ;AACV,kBAAU,UAAU,IAAI,QAAQ;AAChC,kBAAU,cAAc;AAAA,MAC1B,OAAO;AACL,kBAAU,UAAU,OAAO,QAAQ;AACnC,kBAAU,cAAc;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AACF;;;ACrHO,SAAS,0BAA0B,IAA2B;AACnE,QAAM,QAAQ,SAAS,EAAE;AACzB,MAAI,CAAC,MAAO,QAAO,CAAC;AAEpB,QAAM,YAAsB,CAAC;AAC7B,MAAI,UAAU;AAEd,SAAO,SAAS;AACd,QAAI,OAAO,QAAQ,SAAS,cAAc,OAAO,QAAQ,SAAS,UAAU;AAC1E,YAAM,OAAO,OAAO,QAAQ,SAAS,aACjC,QAAQ,KAAK,eAAe,QAAQ,KAAK,OACzC,QAAQ,MAAM,eAAe,QAAQ,MAAM,QAAQ,eAAe,QAAQ,MAAM,QAAQ;AAC5F,UAAI,QAAQ,CAAC,KAAK,WAAW,GAAG,KAAK,SAAS,YAAY;AACxD,kBAAU,QAAQ,IAAI;AAAA,MACxB;AAAA,IACF;AACA,cAAU,QAAQ;AAAA,EACpB;AAEA,SAAO;AACT;AAEA,SAAS,SAAS,IAAsB;AACtC,QAAM,MAAM,OAAO,KAAK,EAAE,EAAE;AAAA,IAC1B,OAAK,EAAE,WAAW,eAAe,KAAK,EAAE,WAAW,0BAA0B;AAAA,EAC/E;AACA,SAAO,MAAO,GAAW,GAAG,IAAI;AAClC;;;ACxBA,IAAM,mBAAmB;AAAA,EACvB;AAAA,EAAW;AAAA,EAAc;AAAA,EAAgB;AAAA,EAAiB;AAAA,EAC1D;AAAA,EAAU;AAAA,EAAa;AAAA,EAAe;AAAA,EAAgB;AAAA,EACtD;AAAA,EAAmB;AAAA,EAAS;AAAA,EAAY;AAAA,EAAc;AAAA,EACtD;AAAA,EAAgB;AAAA,EAAW;AAAA,EAAiB;AAAA,EAAkB;AAAA,EAC9D;AAAA,EAAO;AAAA,EAAS;AAAA,EAAU;AAAA,EAAY;AAAA,EAAa;AAAA,EAAY;AAAA,EAC/D;AAAA,EAAY;AAAA,EAAY;AAAA,EAAU;AAAA,EAAW;AAAA,EAAU;AAAA,EACvD;AAAA,EAAc;AAAA,EAAiB;AACjC;AAEO,SAAS,cAAc,IAAwC;AACpE,QAAM,OAAO,GAAG,aAAa,kBAAkB;AAC/C,QAAM,OAAO,GAAG,aAAa,kBAAkB;AAC/C,QAAM,MAAM,GAAG,aAAa,iBAAiB;AAC7C,MAAI,CAAC,QAAQ,CAAC,KAAM,QAAO;AAC3B,SAAO;AAAA,IACL;AAAA,IACA,MAAM,SAAS,MAAM,EAAE;AAAA,IACvB,KAAK,SAAS,OAAO,KAAK,EAAE;AAAA,IAC5B,WAAW,GAAG,aAAa,uBAAuB,KAAK;AAAA,EACzD;AACF;AAEO,SAAS,eAAe,IAAiC;AAC9D,QAAM,WAAW,iBAAiB,EAAE;AACpC,QAAM,OAAO,GAAG,sBAAsB;AACtC,QAAM,SAAiC,CAAC;AACxC,aAAW,QAAQ,kBAAkB;AACnC,UAAM,QAAQ,SAAS;AAAA,MACrB,KAAK,QAAQ,UAAU,OAAK,MAAM,EAAE,YAAY,CAAC;AAAA,IACnD;AACA,QAAI,SAAS,UAAU,UAAU,UAAU,YAAY,UAAU,UAAU,UAAU,SAAS,UAAU,oBAAoB;AAC1H,aAAO,IAAI,IAAI;AAAA,IACjB;AAAA,EACF;AAEA,SAAO;AAAA,IACL,QAAQ,cAAc,EAAE;AAAA,IACxB,SAAS,GAAG,QAAQ,YAAY;AAAA,IAChC,SAAS,OAAO,GAAG,cAAc,WAAW,GAAG,YAAY;AAAA,IAC3D,gBAAgB;AAAA,IAChB,YAAY,EAAE,OAAO,KAAK,OAAO,QAAQ,KAAK,QAAQ,GAAG,KAAK,GAAG,GAAG,KAAK,EAAE;AAAA,IAC3E,oBAAoB,0BAA0B,EAAE;AAAA,IAChD,KAAK,OAAO,SAAS;AAAA,EACvB;AACF;;;AChDA,eAAsB,yBAAyB,IAA8C;AAC3F,MAAI;AAGF,UAAM,OAAO,GAAG,sBAAsB;AACtC,QAAI,KAAK,UAAU,KAAK,KAAK,WAAW,EAAG,QAAO;AAElD,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,UAAM,MAAM,OAAO,oBAAoB;AACvC,UAAM,UAAU;AAEhB,UAAM,eAAe,KAAK,KAAK,KAAK,QAAQ,UAAU,CAAC;AACvD,UAAM,gBAAgB,KAAK,KAAK,KAAK,SAAS,UAAU,CAAC;AAEzD,WAAO,QAAQ,eAAe;AAC9B,WAAO,SAAS,gBAAgB;AAChC,WAAO,MAAM,QAAQ,eAAe;AACpC,WAAO,MAAM,SAAS,gBAAgB;AAEtC,UAAM,MAAM,OAAO,WAAW,IAAI;AAClC,QAAI,CAAC,IAAK,QAAO;AAEjB,QAAI,MAAM,KAAK,GAAG;AAGlB,UAAM,aAAa,MAAM,2BAA2B,IAAI,MAAM,KAAK,QAAQ,OAAO;AAClF,QAAI,WAAY,QAAO;AAGvB,WAAO,MAAM,gBAAgB,IAAI,MAAM,QAAQ,KAAK,OAAO;AAAA,EAC7D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,2BACb,IACA,MACA,KACA,QACA,SAC6B;AAC7B,MAAI;AAEF,UAAM,QAAQ,GAAG,UAAU,IAAI;AAG/B,uBAAmB,IAAI,KAAK;AAE5B,UAAM,QAAQ,KAAK,KAAK,KAAK,QAAQ,UAAU,CAAC;AAChD,UAAM,SAAS,KAAK,KAAK,KAAK,SAAS,UAAU,CAAC;AAElD,UAAM,QAAQ;AACd,UAAM,MAAM,SAAS,gBAAgB,OAAO,KAAK;AACjD,QAAI,aAAa,SAAS,OAAO,KAAK,CAAC;AACvC,QAAI,aAAa,UAAU,OAAO,MAAM,CAAC;AACzC,QAAI,aAAa,SAAS,KAAK;AAE/B,UAAM,gBAAgB,SAAS,gBAAgB,OAAO,eAAe;AACrE,kBAAc,aAAa,SAAS,MAAM;AAC1C,kBAAc,aAAa,UAAU,MAAM;AAE3C,UAAM,YAAY,SAAS,cAAc,KAAK;AAC9C,cAAU,aAAa,SAAS,8BAA8B;AAC9D,cAAU,MAAM,UAAU;AAAA,eACf,KAAK;AAAA,gBACJ,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA,iBAKL,OAAO;AAAA;AAAA;AAGpB,cAAU,YAAY,KAAK;AAC3B,kBAAc,YAAY,SAAS;AACnC,QAAI,YAAY,aAAa;AAE7B,UAAM,YAAY,IAAI,cAAc,EAAE,kBAAkB,GAAG;AAC3D,UAAM,UAAU,IAAI,KAAK,CAAC,SAAS,GAAG,EAAE,MAAM,8BAA8B,CAAC;AAC7E,UAAM,MAAM,IAAI,gBAAgB,OAAO;AAEvC,WAAO,IAAI,QAA4B,CAAC,YAAY;AAClD,YAAM,MAAM,IAAI,MAAM;AACtB,UAAI,SAAS,MAAM;AACjB,YAAI,UAAU,KAAK,GAAG,CAAC;AACvB,YAAI,gBAAgB,GAAG;AACvB,YAAI;AACF,kBAAQ,OAAO,UAAU,WAAW,CAAC;AAAA,QACvC,QAAQ;AACN,kBAAQ,MAAS;AAAA,QACnB;AAAA,MACF;AACA,UAAI,UAAU,MAAM;AAClB,YAAI,gBAAgB,GAAG;AACvB,gBAAQ,MAAS;AAAA,MACnB;AACA,UAAI,MAAM;AAAA,IACZ,CAAC;AAAA,EACH,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,gBACb,KACA,MACA,QACA,KACA,SAC6B;AAE7B,MAAI;AACF,UAAM,QAAQ,OAAO,SAAS,OAAO,oBAAoB;AACzD,UAAM,SAAS,OAAO,UAAU,OAAO,oBAAoB;AAE3D,QAAI,YAAY;AAChB,QAAI,SAAS,GAAG,GAAG,OAAO,MAAM;AAChC,QAAI,cAAc;AAClB,QAAI,YAAY;AAChB,QAAI,WAAW,SAAS,SAAS,KAAK,OAAO,KAAK,MAAM;AAExD,QAAI,YAAY;AAChB,QAAI,OAAO;AACX,QAAI;AAAA,MACF,GAAG,KAAK,MAAM,KAAK,KAAK,CAAC,MAAM,KAAK,MAAM,KAAK,MAAM,CAAC;AAAA,MACtD,UAAU;AAAA,MACV,UAAU,KAAK,SAAS,IAAI;AAAA,IAC9B;AAEA,WAAO,OAAO,UAAU,WAAW;AAAA,EACrC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,mBAAmB,QAAqB,QAA2B;AAC1E,QAAM,WAAW,iBAAiB,MAAM;AACxC,QAAM,YAAY;AAAA,IAChB;AAAA,IAAW;AAAA,IAAS;AAAA,IAAU;AAAA,IAAW;AAAA,IAAU;AAAA,IACnD;AAAA,IAAiB;AAAA,IAAc;AAAA,IAAoB;AAAA,IACnD;AAAA,IAAa;AAAA,IAAe;AAAA,IAAe;AAAA,IAC3C;AAAA,IAAc;AAAA,IAAc;AAAA,IAAW;AAAA,IACvC;AAAA,IAAmB;AAAA,IAAe;AAAA,IAAO;AAAA,EAC3C;AACA,aAAW,QAAQ,WAAW;AAC5B,WAAO,MAAM,YAAY,MAAM,SAAS,iBAAiB,IAAI,CAAC;AAAA,EAChE;AAGA,QAAM,iBAAiB,OAAO;AAC9B,QAAM,iBAAiB,OAAO;AAC9B,WAAS,IAAI,GAAG,IAAI,eAAe,UAAU,IAAI,eAAe,QAAQ,KAAK;AAC3E,QAAI,eAAe,CAAC,aAAa,eAAe,eAAe,CAAC,aAAa,aAAa;AACxF,yBAAmB,eAAe,CAAC,GAAkB,eAAe,CAAC,CAAgB;AAAA,IACvF;AAAA,EACF;AACF;;;ACtJO,SAAS,uBAAuB,MAKpC;AACD,MAAI,WAAW;AACf,MAAI,aAAiC;AACrC,QAAM,gBAAkC,oBAAI,IAAI;AAEhD,WAAS,gBAAgB,GAAe;AACtC,QAAI,CAAC,SAAU;AACf,UAAM,SAAS,EAAE;AACjB,QAAI,OAAO,OAAO,qBAAqB,OAAO,OAAO,sBAAsB,OAAO,QAAQ,kBAAkB,EAAG;AAC/G,SAAK,QAAQ,MAAM;AAAA,EACrB;AAEA,WAAS,YAAY,GAAe;AAClC,QAAI,CAAC,SAAU;AACf,MAAE,eAAe;AACjB,MAAE,gBAAgB;AAElB,UAAM,SAAS,EAAE;AACjB,QAAI,OAAO,OAAO,qBAAqB,OAAO,QAAQ,kBAAkB,EAAG;AAG3E,QAAI,EAAE,UAAU;AACd,UAAI,cAAc,IAAI,MAAM,GAAG;AAC7B,sBAAc,OAAO,MAAM;AAC3B,eAAO,MAAM,UAAU;AAAA,MACzB,OAAO;AACL,sBAAc,IAAI,MAAM;AACxB,eAAO,MAAM,UAAU;AAAA,MACzB;AACA,WAAK,oBAAoB,cAAc,IAAI;AAC3C;AAAA,IACF;AAEA,iBAAa;AACb,UAAM,UAAU,eAAe,MAAM;AAErC,6BAAyB,MAAM,EAAE,KAAK,gBAAc;AAClD,UAAI,WAAY,SAAQ,oBAAoB;AAC5C,WAAK,SAAS,OAAO;AAAA,IACvB,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,WAAW;AACT,iBAAW;AACX,eAAS,iBAAiB,aAAa,iBAAiB,IAAI;AAC5D,eAAS,iBAAiB,SAAS,aAAa,IAAI;AACpD,eAAS,KAAK,MAAM,SAAS;AAAA,IAC/B;AAAA,IACA,aAAa;AACX,iBAAW;AACX,mBAAa;AAEb,iBAAW,MAAM,eAAe;AAC9B,WAAG,MAAM,UAAU;AAAA,MACrB;AACA,oBAAc,MAAM;AACpB,eAAS,oBAAoB,aAAa,iBAAiB,IAAI;AAC/D,eAAS,oBAAoB,SAAS,aAAa,IAAI;AACvD,eAAS,KAAK,MAAM,SAAS;AAC7B,WAAK,QAAQ,IAAI;AAAA,IACnB;AAAA,IACA,IAAI,WAAW;AAAE,aAAO;AAAA,IAAU;AAAA,IAClC,IAAI,kBAAkB;AAAE,aAAO;AAAA,IAAY;AAAA,IAC3C,IAAI,wBAAwB;AAAE,aAAO;AAAA,IAAe;AAAA,IACpD,IAAI,qBAAqB;AAAE,aAAO,cAAc;AAAA,IAAM;AAAA,IAEtD,MAAM,wBAAmD;AACvD,YAAM,WAA6B,CAAC;AACpC,iBAAW,MAAM,eAAe;AAC9B,cAAM,MAAM,eAAe,EAAE;AAC7B,cAAM,aAAa,MAAM,yBAAyB,EAAE;AACpD,YAAI,WAAY,KAAI,oBAAoB;AACxC,iBAAS,KAAK,GAAG;AAAA,MACnB;AACA,aAAO;AAAA,IACT;AAAA,IAEA,sBAAsB;AACpB,iBAAW,MAAM,eAAe;AAC9B,WAAG,MAAM,UAAU;AAAA,MACrB;AACA,oBAAc,MAAM;AACpB,WAAK,oBAAoB,CAAC;AAAA,IAC5B;AAAA,EACF;AACF;;;AClGA;AAEA,IAAM,sBAAsB;AAE5B,IAAI,YAAY;AAET,SAAS,cAAc,KAAc;AAC1C,cAAY,OAAO,UAAU,SAAS,QAAQ,IAAI,mBAAmB;AACvE;AAEO,SAAS,YAAY,SAA8D;AACxF,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,QAAI;AAEF,UAAI,OAAO,gBAAgB,eAAgB,YAAoB,KAAK;AAClE,QAAC,YAAoB,IAAI,KAAK,sBAAsB,OAAO;AAC3D,gBAAQ,IAAI;AACZ;AAAA,MACF;AAGA,YAAM,GAAG,SAAS,YAAY;AAAA,QAC5B,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,OAAO;AAAA,MAC9B,CAAC,EACE,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,EACxB,KAAK,CAAC,WAAW,QAAQ,OAAO,YAAY,IAAI,CAAC,EACjD,MAAM,MAAM,QAAQ,KAAK,CAAC;AAAA,IAC/B,QAAQ;AACN,cAAQ,KAAK;AAAA,IACf;AAAA,EACF,CAAC;AACH;;;ACjCA,IAAM,cAAc;AAEb,SAAS,eAAe,UAAwB;AAErD,MAAI;AACF,QAAI,aAAa,QAAQ,WAAW,EAAG;AAAA,EACzC,QAAQ;AACN;AAAA,EACF;AAEA,QAAM,OAAO,SAAS,cAAc,KAAK;AACzC,OAAK,MAAM,UAAU;AACrB,WAAS,KAAK,YAAY,IAAI;AAE9B,QAAM,SAAS,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AACjD,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM,cAAc;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuDpB,SAAO,YAAY,KAAK;AAExB,QAAM,kBAAkB,SAAS,MAAM,GAAG,EAAE;AAAA,IAAI,OAC9C,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC;AAAA,EACvC,EAAE,KAAK,KAAK;AAEZ,QAAM,SAAS,SAAS,cAAc,KAAK;AAC3C,SAAO,YAAY;AACnB,SAAO,YAAY;AAAA;AAAA;AAAA;AAAA,+BAIU,eAAe;AAAA;AAAA;AAAA;AAAA;AAK5C,SAAO,YAAY,MAAM;AAEzB,SAAO,cAAc,YAAY,EAAG,iBAAiB,SAAS,MAAM;AAClE,SAAK,OAAO;AACZ,QAAI;AACF,mBAAa,QAAQ,aAAa,GAAG;AAAA,IACvC,QAAQ;AAAA,IAAe;AAAA,EACzB,CAAC;AAGD,aAAW,MAAM;AACf,QAAI,KAAK,YAAY;AACnB,aAAO,MAAM,aAAa;AAC1B,aAAO,MAAM,UAAU;AACvB,iBAAW,MAAM,KAAK,OAAO,GAAG,GAAG;AAAA,IACrC;AAAA,EACF,GAAG,GAAI;AACT;;;ACzFO,SAAS,cAAc,UAA4B,CAAC,GAAG;AAC5D,QAAM,EAAE,WAAW,QAAQ,IAAI;AAE/B,gBAAc,QAAQ,KAAK;AAE3B,MAAI,UAAmD;AACvD,MAAI,UAAmD;AACvD,MAAI,WAAW;AACf,MAAI,kBAAsC,CAAC;AAE3C,QAAM,YAAY,uBAAuB;AAAA,IACvC,QAAQ,IAAI;AACV,UAAI,CAAC,IAAI;AACP,iBAAS,UAAU,IAAI;AACvB;AAAA,MACF;AACA,YAAM,OAAO,GAAG,sBAAsB;AACtC,YAAM,SAAS,cAAc,EAAE;AAC/B,YAAM,QAAQ,SACV,GAAG,OAAO,aAAa,GAAG,QAAQ,YAAY,CAAC,SAAW,OAAO,IAAI,IAAI,OAAO,IAAI,KACpF,GAAG,QAAQ,YAAY;AAC3B,eAAS,UAAU,MAAM,KAAK;AAAA,IAChC;AAAA,IACA,MAAM,SAAS,SAAyB;AACtC,gBAAU,sBAAsB;AAChC,YAAM,UAAU,MAAM,YAAY,OAAO;AACzC,UAAI,SAAS;AACX,kBAAU,mBAAmB;AAAA,MAC/B,OAAO;AACL,kBAAU,oDAAoD;AAAA,MAChE;AAAA,IACF;AAAA,IACA,kBAAkB,OAAO;AACvB,eAAS,YAAY,KAAK;AAAA,IAC5B;AAAA,EACF,CAAC;AAED,WAAS,WAAW;AAClB,QAAI,UAAU,SAAU;AACxB,cAAU,cAAc;AACxB,cAAU,cAAc;AAAA,MACtB,YAAY;AACV,YAAI,UAAU,iBAAiB;AAC7B,gBAAM,UAAU,eAAe,UAAU,eAAe;AACxD,sBAAY,OAAO;AAAA,QACrB;AAAA,MACF;AAAA,MACA,MAAM,eAAe;AACnB,YAAI,UAAU,uBAAuB,GAAG;AACtC,oBAAU,2DAA2D;AACrE;AAAA,QACF;AACA,kBAAU,aAAa,UAAU,kBAAkB,cAAc;AACjE,cAAM,WAAW,MAAM,UAAU,sBAAsB;AACvD,cAAM,UAAU,MAAM,YAAY,QAAQ;AAC1C,YAAI,SAAS;AACX,oBAAU,GAAG,SAAS,MAAM,qBAAqB;AACjD,oBAAU,oBAAoB;AAAA,QAChC,OAAO;AACL,oBAAU,oDAAoD;AAAA,QAChE;AAAA,MACF;AAAA,MACA,UAAU;AAAE,mBAAW;AAAA,MAAG;AAAA,MAC1B,WAAW;AAAE,qBAAa;AAAA,MAAG;AAAA,IAC/B,CAAC;AACD,cAAU,SAAS;AACnB,cAAU,yEAAyE;AAAA,EACrF;AAEA,WAAS,aAAa;AACpB,QAAI,SAAU,aAAY;AAC1B,cAAU,WAAW;AACrB,aAAS,QAAQ;AACjB,aAAS,QAAQ;AACjB,cAAU;AACV,cAAU;AAAA,EACZ;AAEA,WAAS,eAAe;AACtB,QAAI,UAAU;AACZ,kBAAY;AACZ,gBAAU,cAAc;AAAA,IAC1B,OAAO;AACL,gBAAU;AACV,gBAAU,0CAA0C;AAAA,IACtD;AACA,aAAS,kBAAkB,QAAQ;AAAA,EACrC;AAEA,WAAS,YAAY;AACnB,eAAW;AAGX,UAAM,WAAW,IAAI,iBAAiB,CAAC,cAAc;AACnD,iBAAW,YAAY,WAAW;AAEhC,mBAAW,QAAQ,SAAS,YAAY;AACtC,cAAI,gBAAgB,eAAe,CAAC,KAAK,IAAI,SAAS,YAAY,GAAG;AACnE,iBAAK,OAAO;AAAA,UACd;AAAA,QACF;AAEA,YAAI,SAAS,SAAS,gBAAgB,SAAS,kBAAkB,aAAa;AAC5E,cAAI,CAAC,SAAS,OAAO,IAAI,SAAS,YAAY,GAAG;AAC/C,kBAAM,MAAM,SAAS;AACrB,gBAAI,QAAQ,MAAM;AAChB,uBAAS,OAAO,aAAa,SAAS,eAAgB,GAAG;AAAA,YAC3D;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AACD,aAAS,QAAQ,SAAS,MAAM;AAAA,MAC9B,WAAW;AAAA,MACX,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,mBAAmB;AAAA,IACrB,CAAC;AACD,oBAAgB,KAAK,QAAQ;AAAA,EAC/B;AAEA,WAAS,cAAc;AACrB,eAAW;AACX,eAAW,OAAO,iBAAiB;AACjC,UAAI,WAAW;AAAA,IACjB;AACA,sBAAkB,CAAC;AAAA,EACrB;AAGA,WAAS,iBAAiB,WAAW,CAAC,MAAM;AAE1C,UAAM,OAAO,SAAS,MAAM,GAAG;AAC/B,UAAM,WAAW,KAAK,SAAS,KAAK;AACpC,UAAM,YAAY,KAAK,SAAS,MAAM;AACtC,UAAM,aAAa,KAAK,SAAS,OAAO;AACxC,UAAM,UAAU,KAAK,KAAK,SAAS,CAAC,EAAE,YAAY;AAClD,UAAM,WAAW,UAAU,KAAK,OAAO,IAAI,QAAQ,QAAQ,YAAY,IAAI,UAAU,KAAK,OAAO,IAAI,UAAU,UAAU;AAEzH,QACE,EAAE,WAAW,YACb,EAAE,YAAY,aACd,EAAE,aAAa,eACd,WAAW,EAAE,SAAS,WAAW,EAAE,IAAI,YAAY,MAAM,UAC1D;AACA,QAAE,eAAe;AACjB,UAAI,UAAU,UAAU;AACtB,mBAAW;AAAA,MACb,OAAO;AACL,iBAAS;AAAA,MACX;AACA;AAAA,IACF;AAGA,QAAI,UAAU,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,IAAI,YAAY,MAAM,KAAK;AAChF,QAAE,eAAe;AACjB,mBAAa;AAAA,IACf;AAAA,EACF,CAAC;AAGD,iBAAe,QAAQ;AAEvB,SAAO,EAAE,UAAU,WAAW;AAChC;;;AClLA,IAAI,OAAO,WAAW,aAAa;AACjC,EAAC,OAAe,cAAc,cAAc;AAC9C;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/ui/overlay.ts","../src/ui/toast.ts","../src/ui/toolbar.ts","../src/fiber-walker.ts","../src/context-extractor.ts","../src/screenshot.ts","../src/selection.ts","../src/transport.ts","../src/ui/onboarding.ts","../src/index.ts","../src/inject.ts"],"sourcesContent":["let hostEl: HTMLDivElement | null = null;\nlet shadowRoot: ShadowRoot | null = null;\nlet highlightEl: HTMLDivElement | null = null;\n\nexport function createOverlay(): { highlight: (rect: DOMRect | null, label?: string) => void; destroy: () => void } {\n hostEl = document.createElement('div');\n hostEl.id = 'ui-context-host';\n hostEl.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;pointer-events:none;';\n document.body.appendChild(hostEl);\n\n shadowRoot = hostEl.attachShadow({ mode: 'open' });\n\n const style = document.createElement('style');\n style.textContent = `\n .highlight {\n position: fixed;\n border: 2px solid #3b82f6;\n background: rgba(59, 130, 246, 0.1);\n pointer-events: none;\n transition: all 0.1s ease;\n border-radius: 4px;\n z-index: 2147483647;\n }\n .highlight-label {\n position: absolute;\n top: -24px;\n left: -2px;\n background: #3b82f6;\n color: white;\n font-size: 11px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n padding: 2px 6px;\n border-radius: 3px 3px 0 0;\n white-space: nowrap;\n pointer-events: none;\n }\n `;\n shadowRoot.appendChild(style);\n\n highlightEl = document.createElement('div');\n highlightEl.className = 'highlight';\n highlightEl.style.display = 'none';\n\n const labelEl = document.createElement('div');\n labelEl.className = 'highlight-label';\n highlightEl.appendChild(labelEl);\n\n shadowRoot.appendChild(highlightEl);\n\n return {\n highlight(rect: DOMRect | null, label?: string) {\n if (!rect || !highlightEl) {\n if (highlightEl) highlightEl.style.display = 'none';\n return;\n }\n highlightEl.style.display = 'block';\n highlightEl.style.top = rect.top + 'px';\n highlightEl.style.left = rect.left + 'px';\n highlightEl.style.width = rect.width + 'px';\n highlightEl.style.height = rect.height + 'px';\n const lbl = highlightEl.querySelector('.highlight-label') as HTMLDivElement;\n if (lbl && label) {\n lbl.textContent = label;\n lbl.style.display = 'block';\n } else if (lbl) {\n lbl.style.display = 'none';\n }\n },\n destroy() {\n hostEl?.remove();\n hostEl = null;\n shadowRoot = null;\n highlightEl = null;\n },\n };\n}\n","let toastContainer: HTMLDivElement | null = null;\nlet toastShadow: ShadowRoot | null = null;\n\nfunction ensureContainer() {\n if (toastContainer) return;\n toastContainer = document.createElement('div');\n toastContainer.id = 'ui-context-toast';\n toastContainer.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;pointer-events:none;';\n document.body.appendChild(toastContainer);\n toastShadow = toastContainer.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = `\n .toast {\n position: fixed;\n bottom: 24px;\n right: 24px;\n background: #1e293b;\n color: #f1f5f9;\n padding: 12px 20px;\n border-radius: 8px;\n font-size: 13px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.3);\n pointer-events: auto;\n animation: slideIn 0.3s ease, fadeOut 0.3s ease 2.7s;\n z-index: 2147483647;\n }\n @keyframes slideIn { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }\n @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } }\n `;\n toastShadow.appendChild(style);\n}\n\nexport function showToast(message: string, duration = 3000) {\n ensureContainer();\n if (!toastShadow) return;\n const el = document.createElement('div');\n el.className = 'toast';\n el.textContent = message;\n toastShadow.appendChild(el);\n setTimeout(() => el.remove(), duration);\n}\n","export function createToolbar(opts: {\n onCapture: () => void;\n onCaptureAll?: () => void;\n onClose: () => void;\n onFreeze?: () => void;\n}): { el: HTMLElement; destroy: () => void; updateBadge: (count: number) => void; updateFreezeState: (frozen: boolean) => void } {\n const host = document.createElement('div');\n host.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;';\n document.body.appendChild(host);\n\n const shadow = host.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = `\n .toolbar {\n position: fixed;\n bottom: 24px;\n left: 50%;\n transform: translateX(-50%);\n background: #1e293b;\n border: 1px solid #334155;\n border-radius: 12px;\n padding: 8px 12px;\n display: flex;\n gap: 6px;\n align-items: center;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 4px 20px rgba(0,0,0,0.4);\n }\n .toolbar-btn {\n background: #3b82f6;\n color: white;\n border: none;\n padding: 6px 14px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n }\n .toolbar-btn:hover { background: #2563eb; }\n .toolbar-btn.secondary { background: #475569; }\n .toolbar-btn.secondary:hover { background: #64748b; }\n .toolbar-btn.freeze { background: #475569; }\n .toolbar-btn.freeze:hover { background: #64748b; }\n .toolbar-btn.freeze.active { background: #f59e0b; color: #1e293b; }\n .toolbar-btn.freeze.active:hover { background: #d97706; }\n .toolbar-label {\n color: #94a3b8;\n font-size: 12px;\n padding: 0 4px;\n }\n .badge {\n display: inline-block;\n background: #f59e0b;\n color: #1e293b;\n font-size: 10px;\n font-weight: 700;\n padding: 1px 5px;\n border-radius: 10px;\n margin-left: 4px;\n }\n .badge.hidden { display: none; }\n .divider {\n width: 1px;\n height: 20px;\n background: #334155;\n }\n `;\n shadow.appendChild(style);\n\n const toolbar = document.createElement('div');\n toolbar.className = 'toolbar';\n toolbar.innerHTML = `\n <span class=\"toolbar-label\">UI Context</span>\n <div class=\"divider\"></div>\n <button class=\"toolbar-btn capture\">Capture</button>\n <button class=\"toolbar-btn secondary capture-all\" style=\"display:none\">Capture All <span class=\"badge hidden\">0</span></button>\n <div class=\"divider\"></div>\n <button class=\"toolbar-btn freeze\" title=\"Freeze DOM (Ctrl+Shift+F)\">Freeze</button>\n <button class=\"toolbar-btn secondary close\">\\u2715</button>\n `;\n shadow.appendChild(toolbar);\n\n const captureBtn = toolbar.querySelector('.capture') as HTMLButtonElement;\n const captureAllBtn = toolbar.querySelector('.capture-all') as HTMLButtonElement;\n const freezeBtn = toolbar.querySelector('.freeze') as HTMLButtonElement;\n const closeBtn = toolbar.querySelector('.close') as HTMLButtonElement;\n const badge = toolbar.querySelector('.badge') as HTMLSpanElement;\n\n captureBtn.addEventListener('click', opts.onCapture);\n captureAllBtn.addEventListener('click', () => opts.onCaptureAll?.());\n freezeBtn.addEventListener('click', () => opts.onFreeze?.());\n closeBtn.addEventListener('click', opts.onClose);\n\n return {\n el: host,\n destroy() { host.remove(); },\n updateBadge(count: number) {\n if (count > 0) {\n captureAllBtn.style.display = '';\n badge.textContent = String(count);\n badge.classList.remove('hidden');\n } else {\n captureAllBtn.style.display = 'none';\n badge.classList.add('hidden');\n }\n },\n updateFreezeState(frozen: boolean) {\n if (frozen) {\n freezeBtn.classList.add('active');\n freezeBtn.textContent = 'Frozen';\n } else {\n freezeBtn.classList.remove('active');\n freezeBtn.textContent = 'Freeze';\n }\n },\n };\n}\n","export function extractComponentHierarchy(el: HTMLElement): string[] {\n const fiber = getFiber(el);\n if (!fiber) return [];\n\n const hierarchy: string[] = [];\n let current = fiber;\n\n while (current) {\n if (typeof current.type === 'function' || typeof current.type === 'object') {\n const name = typeof current.type === 'function'\n ? current.type.displayName || current.type.name\n : current.type?.displayName || current.type?.render?.displayName || current.type?.render?.name;\n if (name && !name.startsWith('_') && name !== 'Fragment') {\n hierarchy.unshift(name);\n }\n }\n current = current.return;\n }\n\n return hierarchy;\n}\n\nfunction getFiber(el: HTMLElement): any {\n const key = Object.keys(el).find(\n k => k.startsWith('__reactFiber$') || k.startsWith('__reactInternalInstance$')\n );\n return key ? (el as any)[key] : null;\n}\n","import { ElementContext, SourceLocation } from './types';\nimport { extractComponentHierarchy } from './fiber-walker';\n\nconst STYLE_PROPERTIES = [\n 'padding', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft',\n 'margin', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft',\n 'backgroundColor', 'color', 'fontSize', 'fontWeight', 'fontFamily',\n 'borderRadius', 'display', 'flexDirection', 'justifyContent', 'alignItems',\n 'gap', 'width', 'height', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight',\n 'overflow', 'position', 'zIndex', 'opacity', 'border', 'boxShadow',\n 'lineHeight', 'letterSpacing', 'textAlign',\n];\n\nexport function extractSource(el: HTMLElement): SourceLocation | null {\n const file = el.getAttribute('data-source-file');\n const line = el.getAttribute('data-source-line');\n const col = el.getAttribute('data-source-col');\n if (!file || !line) return null;\n return {\n file,\n line: parseInt(line, 10),\n col: parseInt(col || '0', 10),\n component: el.getAttribute('data-source-component') || undefined,\n };\n}\n\nexport function extractContext(el: HTMLElement): ElementContext {\n const computed = getComputedStyle(el);\n const rect = el.getBoundingClientRect();\n const styles: Record<string, string> = {};\n for (const prop of STYLE_PROPERTIES) {\n const value = computed.getPropertyValue(\n prop.replace(/[A-Z]/g, m => '-' + m.toLowerCase())\n );\n if (value && value !== 'none' && value !== 'normal' && value !== 'auto' && value !== '0px' && value !== 'rgba(0, 0, 0, 0)') {\n styles[prop] = value;\n }\n }\n\n return {\n source: extractSource(el),\n tagName: el.tagName.toLowerCase(),\n classes: typeof el.className === 'string' ? el.className : '',\n computedStyles: styles,\n dimensions: { width: rect.width, height: rect.height, x: rect.x, y: rect.y },\n componentHierarchy: extractComponentHierarchy(el),\n url: window.location.href,\n };\n}\n","export async function captureElementScreenshot(el: HTMLElement): Promise<string | undefined> {\n try {\n // Use native canvas approach - works well for most elements\n // without requiring external dependencies like html2canvas\n const rect = el.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) return undefined;\n\n const canvas = document.createElement('canvas');\n const dpr = window.devicePixelRatio || 1;\n const padding = 8; // visual padding around element\n\n const captureWidth = Math.ceil(rect.width + padding * 2);\n const captureHeight = Math.ceil(rect.height + padding * 2);\n\n canvas.width = captureWidth * dpr;\n canvas.height = captureHeight * dpr;\n canvas.style.width = captureWidth + 'px';\n canvas.style.height = captureHeight + 'px';\n\n const ctx = canvas.getContext('2d');\n if (!ctx) return undefined;\n\n ctx.scale(dpr, dpr);\n\n // Try using html-to-image approach via SVG foreignObject\n const screenshot = await captureViaSvgForeignObject(el, rect, ctx, canvas, padding);\n if (screenshot) return screenshot;\n\n // Fallback: capture visible viewport area containing the element\n return await captureViaRange(el, rect, canvas, ctx, padding);\n } catch {\n return undefined;\n }\n}\n\nasync function captureViaSvgForeignObject(\n el: HTMLElement,\n rect: DOMRect,\n ctx: CanvasRenderingContext2D,\n canvas: HTMLCanvasElement,\n padding: number,\n): Promise<string | undefined> {\n try {\n // Clone the element to avoid modifying the original\n const clone = el.cloneNode(true) as HTMLElement;\n\n // Copy computed styles inline\n copyComputedStyles(el, clone);\n\n const width = Math.ceil(rect.width + padding * 2);\n const height = Math.ceil(rect.height + padding * 2);\n\n const svgNs = 'http://www.w3.org/2000/svg';\n const svg = document.createElementNS(svgNs, 'svg');\n svg.setAttribute('width', String(width));\n svg.setAttribute('height', String(height));\n svg.setAttribute('xmlns', svgNs);\n\n const foreignObject = document.createElementNS(svgNs, 'foreignObject');\n foreignObject.setAttribute('width', '100%');\n foreignObject.setAttribute('height', '100%');\n\n const container = document.createElement('div');\n container.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml');\n container.style.cssText = `\n width: ${width}px;\n height: ${height}px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: white;\n padding: ${padding}px;\n box-sizing: border-box;\n `;\n container.appendChild(clone);\n foreignObject.appendChild(container);\n svg.appendChild(foreignObject);\n\n const svgString = new XMLSerializer().serializeToString(svg);\n const svgBlob = new Blob([svgString], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(svgBlob);\n\n return new Promise<string | undefined>((resolve) => {\n const img = new Image();\n img.onload = () => {\n ctx.drawImage(img, 0, 0);\n URL.revokeObjectURL(url);\n try {\n resolve(canvas.toDataURL('image/png'));\n } catch {\n resolve(undefined);\n }\n };\n img.onerror = () => {\n URL.revokeObjectURL(url);\n resolve(undefined);\n };\n img.src = url;\n });\n } catch {\n return undefined;\n }\n}\n\nasync function captureViaRange(\n _el: HTMLElement,\n rect: DOMRect,\n canvas: HTMLCanvasElement,\n ctx: CanvasRenderingContext2D,\n padding: number,\n): Promise<string | undefined> {\n // Fallback: draw a placeholder with element info\n try {\n const width = canvas.width / (window.devicePixelRatio || 1);\n const height = canvas.height / (window.devicePixelRatio || 1);\n\n ctx.fillStyle = '#f8fafc';\n ctx.fillRect(0, 0, width, height);\n ctx.strokeStyle = '#3b82f6';\n ctx.lineWidth = 2;\n ctx.strokeRect(padding, padding, rect.width, rect.height);\n\n ctx.fillStyle = '#64748b';\n ctx.font = '11px -apple-system, BlinkMacSystemFont, sans-serif';\n ctx.fillText(\n `${Math.round(rect.width)} x ${Math.round(rect.height)}px`,\n padding + 4,\n padding + rect.height / 2 + 4,\n );\n\n return canvas.toDataURL('image/png');\n } catch {\n return undefined;\n }\n}\n\nfunction copyComputedStyles(source: HTMLElement, target: HTMLElement): void {\n const computed = getComputedStyle(source);\n const important = [\n 'display', 'width', 'height', 'padding', 'margin', 'border',\n 'border-radius', 'background', 'background-color', 'color',\n 'font-size', 'font-weight', 'font-family', 'line-height',\n 'text-align', 'box-shadow', 'opacity', 'flex-direction',\n 'justify-content', 'align-items', 'gap', 'overflow',\n ];\n for (const prop of important) {\n target.style.setProperty(prop, computed.getPropertyValue(prop));\n }\n\n // Recurse for children\n const sourceChildren = source.children;\n const targetChildren = target.children;\n for (let i = 0; i < sourceChildren.length && i < targetChildren.length; i++) {\n if (sourceChildren[i] instanceof HTMLElement && targetChildren[i] instanceof HTMLElement) {\n copyComputedStyles(sourceChildren[i] as HTMLElement, targetChildren[i] as HTMLElement);\n }\n }\n}\n","import { extractContext } from './context-extractor';\nimport { captureElementScreenshot } from './screenshot';\nimport { ElementContext } from './types';\n\ntype SelectionCallback = (context: ElementContext) => void;\ntype MultiSelectionCallback = (contexts: ElementContext[]) => void;\n\nexport function createSelectionHandler(opts: {\n onHover: (el: HTMLElement | null) => void;\n onSelect: SelectionCallback;\n onMultiSelect?: MultiSelectionCallback;\n onSelectionChange?: (count: number) => void;\n}) {\n let isActive = false;\n let selectedEl: HTMLElement | null = null;\n const multiSelected: Set<HTMLElement> = new Set();\n\n function handleMouseMove(e: MouseEvent) {\n if (!isActive) return;\n const target = e.target as HTMLElement;\n if (target.id === 'ui-context-host' || target.id === 'ui-context-toast' || target.closest('#ui-context-host')) return;\n opts.onHover(target);\n }\n\n function handleClick(e: MouseEvent) {\n if (!isActive) return;\n e.preventDefault();\n e.stopPropagation();\n\n const target = e.target as HTMLElement;\n if (target.id === 'ui-context-host' || target.closest('#ui-context-host')) return;\n\n // Shift+Click: add to multi-selection\n if (e.shiftKey) {\n if (multiSelected.has(target)) {\n multiSelected.delete(target);\n target.style.outline = '';\n } else {\n multiSelected.add(target);\n target.style.outline = '2px dashed #f59e0b';\n }\n opts.onSelectionChange?.(multiSelected.size);\n return;\n }\n\n selectedEl = target;\n const context = extractContext(target);\n\n captureElementScreenshot(target).then(screenshot => {\n if (screenshot) context.screenshotDataUrl = screenshot;\n opts.onSelect(context);\n });\n }\n\n return {\n activate() {\n isActive = true;\n document.addEventListener('mousemove', handleMouseMove, true);\n document.addEventListener('click', handleClick, true);\n document.body.style.cursor = 'crosshair';\n },\n deactivate() {\n isActive = false;\n selectedEl = null;\n // Clear multi-selection outlines\n for (const el of multiSelected) {\n el.style.outline = '';\n }\n multiSelected.clear();\n document.removeEventListener('mousemove', handleMouseMove, true);\n document.removeEventListener('click', handleClick, true);\n document.body.style.cursor = '';\n opts.onHover(null);\n },\n get isActive() { return isActive; },\n get selectedElement() { return selectedEl; },\n get multiSelectedElements() { return multiSelected; },\n get multiSelectedCount() { return multiSelected.size; },\n\n async captureMultiSelection(): Promise<ElementContext[]> {\n const contexts: ElementContext[] = [];\n for (const el of multiSelected) {\n const ctx = extractContext(el);\n const screenshot = await captureElementScreenshot(el);\n if (screenshot) ctx.screenshotDataUrl = screenshot;\n contexts.push(ctx);\n }\n return contexts;\n },\n\n clearMultiSelection() {\n for (const el of multiSelected) {\n el.style.outline = '';\n }\n multiSelected.clear();\n opts.onSelectionChange?.(0);\n },\n };\n}\n","import { ElementContext } from './types';\n\nconst DEFAULT_SERVER_PORT = 19638;\n\nlet serverUrl = '';\n\nexport function initTransport(url?: string) {\n serverUrl = url || `http://127.0.0.1:${DEFAULT_SERVER_PORT}`;\n}\n\nexport function sendContext(context: ElementContext | ElementContext[]): Promise<boolean> {\n return new Promise((resolve) => {\n try {\n // Strategy 1: Vite HMR WebSocket (for Vite projects)\n if (typeof import.meta !== 'undefined' && (import.meta as any).hot) {\n (import.meta as any).hot.send('ui-context:capture', context);\n resolve(true);\n return;\n }\n\n // Strategy 2: HTTP POST to standalone context server (for Next.js projects)\n fetch(`${serverUrl}/capture`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(context),\n })\n .then((res) => res.json())\n .then((result) => resolve(result.success === true))\n .catch(() => resolve(false));\n } catch {\n resolve(false);\n }\n });\n}\n","const STORAGE_KEY = 'ui-context-kit-onboarding-dismissed';\n\nexport function showOnboarding(shortcut: string): void {\n // Don't show if already dismissed\n try {\n if (localStorage.getItem(STORAGE_KEY)) return;\n } catch {\n return; // localStorage not available\n }\n\n const host = document.createElement('div');\n host.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483646;';\n document.body.appendChild(host);\n\n const shadow = host.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = `\n .banner {\n position: fixed;\n bottom: 20px;\n left: 50%;\n transform: translateX(-50%);\n background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);\n border: 1px solid #334155;\n border-radius: 12px;\n padding: 12px 20px;\n display: flex;\n gap: 12px;\n align-items: center;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 8px 32px rgba(0,0,0,0.4);\n animation: slideUp 0.4s ease;\n max-width: 480px;\n }\n @keyframes slideUp {\n from { opacity: 0; transform: translateX(-50%) translateY(20px); }\n to { opacity: 1; transform: translateX(-50%) translateY(0); }\n }\n .icon {\n font-size: 20px;\n flex-shrink: 0;\n }\n .text {\n color: #e2e8f0;\n font-size: 13px;\n line-height: 1.4;\n }\n .text strong {\n color: #60a5fa;\n }\n .kbd {\n display: inline-block;\n background: #334155;\n color: #e2e8f0;\n padding: 1px 6px;\n border-radius: 4px;\n font-size: 12px;\n font-family: monospace;\n border: 1px solid #475569;\n }\n .close-btn {\n background: none;\n border: none;\n color: #64748b;\n cursor: pointer;\n padding: 4px;\n font-size: 16px;\n flex-shrink: 0;\n }\n .close-btn:hover { color: #94a3b8; }\n `;\n shadow.appendChild(style);\n\n const shortcutDisplay = shortcut.split('+').map(k =>\n k.charAt(0).toUpperCase() + k.slice(1)\n ).join(' + ');\n\n const banner = document.createElement('div');\n banner.className = 'banner';\n banner.innerHTML = `\n <span class=\"icon\">\\u{1F3AF}</span>\n <span class=\"text\">\n <strong>UI Context Kit</strong> is ready!\n Press <kbd class=\"kbd\">${shortcutDisplay}</kbd> to select any UI element and capture its context for AI.\n Use <strong>Shift+Click</strong> for multi-select, <strong>Ctrl+Shift+F</strong> to freeze state.\n </span>\n <button class=\"close-btn\" title=\"Dismiss\">\\u2715</button>\n `;\n shadow.appendChild(banner);\n\n banner.querySelector('.close-btn')!.addEventListener('click', () => {\n host.remove();\n try {\n localStorage.setItem(STORAGE_KEY, '1');\n } catch { /* ignore */ }\n });\n\n // Auto-dismiss after 8 seconds\n setTimeout(() => {\n if (host.parentNode) {\n banner.style.transition = 'opacity 0.3s ease';\n banner.style.opacity = '0';\n setTimeout(() => host.remove(), 300);\n }\n }, 8000);\n}\n","import { createOverlay } from './ui/overlay';\nimport { showToast } from './ui/toast';\nimport { createToolbar } from './ui/toolbar';\nimport { createSelectionHandler } from './selection';\nimport { sendContext, initTransport } from './transport';\nimport { extractContext, extractSource } from './context-extractor';\nimport { showOnboarding } from './ui/onboarding';\nimport type { ElementContext } from './types';\n\nexport type { ElementContext, SourceLocation } from './types';\n\nexport interface UIContextOptions {\n shortcut?: string;\n wsUrl?: string;\n}\n\nexport function initUIContext(options: UIContextOptions = {}) {\n const { shortcut = 'alt+x' } = options;\n\n initTransport(options.wsUrl);\n\n let overlay: ReturnType<typeof createOverlay> | null = null;\n let toolbar: ReturnType<typeof createToolbar> | null = null;\n let isFrozen = false;\n let frozenObservers: MutationObserver[] = [];\n\n const selection = createSelectionHandler({\n onHover(el) {\n if (!el) {\n overlay?.highlight(null);\n return;\n }\n const rect = el.getBoundingClientRect();\n const source = extractSource(el);\n const label = source\n ? `${source.component || el.tagName.toLowerCase()} \\u00b7 ${source.file}:${source.line}`\n : el.tagName.toLowerCase();\n overlay?.highlight(rect, label);\n },\n async onSelect(context: ElementContext) {\n showToast('Capturing context...');\n const success = await sendContext(context);\n if (success) {\n showToast('Context captured!');\n } else {\n showToast('Failed to send context. Is the dev server running?');\n }\n },\n onSelectionChange(count) {\n toolbar?.updateBadge(count);\n },\n });\n\n function activate() {\n if (selection.isActive) return;\n overlay = createOverlay();\n toolbar = createToolbar({\n onCapture() {\n if (selection.selectedElement) {\n const context = extractContext(selection.selectedElement);\n sendContext(context);\n }\n },\n async onCaptureAll() {\n if (selection.multiSelectedCount === 0) {\n showToast('No elements selected. Use Shift+Click to select multiple.');\n return;\n }\n showToast(`Capturing ${selection.multiSelectedCount} elements...`);\n const contexts = await selection.captureMultiSelection();\n const success = await sendContext(contexts);\n if (success) {\n showToast(`${contexts.length} elements captured!`);\n selection.clearMultiSelection();\n } else {\n showToast('Failed to send context. Is the dev server running?');\n }\n },\n onClose() { deactivate(); },\n onFreeze() { toggleFreeze(); },\n });\n selection.activate();\n showToast('UI Context active \\u2014 click to capture, Shift+click for multi-select');\n }\n\n function deactivate() {\n if (isFrozen) unfreezeDOM();\n selection.deactivate();\n overlay?.destroy();\n toolbar?.destroy();\n overlay = null;\n toolbar = null;\n }\n\n function toggleFreeze() {\n if (isFrozen) {\n unfreezeDOM();\n showToast('DOM unfrozen');\n } else {\n freezeDOM();\n showToast('DOM frozen \\u2014 hover states preserved');\n }\n toolbar?.updateFreezeState(isFrozen);\n }\n\n function freezeDOM() {\n isFrozen = true;\n // Disconnect all existing MutationObservers by creating a blocking one\n // This prevents DOM updates (dropdowns closing, tooltips hiding, etc.)\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n // Revert added/removed nodes\n for (const node of mutation.addedNodes) {\n if (node instanceof HTMLElement && !node.id?.includes('ui-context')) {\n node.remove();\n }\n }\n // Revert attribute changes\n if (mutation.type === 'attributes' && mutation.target instanceof HTMLElement) {\n if (!mutation.target.id?.includes('ui-context')) {\n const old = mutation.oldValue;\n if (old !== null) {\n mutation.target.setAttribute(mutation.attributeName!, old);\n }\n }\n }\n }\n });\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeOldValue: true,\n });\n frozenObservers.push(observer);\n }\n\n function unfreezeDOM() {\n isFrozen = false;\n for (const obs of frozenObservers) {\n obs.disconnect();\n }\n frozenObservers = [];\n }\n\n // Register keyboard shortcuts\n document.addEventListener('keydown', (e) => {\n // Main shortcut (Alt+X)\n const keys = shortcut.split('+');\n const needsAlt = keys.includes('alt');\n const needsCtrl = keys.includes('ctrl');\n const needsShift = keys.includes('shift');\n const mainKey = keys[keys.length - 1].toLowerCase();\n const mainCode = /^[a-z]$/.test(mainKey) ? 'Key' + mainKey.toUpperCase() : /^[0-9]$/.test(mainKey) ? 'Digit' + mainKey : '';\n\n if (\n e.altKey === needsAlt &&\n e.ctrlKey === needsCtrl &&\n e.shiftKey === needsShift &&\n (mainCode ? e.code === mainCode : e.key.toLowerCase() === mainKey)\n ) {\n e.preventDefault();\n if (selection.isActive) {\n deactivate();\n } else {\n activate();\n }\n return;\n }\n\n // Freeze shortcut: Ctrl+Shift+F (only when active)\n if (selection.isActive && e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'f') {\n e.preventDefault();\n toggleFreeze();\n }\n });\n\n // Show onboarding on first use\n showOnboarding(shortcut);\n\n return { activate, deactivate };\n}\n","import { initUIContext } from './index';\n\n// Auto-initialize when loaded\nif (typeof window !== 'undefined') {\n (window as any).__uiContext = initUIContext();\n}\n"],"mappings":"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","names":[]}
|
package/dist/inject.js
CHANGED
package/dist/react.cjs
CHANGED
|
@@ -609,7 +609,7 @@ var init_selection = __esm({
|
|
|
609
609
|
|
|
610
610
|
// src/transport.ts
|
|
611
611
|
function initTransport(url) {
|
|
612
|
-
serverUrl = url || `http
|
|
612
|
+
serverUrl = url || `http://127.0.0.1:${DEFAULT_SERVER_PORT}`;
|
|
613
613
|
}
|
|
614
614
|
function sendContext(context) {
|
|
615
615
|
return new Promise((resolve) => {
|
package/dist/react.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ui/overlay.ts","../src/ui/toast.ts","../src/ui/toolbar.ts","../src/fiber-walker.ts","../src/context-extractor.ts","../src/screenshot.ts","../src/selection.ts","../src/transport.ts","../src/ui/onboarding.ts","../src/index.ts","../src/react.tsx"],"sourcesContent":["let hostEl: HTMLDivElement | null = null;\nlet shadowRoot: ShadowRoot | null = null;\nlet highlightEl: HTMLDivElement | null = null;\n\nexport function createOverlay(): { highlight: (rect: DOMRect | null, label?: string) => void; destroy: () => void } {\n hostEl = document.createElement('div');\n hostEl.id = 'ui-context-host';\n hostEl.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;pointer-events:none;';\n document.body.appendChild(hostEl);\n\n shadowRoot = hostEl.attachShadow({ mode: 'open' });\n\n const style = document.createElement('style');\n style.textContent = `\n .highlight {\n position: fixed;\n border: 2px solid #3b82f6;\n background: rgba(59, 130, 246, 0.1);\n pointer-events: none;\n transition: all 0.1s ease;\n border-radius: 4px;\n z-index: 2147483647;\n }\n .highlight-label {\n position: absolute;\n top: -24px;\n left: -2px;\n background: #3b82f6;\n color: white;\n font-size: 11px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n padding: 2px 6px;\n border-radius: 3px 3px 0 0;\n white-space: nowrap;\n pointer-events: none;\n }\n `;\n shadowRoot.appendChild(style);\n\n highlightEl = document.createElement('div');\n highlightEl.className = 'highlight';\n highlightEl.style.display = 'none';\n\n const labelEl = document.createElement('div');\n labelEl.className = 'highlight-label';\n highlightEl.appendChild(labelEl);\n\n shadowRoot.appendChild(highlightEl);\n\n return {\n highlight(rect: DOMRect | null, label?: string) {\n if (!rect || !highlightEl) {\n if (highlightEl) highlightEl.style.display = 'none';\n return;\n }\n highlightEl.style.display = 'block';\n highlightEl.style.top = rect.top + 'px';\n highlightEl.style.left = rect.left + 'px';\n highlightEl.style.width = rect.width + 'px';\n highlightEl.style.height = rect.height + 'px';\n const lbl = highlightEl.querySelector('.highlight-label') as HTMLDivElement;\n if (lbl && label) {\n lbl.textContent = label;\n lbl.style.display = 'block';\n } else if (lbl) {\n lbl.style.display = 'none';\n }\n },\n destroy() {\n hostEl?.remove();\n hostEl = null;\n shadowRoot = null;\n highlightEl = null;\n },\n };\n}\n","let toastContainer: HTMLDivElement | null = null;\nlet toastShadow: ShadowRoot | null = null;\n\nfunction ensureContainer() {\n if (toastContainer) return;\n toastContainer = document.createElement('div');\n toastContainer.id = 'ui-context-toast';\n toastContainer.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;pointer-events:none;';\n document.body.appendChild(toastContainer);\n toastShadow = toastContainer.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = `\n .toast {\n position: fixed;\n bottom: 24px;\n right: 24px;\n background: #1e293b;\n color: #f1f5f9;\n padding: 12px 20px;\n border-radius: 8px;\n font-size: 13px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.3);\n pointer-events: auto;\n animation: slideIn 0.3s ease, fadeOut 0.3s ease 2.7s;\n z-index: 2147483647;\n }\n @keyframes slideIn { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }\n @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } }\n `;\n toastShadow.appendChild(style);\n}\n\nexport function showToast(message: string, duration = 3000) {\n ensureContainer();\n if (!toastShadow) return;\n const el = document.createElement('div');\n el.className = 'toast';\n el.textContent = message;\n toastShadow.appendChild(el);\n setTimeout(() => el.remove(), duration);\n}\n","export function createToolbar(opts: {\n onCapture: () => void;\n onCaptureAll?: () => void;\n onClose: () => void;\n onFreeze?: () => void;\n}): { el: HTMLElement; destroy: () => void; updateBadge: (count: number) => void; updateFreezeState: (frozen: boolean) => void } {\n const host = document.createElement('div');\n host.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;';\n document.body.appendChild(host);\n\n const shadow = host.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = `\n .toolbar {\n position: fixed;\n bottom: 24px;\n left: 50%;\n transform: translateX(-50%);\n background: #1e293b;\n border: 1px solid #334155;\n border-radius: 12px;\n padding: 8px 12px;\n display: flex;\n gap: 6px;\n align-items: center;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 4px 20px rgba(0,0,0,0.4);\n }\n .toolbar-btn {\n background: #3b82f6;\n color: white;\n border: none;\n padding: 6px 14px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n }\n .toolbar-btn:hover { background: #2563eb; }\n .toolbar-btn.secondary { background: #475569; }\n .toolbar-btn.secondary:hover { background: #64748b; }\n .toolbar-btn.freeze { background: #475569; }\n .toolbar-btn.freeze:hover { background: #64748b; }\n .toolbar-btn.freeze.active { background: #f59e0b; color: #1e293b; }\n .toolbar-btn.freeze.active:hover { background: #d97706; }\n .toolbar-label {\n color: #94a3b8;\n font-size: 12px;\n padding: 0 4px;\n }\n .badge {\n display: inline-block;\n background: #f59e0b;\n color: #1e293b;\n font-size: 10px;\n font-weight: 700;\n padding: 1px 5px;\n border-radius: 10px;\n margin-left: 4px;\n }\n .badge.hidden { display: none; }\n .divider {\n width: 1px;\n height: 20px;\n background: #334155;\n }\n `;\n shadow.appendChild(style);\n\n const toolbar = document.createElement('div');\n toolbar.className = 'toolbar';\n toolbar.innerHTML = `\n <span class=\"toolbar-label\">UI Context</span>\n <div class=\"divider\"></div>\n <button class=\"toolbar-btn capture\">Capture</button>\n <button class=\"toolbar-btn secondary capture-all\" style=\"display:none\">Capture All <span class=\"badge hidden\">0</span></button>\n <div class=\"divider\"></div>\n <button class=\"toolbar-btn freeze\" title=\"Freeze DOM (Ctrl+Shift+F)\">Freeze</button>\n <button class=\"toolbar-btn secondary close\">\\u2715</button>\n `;\n shadow.appendChild(toolbar);\n\n const captureBtn = toolbar.querySelector('.capture') as HTMLButtonElement;\n const captureAllBtn = toolbar.querySelector('.capture-all') as HTMLButtonElement;\n const freezeBtn = toolbar.querySelector('.freeze') as HTMLButtonElement;\n const closeBtn = toolbar.querySelector('.close') as HTMLButtonElement;\n const badge = toolbar.querySelector('.badge') as HTMLSpanElement;\n\n captureBtn.addEventListener('click', opts.onCapture);\n captureAllBtn.addEventListener('click', () => opts.onCaptureAll?.());\n freezeBtn.addEventListener('click', () => opts.onFreeze?.());\n closeBtn.addEventListener('click', opts.onClose);\n\n return {\n el: host,\n destroy() { host.remove(); },\n updateBadge(count: number) {\n if (count > 0) {\n captureAllBtn.style.display = '';\n badge.textContent = String(count);\n badge.classList.remove('hidden');\n } else {\n captureAllBtn.style.display = 'none';\n badge.classList.add('hidden');\n }\n },\n updateFreezeState(frozen: boolean) {\n if (frozen) {\n freezeBtn.classList.add('active');\n freezeBtn.textContent = 'Frozen';\n } else {\n freezeBtn.classList.remove('active');\n freezeBtn.textContent = 'Freeze';\n }\n },\n };\n}\n","export function extractComponentHierarchy(el: HTMLElement): string[] {\n const fiber = getFiber(el);\n if (!fiber) return [];\n\n const hierarchy: string[] = [];\n let current = fiber;\n\n while (current) {\n if (typeof current.type === 'function' || typeof current.type === 'object') {\n const name = typeof current.type === 'function'\n ? current.type.displayName || current.type.name\n : current.type?.displayName || current.type?.render?.displayName || current.type?.render?.name;\n if (name && !name.startsWith('_') && name !== 'Fragment') {\n hierarchy.unshift(name);\n }\n }\n current = current.return;\n }\n\n return hierarchy;\n}\n\nfunction getFiber(el: HTMLElement): any {\n const key = Object.keys(el).find(\n k => k.startsWith('__reactFiber$') || k.startsWith('__reactInternalInstance$')\n );\n return key ? (el as any)[key] : null;\n}\n","import { ElementContext, SourceLocation } from './types';\nimport { extractComponentHierarchy } from './fiber-walker';\n\nconst STYLE_PROPERTIES = [\n 'padding', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft',\n 'margin', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft',\n 'backgroundColor', 'color', 'fontSize', 'fontWeight', 'fontFamily',\n 'borderRadius', 'display', 'flexDirection', 'justifyContent', 'alignItems',\n 'gap', 'width', 'height', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight',\n 'overflow', 'position', 'zIndex', 'opacity', 'border', 'boxShadow',\n 'lineHeight', 'letterSpacing', 'textAlign',\n];\n\nexport function extractSource(el: HTMLElement): SourceLocation | null {\n const file = el.getAttribute('data-source-file');\n const line = el.getAttribute('data-source-line');\n const col = el.getAttribute('data-source-col');\n if (!file || !line) return null;\n return {\n file,\n line: parseInt(line, 10),\n col: parseInt(col || '0', 10),\n component: el.getAttribute('data-source-component') || undefined,\n };\n}\n\nexport function extractContext(el: HTMLElement): ElementContext {\n const computed = getComputedStyle(el);\n const rect = el.getBoundingClientRect();\n const styles: Record<string, string> = {};\n for (const prop of STYLE_PROPERTIES) {\n const value = computed.getPropertyValue(\n prop.replace(/[A-Z]/g, m => '-' + m.toLowerCase())\n );\n if (value && value !== 'none' && value !== 'normal' && value !== 'auto' && value !== '0px' && value !== 'rgba(0, 0, 0, 0)') {\n styles[prop] = value;\n }\n }\n\n return {\n source: extractSource(el),\n tagName: el.tagName.toLowerCase(),\n classes: typeof el.className === 'string' ? el.className : '',\n computedStyles: styles,\n dimensions: { width: rect.width, height: rect.height, x: rect.x, y: rect.y },\n componentHierarchy: extractComponentHierarchy(el),\n url: window.location.href,\n };\n}\n","export async function captureElementScreenshot(el: HTMLElement): Promise<string | undefined> {\n try {\n // Use native canvas approach - works well for most elements\n // without requiring external dependencies like html2canvas\n const rect = el.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) return undefined;\n\n const canvas = document.createElement('canvas');\n const dpr = window.devicePixelRatio || 1;\n const padding = 8; // visual padding around element\n\n const captureWidth = Math.ceil(rect.width + padding * 2);\n const captureHeight = Math.ceil(rect.height + padding * 2);\n\n canvas.width = captureWidth * dpr;\n canvas.height = captureHeight * dpr;\n canvas.style.width = captureWidth + 'px';\n canvas.style.height = captureHeight + 'px';\n\n const ctx = canvas.getContext('2d');\n if (!ctx) return undefined;\n\n ctx.scale(dpr, dpr);\n\n // Try using html-to-image approach via SVG foreignObject\n const screenshot = await captureViaSvgForeignObject(el, rect, ctx, canvas, padding);\n if (screenshot) return screenshot;\n\n // Fallback: capture visible viewport area containing the element\n return await captureViaRange(el, rect, canvas, ctx, padding);\n } catch {\n return undefined;\n }\n}\n\nasync function captureViaSvgForeignObject(\n el: HTMLElement,\n rect: DOMRect,\n ctx: CanvasRenderingContext2D,\n canvas: HTMLCanvasElement,\n padding: number,\n): Promise<string | undefined> {\n try {\n // Clone the element to avoid modifying the original\n const clone = el.cloneNode(true) as HTMLElement;\n\n // Copy computed styles inline\n copyComputedStyles(el, clone);\n\n const width = Math.ceil(rect.width + padding * 2);\n const height = Math.ceil(rect.height + padding * 2);\n\n const svgNs = 'http://www.w3.org/2000/svg';\n const svg = document.createElementNS(svgNs, 'svg');\n svg.setAttribute('width', String(width));\n svg.setAttribute('height', String(height));\n svg.setAttribute('xmlns', svgNs);\n\n const foreignObject = document.createElementNS(svgNs, 'foreignObject');\n foreignObject.setAttribute('width', '100%');\n foreignObject.setAttribute('height', '100%');\n\n const container = document.createElement('div');\n container.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml');\n container.style.cssText = `\n width: ${width}px;\n height: ${height}px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: white;\n padding: ${padding}px;\n box-sizing: border-box;\n `;\n container.appendChild(clone);\n foreignObject.appendChild(container);\n svg.appendChild(foreignObject);\n\n const svgString = new XMLSerializer().serializeToString(svg);\n const svgBlob = new Blob([svgString], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(svgBlob);\n\n return new Promise<string | undefined>((resolve) => {\n const img = new Image();\n img.onload = () => {\n ctx.drawImage(img, 0, 0);\n URL.revokeObjectURL(url);\n try {\n resolve(canvas.toDataURL('image/png'));\n } catch {\n resolve(undefined);\n }\n };\n img.onerror = () => {\n URL.revokeObjectURL(url);\n resolve(undefined);\n };\n img.src = url;\n });\n } catch {\n return undefined;\n }\n}\n\nasync function captureViaRange(\n _el: HTMLElement,\n rect: DOMRect,\n canvas: HTMLCanvasElement,\n ctx: CanvasRenderingContext2D,\n padding: number,\n): Promise<string | undefined> {\n // Fallback: draw a placeholder with element info\n try {\n const width = canvas.width / (window.devicePixelRatio || 1);\n const height = canvas.height / (window.devicePixelRatio || 1);\n\n ctx.fillStyle = '#f8fafc';\n ctx.fillRect(0, 0, width, height);\n ctx.strokeStyle = '#3b82f6';\n ctx.lineWidth = 2;\n ctx.strokeRect(padding, padding, rect.width, rect.height);\n\n ctx.fillStyle = '#64748b';\n ctx.font = '11px -apple-system, BlinkMacSystemFont, sans-serif';\n ctx.fillText(\n `${Math.round(rect.width)} x ${Math.round(rect.height)}px`,\n padding + 4,\n padding + rect.height / 2 + 4,\n );\n\n return canvas.toDataURL('image/png');\n } catch {\n return undefined;\n }\n}\n\nfunction copyComputedStyles(source: HTMLElement, target: HTMLElement): void {\n const computed = getComputedStyle(source);\n const important = [\n 'display', 'width', 'height', 'padding', 'margin', 'border',\n 'border-radius', 'background', 'background-color', 'color',\n 'font-size', 'font-weight', 'font-family', 'line-height',\n 'text-align', 'box-shadow', 'opacity', 'flex-direction',\n 'justify-content', 'align-items', 'gap', 'overflow',\n ];\n for (const prop of important) {\n target.style.setProperty(prop, computed.getPropertyValue(prop));\n }\n\n // Recurse for children\n const sourceChildren = source.children;\n const targetChildren = target.children;\n for (let i = 0; i < sourceChildren.length && i < targetChildren.length; i++) {\n if (sourceChildren[i] instanceof HTMLElement && targetChildren[i] instanceof HTMLElement) {\n copyComputedStyles(sourceChildren[i] as HTMLElement, targetChildren[i] as HTMLElement);\n }\n }\n}\n","import { extractContext } from './context-extractor';\nimport { captureElementScreenshot } from './screenshot';\nimport { ElementContext } from './types';\n\ntype SelectionCallback = (context: ElementContext) => void;\ntype MultiSelectionCallback = (contexts: ElementContext[]) => void;\n\nexport function createSelectionHandler(opts: {\n onHover: (el: HTMLElement | null) => void;\n onSelect: SelectionCallback;\n onMultiSelect?: MultiSelectionCallback;\n onSelectionChange?: (count: number) => void;\n}) {\n let isActive = false;\n let selectedEl: HTMLElement | null = null;\n const multiSelected: Set<HTMLElement> = new Set();\n\n function handleMouseMove(e: MouseEvent) {\n if (!isActive) return;\n const target = e.target as HTMLElement;\n if (target.id === 'ui-context-host' || target.id === 'ui-context-toast' || target.closest('#ui-context-host')) return;\n opts.onHover(target);\n }\n\n function handleClick(e: MouseEvent) {\n if (!isActive) return;\n e.preventDefault();\n e.stopPropagation();\n\n const target = e.target as HTMLElement;\n if (target.id === 'ui-context-host' || target.closest('#ui-context-host')) return;\n\n // Shift+Click: add to multi-selection\n if (e.shiftKey) {\n if (multiSelected.has(target)) {\n multiSelected.delete(target);\n target.style.outline = '';\n } else {\n multiSelected.add(target);\n target.style.outline = '2px dashed #f59e0b';\n }\n opts.onSelectionChange?.(multiSelected.size);\n return;\n }\n\n selectedEl = target;\n const context = extractContext(target);\n\n captureElementScreenshot(target).then(screenshot => {\n if (screenshot) context.screenshotDataUrl = screenshot;\n opts.onSelect(context);\n });\n }\n\n return {\n activate() {\n isActive = true;\n document.addEventListener('mousemove', handleMouseMove, true);\n document.addEventListener('click', handleClick, true);\n document.body.style.cursor = 'crosshair';\n },\n deactivate() {\n isActive = false;\n selectedEl = null;\n // Clear multi-selection outlines\n for (const el of multiSelected) {\n el.style.outline = '';\n }\n multiSelected.clear();\n document.removeEventListener('mousemove', handleMouseMove, true);\n document.removeEventListener('click', handleClick, true);\n document.body.style.cursor = '';\n opts.onHover(null);\n },\n get isActive() { return isActive; },\n get selectedElement() { return selectedEl; },\n get multiSelectedElements() { return multiSelected; },\n get multiSelectedCount() { return multiSelected.size; },\n\n async captureMultiSelection(): Promise<ElementContext[]> {\n const contexts: ElementContext[] = [];\n for (const el of multiSelected) {\n const ctx = extractContext(el);\n const screenshot = await captureElementScreenshot(el);\n if (screenshot) ctx.screenshotDataUrl = screenshot;\n contexts.push(ctx);\n }\n return contexts;\n },\n\n clearMultiSelection() {\n for (const el of multiSelected) {\n el.style.outline = '';\n }\n multiSelected.clear();\n opts.onSelectionChange?.(0);\n },\n };\n}\n","import { ElementContext } from './types';\n\nconst DEFAULT_SERVER_PORT = 19638;\n\nlet serverUrl = '';\n\nexport function initTransport(url?: string) {\n serverUrl = url || `http://${location.hostname}:${DEFAULT_SERVER_PORT}`;\n}\n\nexport function sendContext(context: ElementContext | ElementContext[]): Promise<boolean> {\n return new Promise((resolve) => {\n try {\n // Strategy 1: Vite HMR WebSocket (for Vite projects)\n if (typeof import.meta !== 'undefined' && (import.meta as any).hot) {\n (import.meta as any).hot.send('ui-context:capture', context);\n resolve(true);\n return;\n }\n\n // Strategy 2: HTTP POST to standalone context server (for Next.js projects)\n fetch(`${serverUrl}/capture`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(context),\n })\n .then((res) => res.json())\n .then((result) => resolve(result.success === true))\n .catch(() => resolve(false));\n } catch {\n resolve(false);\n }\n });\n}\n","const STORAGE_KEY = 'ui-context-kit-onboarding-dismissed';\n\nexport function showOnboarding(shortcut: string): void {\n // Don't show if already dismissed\n try {\n if (localStorage.getItem(STORAGE_KEY)) return;\n } catch {\n return; // localStorage not available\n }\n\n const host = document.createElement('div');\n host.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483646;';\n document.body.appendChild(host);\n\n const shadow = host.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = `\n .banner {\n position: fixed;\n bottom: 20px;\n left: 50%;\n transform: translateX(-50%);\n background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);\n border: 1px solid #334155;\n border-radius: 12px;\n padding: 12px 20px;\n display: flex;\n gap: 12px;\n align-items: center;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 8px 32px rgba(0,0,0,0.4);\n animation: slideUp 0.4s ease;\n max-width: 480px;\n }\n @keyframes slideUp {\n from { opacity: 0; transform: translateX(-50%) translateY(20px); }\n to { opacity: 1; transform: translateX(-50%) translateY(0); }\n }\n .icon {\n font-size: 20px;\n flex-shrink: 0;\n }\n .text {\n color: #e2e8f0;\n font-size: 13px;\n line-height: 1.4;\n }\n .text strong {\n color: #60a5fa;\n }\n .kbd {\n display: inline-block;\n background: #334155;\n color: #e2e8f0;\n padding: 1px 6px;\n border-radius: 4px;\n font-size: 12px;\n font-family: monospace;\n border: 1px solid #475569;\n }\n .close-btn {\n background: none;\n border: none;\n color: #64748b;\n cursor: pointer;\n padding: 4px;\n font-size: 16px;\n flex-shrink: 0;\n }\n .close-btn:hover { color: #94a3b8; }\n `;\n shadow.appendChild(style);\n\n const shortcutDisplay = shortcut.split('+').map(k =>\n k.charAt(0).toUpperCase() + k.slice(1)\n ).join(' + ');\n\n const banner = document.createElement('div');\n banner.className = 'banner';\n banner.innerHTML = `\n <span class=\"icon\">\\u{1F3AF}</span>\n <span class=\"text\">\n <strong>UI Context Kit</strong> is ready!\n Press <kbd class=\"kbd\">${shortcutDisplay}</kbd> to select any UI element and capture its context for AI.\n Use <strong>Shift+Click</strong> for multi-select, <strong>Ctrl+Shift+F</strong> to freeze state.\n </span>\n <button class=\"close-btn\" title=\"Dismiss\">\\u2715</button>\n `;\n shadow.appendChild(banner);\n\n banner.querySelector('.close-btn')!.addEventListener('click', () => {\n host.remove();\n try {\n localStorage.setItem(STORAGE_KEY, '1');\n } catch { /* ignore */ }\n });\n\n // Auto-dismiss after 8 seconds\n setTimeout(() => {\n if (host.parentNode) {\n banner.style.transition = 'opacity 0.3s ease';\n banner.style.opacity = '0';\n setTimeout(() => host.remove(), 300);\n }\n }, 8000);\n}\n","import { createOverlay } from './ui/overlay';\nimport { showToast } from './ui/toast';\nimport { createToolbar } from './ui/toolbar';\nimport { createSelectionHandler } from './selection';\nimport { sendContext, initTransport } from './transport';\nimport { extractContext, extractSource } from './context-extractor';\nimport { showOnboarding } from './ui/onboarding';\nimport type { ElementContext } from './types';\n\nexport type { ElementContext, SourceLocation } from './types';\n\nexport interface UIContextOptions {\n shortcut?: string;\n wsUrl?: string;\n}\n\nexport function initUIContext(options: UIContextOptions = {}) {\n const { shortcut = 'alt+x' } = options;\n\n initTransport(options.wsUrl);\n\n let overlay: ReturnType<typeof createOverlay> | null = null;\n let toolbar: ReturnType<typeof createToolbar> | null = null;\n let isFrozen = false;\n let frozenObservers: MutationObserver[] = [];\n\n const selection = createSelectionHandler({\n onHover(el) {\n if (!el) {\n overlay?.highlight(null);\n return;\n }\n const rect = el.getBoundingClientRect();\n const source = extractSource(el);\n const label = source\n ? `${source.component || el.tagName.toLowerCase()} \\u00b7 ${source.file}:${source.line}`\n : el.tagName.toLowerCase();\n overlay?.highlight(rect, label);\n },\n async onSelect(context: ElementContext) {\n showToast('Capturing context...');\n const success = await sendContext(context);\n if (success) {\n showToast('Context captured!');\n } else {\n showToast('Failed to send context. Is the dev server running?');\n }\n },\n onSelectionChange(count) {\n toolbar?.updateBadge(count);\n },\n });\n\n function activate() {\n if (selection.isActive) return;\n overlay = createOverlay();\n toolbar = createToolbar({\n onCapture() {\n if (selection.selectedElement) {\n const context = extractContext(selection.selectedElement);\n sendContext(context);\n }\n },\n async onCaptureAll() {\n if (selection.multiSelectedCount === 0) {\n showToast('No elements selected. Use Shift+Click to select multiple.');\n return;\n }\n showToast(`Capturing ${selection.multiSelectedCount} elements...`);\n const contexts = await selection.captureMultiSelection();\n const success = await sendContext(contexts);\n if (success) {\n showToast(`${contexts.length} elements captured!`);\n selection.clearMultiSelection();\n } else {\n showToast('Failed to send context. Is the dev server running?');\n }\n },\n onClose() { deactivate(); },\n onFreeze() { toggleFreeze(); },\n });\n selection.activate();\n showToast('UI Context active \\u2014 click to capture, Shift+click for multi-select');\n }\n\n function deactivate() {\n if (isFrozen) unfreezeDOM();\n selection.deactivate();\n overlay?.destroy();\n toolbar?.destroy();\n overlay = null;\n toolbar = null;\n }\n\n function toggleFreeze() {\n if (isFrozen) {\n unfreezeDOM();\n showToast('DOM unfrozen');\n } else {\n freezeDOM();\n showToast('DOM frozen \\u2014 hover states preserved');\n }\n toolbar?.updateFreezeState(isFrozen);\n }\n\n function freezeDOM() {\n isFrozen = true;\n // Disconnect all existing MutationObservers by creating a blocking one\n // This prevents DOM updates (dropdowns closing, tooltips hiding, etc.)\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n // Revert added/removed nodes\n for (const node of mutation.addedNodes) {\n if (node instanceof HTMLElement && !node.id?.includes('ui-context')) {\n node.remove();\n }\n }\n // Revert attribute changes\n if (mutation.type === 'attributes' && mutation.target instanceof HTMLElement) {\n if (!mutation.target.id?.includes('ui-context')) {\n const old = mutation.oldValue;\n if (old !== null) {\n mutation.target.setAttribute(mutation.attributeName!, old);\n }\n }\n }\n }\n });\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeOldValue: true,\n });\n frozenObservers.push(observer);\n }\n\n function unfreezeDOM() {\n isFrozen = false;\n for (const obs of frozenObservers) {\n obs.disconnect();\n }\n frozenObservers = [];\n }\n\n // Register keyboard shortcuts\n document.addEventListener('keydown', (e) => {\n // Main shortcut (Alt+X)\n const keys = shortcut.split('+');\n const needsAlt = keys.includes('alt');\n const needsCtrl = keys.includes('ctrl');\n const needsShift = keys.includes('shift');\n const mainKey = keys[keys.length - 1].toLowerCase();\n const mainCode = /^[a-z]$/.test(mainKey) ? 'Key' + mainKey.toUpperCase() : /^[0-9]$/.test(mainKey) ? 'Digit' + mainKey : '';\n\n if (\n e.altKey === needsAlt &&\n e.ctrlKey === needsCtrl &&\n e.shiftKey === needsShift &&\n (mainCode ? e.code === mainCode : e.key.toLowerCase() === mainKey)\n ) {\n e.preventDefault();\n if (selection.isActive) {\n deactivate();\n } else {\n activate();\n }\n return;\n }\n\n // Freeze shortcut: Ctrl+Shift+F (only when active)\n if (selection.isActive && e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'f') {\n e.preventDefault();\n toggleFreeze();\n }\n });\n\n // Show onboarding on first use\n showOnboarding(shortcut);\n\n return { activate, deactivate };\n}\n","'use client';\n\nimport { useEffect } from 'react';\n\ninterface UIContextDevToolsProps {\n /** URL of the context server. Default: http://localhost:19638 */\n serverUrl?: string;\n /** Toggle shortcut. Default: 'alt+x' */\n shortcut?: string;\n}\n\nexport function UIContextDevTools({ serverUrl, shortcut }: UIContextDevToolsProps = {}) {\n useEffect(() => {\n let cleanup: (() => void) | undefined;\n\n import('./index').then(({ initUIContext }) => {\n const ctx = initUIContext({\n ...(serverUrl && { wsUrl: serverUrl }),\n ...(shortcut && { shortcut }),\n });\n cleanup = () => ctx.deactivate();\n });\n\n return () => {\n cleanup?.();\n };\n }, []);\n\n return null;\n}\n"],"mappings":"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","names":["serverUrl","initUIContext"]}
|
|
1
|
+
{"version":3,"sources":["../src/ui/overlay.ts","../src/ui/toast.ts","../src/ui/toolbar.ts","../src/fiber-walker.ts","../src/context-extractor.ts","../src/screenshot.ts","../src/selection.ts","../src/transport.ts","../src/ui/onboarding.ts","../src/index.ts","../src/react.tsx"],"sourcesContent":["let hostEl: HTMLDivElement | null = null;\nlet shadowRoot: ShadowRoot | null = null;\nlet highlightEl: HTMLDivElement | null = null;\n\nexport function createOverlay(): { highlight: (rect: DOMRect | null, label?: string) => void; destroy: () => void } {\n hostEl = document.createElement('div');\n hostEl.id = 'ui-context-host';\n hostEl.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;pointer-events:none;';\n document.body.appendChild(hostEl);\n\n shadowRoot = hostEl.attachShadow({ mode: 'open' });\n\n const style = document.createElement('style');\n style.textContent = `\n .highlight {\n position: fixed;\n border: 2px solid #3b82f6;\n background: rgba(59, 130, 246, 0.1);\n pointer-events: none;\n transition: all 0.1s ease;\n border-radius: 4px;\n z-index: 2147483647;\n }\n .highlight-label {\n position: absolute;\n top: -24px;\n left: -2px;\n background: #3b82f6;\n color: white;\n font-size: 11px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n padding: 2px 6px;\n border-radius: 3px 3px 0 0;\n white-space: nowrap;\n pointer-events: none;\n }\n `;\n shadowRoot.appendChild(style);\n\n highlightEl = document.createElement('div');\n highlightEl.className = 'highlight';\n highlightEl.style.display = 'none';\n\n const labelEl = document.createElement('div');\n labelEl.className = 'highlight-label';\n highlightEl.appendChild(labelEl);\n\n shadowRoot.appendChild(highlightEl);\n\n return {\n highlight(rect: DOMRect | null, label?: string) {\n if (!rect || !highlightEl) {\n if (highlightEl) highlightEl.style.display = 'none';\n return;\n }\n highlightEl.style.display = 'block';\n highlightEl.style.top = rect.top + 'px';\n highlightEl.style.left = rect.left + 'px';\n highlightEl.style.width = rect.width + 'px';\n highlightEl.style.height = rect.height + 'px';\n const lbl = highlightEl.querySelector('.highlight-label') as HTMLDivElement;\n if (lbl && label) {\n lbl.textContent = label;\n lbl.style.display = 'block';\n } else if (lbl) {\n lbl.style.display = 'none';\n }\n },\n destroy() {\n hostEl?.remove();\n hostEl = null;\n shadowRoot = null;\n highlightEl = null;\n },\n };\n}\n","let toastContainer: HTMLDivElement | null = null;\nlet toastShadow: ShadowRoot | null = null;\n\nfunction ensureContainer() {\n if (toastContainer) return;\n toastContainer = document.createElement('div');\n toastContainer.id = 'ui-context-toast';\n toastContainer.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;pointer-events:none;';\n document.body.appendChild(toastContainer);\n toastShadow = toastContainer.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = `\n .toast {\n position: fixed;\n bottom: 24px;\n right: 24px;\n background: #1e293b;\n color: #f1f5f9;\n padding: 12px 20px;\n border-radius: 8px;\n font-size: 13px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.3);\n pointer-events: auto;\n animation: slideIn 0.3s ease, fadeOut 0.3s ease 2.7s;\n z-index: 2147483647;\n }\n @keyframes slideIn { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }\n @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } }\n `;\n toastShadow.appendChild(style);\n}\n\nexport function showToast(message: string, duration = 3000) {\n ensureContainer();\n if (!toastShadow) return;\n const el = document.createElement('div');\n el.className = 'toast';\n el.textContent = message;\n toastShadow.appendChild(el);\n setTimeout(() => el.remove(), duration);\n}\n","export function createToolbar(opts: {\n onCapture: () => void;\n onCaptureAll?: () => void;\n onClose: () => void;\n onFreeze?: () => void;\n}): { el: HTMLElement; destroy: () => void; updateBadge: (count: number) => void; updateFreezeState: (frozen: boolean) => void } {\n const host = document.createElement('div');\n host.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;';\n document.body.appendChild(host);\n\n const shadow = host.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = `\n .toolbar {\n position: fixed;\n bottom: 24px;\n left: 50%;\n transform: translateX(-50%);\n background: #1e293b;\n border: 1px solid #334155;\n border-radius: 12px;\n padding: 8px 12px;\n display: flex;\n gap: 6px;\n align-items: center;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 4px 20px rgba(0,0,0,0.4);\n }\n .toolbar-btn {\n background: #3b82f6;\n color: white;\n border: none;\n padding: 6px 14px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n }\n .toolbar-btn:hover { background: #2563eb; }\n .toolbar-btn.secondary { background: #475569; }\n .toolbar-btn.secondary:hover { background: #64748b; }\n .toolbar-btn.freeze { background: #475569; }\n .toolbar-btn.freeze:hover { background: #64748b; }\n .toolbar-btn.freeze.active { background: #f59e0b; color: #1e293b; }\n .toolbar-btn.freeze.active:hover { background: #d97706; }\n .toolbar-label {\n color: #94a3b8;\n font-size: 12px;\n padding: 0 4px;\n }\n .badge {\n display: inline-block;\n background: #f59e0b;\n color: #1e293b;\n font-size: 10px;\n font-weight: 700;\n padding: 1px 5px;\n border-radius: 10px;\n margin-left: 4px;\n }\n .badge.hidden { display: none; }\n .divider {\n width: 1px;\n height: 20px;\n background: #334155;\n }\n `;\n shadow.appendChild(style);\n\n const toolbar = document.createElement('div');\n toolbar.className = 'toolbar';\n toolbar.innerHTML = `\n <span class=\"toolbar-label\">UI Context</span>\n <div class=\"divider\"></div>\n <button class=\"toolbar-btn capture\">Capture</button>\n <button class=\"toolbar-btn secondary capture-all\" style=\"display:none\">Capture All <span class=\"badge hidden\">0</span></button>\n <div class=\"divider\"></div>\n <button class=\"toolbar-btn freeze\" title=\"Freeze DOM (Ctrl+Shift+F)\">Freeze</button>\n <button class=\"toolbar-btn secondary close\">\\u2715</button>\n `;\n shadow.appendChild(toolbar);\n\n const captureBtn = toolbar.querySelector('.capture') as HTMLButtonElement;\n const captureAllBtn = toolbar.querySelector('.capture-all') as HTMLButtonElement;\n const freezeBtn = toolbar.querySelector('.freeze') as HTMLButtonElement;\n const closeBtn = toolbar.querySelector('.close') as HTMLButtonElement;\n const badge = toolbar.querySelector('.badge') as HTMLSpanElement;\n\n captureBtn.addEventListener('click', opts.onCapture);\n captureAllBtn.addEventListener('click', () => opts.onCaptureAll?.());\n freezeBtn.addEventListener('click', () => opts.onFreeze?.());\n closeBtn.addEventListener('click', opts.onClose);\n\n return {\n el: host,\n destroy() { host.remove(); },\n updateBadge(count: number) {\n if (count > 0) {\n captureAllBtn.style.display = '';\n badge.textContent = String(count);\n badge.classList.remove('hidden');\n } else {\n captureAllBtn.style.display = 'none';\n badge.classList.add('hidden');\n }\n },\n updateFreezeState(frozen: boolean) {\n if (frozen) {\n freezeBtn.classList.add('active');\n freezeBtn.textContent = 'Frozen';\n } else {\n freezeBtn.classList.remove('active');\n freezeBtn.textContent = 'Freeze';\n }\n },\n };\n}\n","export function extractComponentHierarchy(el: HTMLElement): string[] {\n const fiber = getFiber(el);\n if (!fiber) return [];\n\n const hierarchy: string[] = [];\n let current = fiber;\n\n while (current) {\n if (typeof current.type === 'function' || typeof current.type === 'object') {\n const name = typeof current.type === 'function'\n ? current.type.displayName || current.type.name\n : current.type?.displayName || current.type?.render?.displayName || current.type?.render?.name;\n if (name && !name.startsWith('_') && name !== 'Fragment') {\n hierarchy.unshift(name);\n }\n }\n current = current.return;\n }\n\n return hierarchy;\n}\n\nfunction getFiber(el: HTMLElement): any {\n const key = Object.keys(el).find(\n k => k.startsWith('__reactFiber$') || k.startsWith('__reactInternalInstance$')\n );\n return key ? (el as any)[key] : null;\n}\n","import { ElementContext, SourceLocation } from './types';\nimport { extractComponentHierarchy } from './fiber-walker';\n\nconst STYLE_PROPERTIES = [\n 'padding', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft',\n 'margin', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft',\n 'backgroundColor', 'color', 'fontSize', 'fontWeight', 'fontFamily',\n 'borderRadius', 'display', 'flexDirection', 'justifyContent', 'alignItems',\n 'gap', 'width', 'height', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight',\n 'overflow', 'position', 'zIndex', 'opacity', 'border', 'boxShadow',\n 'lineHeight', 'letterSpacing', 'textAlign',\n];\n\nexport function extractSource(el: HTMLElement): SourceLocation | null {\n const file = el.getAttribute('data-source-file');\n const line = el.getAttribute('data-source-line');\n const col = el.getAttribute('data-source-col');\n if (!file || !line) return null;\n return {\n file,\n line: parseInt(line, 10),\n col: parseInt(col || '0', 10),\n component: el.getAttribute('data-source-component') || undefined,\n };\n}\n\nexport function extractContext(el: HTMLElement): ElementContext {\n const computed = getComputedStyle(el);\n const rect = el.getBoundingClientRect();\n const styles: Record<string, string> = {};\n for (const prop of STYLE_PROPERTIES) {\n const value = computed.getPropertyValue(\n prop.replace(/[A-Z]/g, m => '-' + m.toLowerCase())\n );\n if (value && value !== 'none' && value !== 'normal' && value !== 'auto' && value !== '0px' && value !== 'rgba(0, 0, 0, 0)') {\n styles[prop] = value;\n }\n }\n\n return {\n source: extractSource(el),\n tagName: el.tagName.toLowerCase(),\n classes: typeof el.className === 'string' ? el.className : '',\n computedStyles: styles,\n dimensions: { width: rect.width, height: rect.height, x: rect.x, y: rect.y },\n componentHierarchy: extractComponentHierarchy(el),\n url: window.location.href,\n };\n}\n","export async function captureElementScreenshot(el: HTMLElement): Promise<string | undefined> {\n try {\n // Use native canvas approach - works well for most elements\n // without requiring external dependencies like html2canvas\n const rect = el.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) return undefined;\n\n const canvas = document.createElement('canvas');\n const dpr = window.devicePixelRatio || 1;\n const padding = 8; // visual padding around element\n\n const captureWidth = Math.ceil(rect.width + padding * 2);\n const captureHeight = Math.ceil(rect.height + padding * 2);\n\n canvas.width = captureWidth * dpr;\n canvas.height = captureHeight * dpr;\n canvas.style.width = captureWidth + 'px';\n canvas.style.height = captureHeight + 'px';\n\n const ctx = canvas.getContext('2d');\n if (!ctx) return undefined;\n\n ctx.scale(dpr, dpr);\n\n // Try using html-to-image approach via SVG foreignObject\n const screenshot = await captureViaSvgForeignObject(el, rect, ctx, canvas, padding);\n if (screenshot) return screenshot;\n\n // Fallback: capture visible viewport area containing the element\n return await captureViaRange(el, rect, canvas, ctx, padding);\n } catch {\n return undefined;\n }\n}\n\nasync function captureViaSvgForeignObject(\n el: HTMLElement,\n rect: DOMRect,\n ctx: CanvasRenderingContext2D,\n canvas: HTMLCanvasElement,\n padding: number,\n): Promise<string | undefined> {\n try {\n // Clone the element to avoid modifying the original\n const clone = el.cloneNode(true) as HTMLElement;\n\n // Copy computed styles inline\n copyComputedStyles(el, clone);\n\n const width = Math.ceil(rect.width + padding * 2);\n const height = Math.ceil(rect.height + padding * 2);\n\n const svgNs = 'http://www.w3.org/2000/svg';\n const svg = document.createElementNS(svgNs, 'svg');\n svg.setAttribute('width', String(width));\n svg.setAttribute('height', String(height));\n svg.setAttribute('xmlns', svgNs);\n\n const foreignObject = document.createElementNS(svgNs, 'foreignObject');\n foreignObject.setAttribute('width', '100%');\n foreignObject.setAttribute('height', '100%');\n\n const container = document.createElement('div');\n container.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml');\n container.style.cssText = `\n width: ${width}px;\n height: ${height}px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: white;\n padding: ${padding}px;\n box-sizing: border-box;\n `;\n container.appendChild(clone);\n foreignObject.appendChild(container);\n svg.appendChild(foreignObject);\n\n const svgString = new XMLSerializer().serializeToString(svg);\n const svgBlob = new Blob([svgString], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(svgBlob);\n\n return new Promise<string | undefined>((resolve) => {\n const img = new Image();\n img.onload = () => {\n ctx.drawImage(img, 0, 0);\n URL.revokeObjectURL(url);\n try {\n resolve(canvas.toDataURL('image/png'));\n } catch {\n resolve(undefined);\n }\n };\n img.onerror = () => {\n URL.revokeObjectURL(url);\n resolve(undefined);\n };\n img.src = url;\n });\n } catch {\n return undefined;\n }\n}\n\nasync function captureViaRange(\n _el: HTMLElement,\n rect: DOMRect,\n canvas: HTMLCanvasElement,\n ctx: CanvasRenderingContext2D,\n padding: number,\n): Promise<string | undefined> {\n // Fallback: draw a placeholder with element info\n try {\n const width = canvas.width / (window.devicePixelRatio || 1);\n const height = canvas.height / (window.devicePixelRatio || 1);\n\n ctx.fillStyle = '#f8fafc';\n ctx.fillRect(0, 0, width, height);\n ctx.strokeStyle = '#3b82f6';\n ctx.lineWidth = 2;\n ctx.strokeRect(padding, padding, rect.width, rect.height);\n\n ctx.fillStyle = '#64748b';\n ctx.font = '11px -apple-system, BlinkMacSystemFont, sans-serif';\n ctx.fillText(\n `${Math.round(rect.width)} x ${Math.round(rect.height)}px`,\n padding + 4,\n padding + rect.height / 2 + 4,\n );\n\n return canvas.toDataURL('image/png');\n } catch {\n return undefined;\n }\n}\n\nfunction copyComputedStyles(source: HTMLElement, target: HTMLElement): void {\n const computed = getComputedStyle(source);\n const important = [\n 'display', 'width', 'height', 'padding', 'margin', 'border',\n 'border-radius', 'background', 'background-color', 'color',\n 'font-size', 'font-weight', 'font-family', 'line-height',\n 'text-align', 'box-shadow', 'opacity', 'flex-direction',\n 'justify-content', 'align-items', 'gap', 'overflow',\n ];\n for (const prop of important) {\n target.style.setProperty(prop, computed.getPropertyValue(prop));\n }\n\n // Recurse for children\n const sourceChildren = source.children;\n const targetChildren = target.children;\n for (let i = 0; i < sourceChildren.length && i < targetChildren.length; i++) {\n if (sourceChildren[i] instanceof HTMLElement && targetChildren[i] instanceof HTMLElement) {\n copyComputedStyles(sourceChildren[i] as HTMLElement, targetChildren[i] as HTMLElement);\n }\n }\n}\n","import { extractContext } from './context-extractor';\nimport { captureElementScreenshot } from './screenshot';\nimport { ElementContext } from './types';\n\ntype SelectionCallback = (context: ElementContext) => void;\ntype MultiSelectionCallback = (contexts: ElementContext[]) => void;\n\nexport function createSelectionHandler(opts: {\n onHover: (el: HTMLElement | null) => void;\n onSelect: SelectionCallback;\n onMultiSelect?: MultiSelectionCallback;\n onSelectionChange?: (count: number) => void;\n}) {\n let isActive = false;\n let selectedEl: HTMLElement | null = null;\n const multiSelected: Set<HTMLElement> = new Set();\n\n function handleMouseMove(e: MouseEvent) {\n if (!isActive) return;\n const target = e.target as HTMLElement;\n if (target.id === 'ui-context-host' || target.id === 'ui-context-toast' || target.closest('#ui-context-host')) return;\n opts.onHover(target);\n }\n\n function handleClick(e: MouseEvent) {\n if (!isActive) return;\n e.preventDefault();\n e.stopPropagation();\n\n const target = e.target as HTMLElement;\n if (target.id === 'ui-context-host' || target.closest('#ui-context-host')) return;\n\n // Shift+Click: add to multi-selection\n if (e.shiftKey) {\n if (multiSelected.has(target)) {\n multiSelected.delete(target);\n target.style.outline = '';\n } else {\n multiSelected.add(target);\n target.style.outline = '2px dashed #f59e0b';\n }\n opts.onSelectionChange?.(multiSelected.size);\n return;\n }\n\n selectedEl = target;\n const context = extractContext(target);\n\n captureElementScreenshot(target).then(screenshot => {\n if (screenshot) context.screenshotDataUrl = screenshot;\n opts.onSelect(context);\n });\n }\n\n return {\n activate() {\n isActive = true;\n document.addEventListener('mousemove', handleMouseMove, true);\n document.addEventListener('click', handleClick, true);\n document.body.style.cursor = 'crosshair';\n },\n deactivate() {\n isActive = false;\n selectedEl = null;\n // Clear multi-selection outlines\n for (const el of multiSelected) {\n el.style.outline = '';\n }\n multiSelected.clear();\n document.removeEventListener('mousemove', handleMouseMove, true);\n document.removeEventListener('click', handleClick, true);\n document.body.style.cursor = '';\n opts.onHover(null);\n },\n get isActive() { return isActive; },\n get selectedElement() { return selectedEl; },\n get multiSelectedElements() { return multiSelected; },\n get multiSelectedCount() { return multiSelected.size; },\n\n async captureMultiSelection(): Promise<ElementContext[]> {\n const contexts: ElementContext[] = [];\n for (const el of multiSelected) {\n const ctx = extractContext(el);\n const screenshot = await captureElementScreenshot(el);\n if (screenshot) ctx.screenshotDataUrl = screenshot;\n contexts.push(ctx);\n }\n return contexts;\n },\n\n clearMultiSelection() {\n for (const el of multiSelected) {\n el.style.outline = '';\n }\n multiSelected.clear();\n opts.onSelectionChange?.(0);\n },\n };\n}\n","import { ElementContext } from './types';\n\nconst DEFAULT_SERVER_PORT = 19638;\n\nlet serverUrl = '';\n\nexport function initTransport(url?: string) {\n serverUrl = url || `http://127.0.0.1:${DEFAULT_SERVER_PORT}`;\n}\n\nexport function sendContext(context: ElementContext | ElementContext[]): Promise<boolean> {\n return new Promise((resolve) => {\n try {\n // Strategy 1: Vite HMR WebSocket (for Vite projects)\n if (typeof import.meta !== 'undefined' && (import.meta as any).hot) {\n (import.meta as any).hot.send('ui-context:capture', context);\n resolve(true);\n return;\n }\n\n // Strategy 2: HTTP POST to standalone context server (for Next.js projects)\n fetch(`${serverUrl}/capture`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(context),\n })\n .then((res) => res.json())\n .then((result) => resolve(result.success === true))\n .catch(() => resolve(false));\n } catch {\n resolve(false);\n }\n });\n}\n","const STORAGE_KEY = 'ui-context-kit-onboarding-dismissed';\n\nexport function showOnboarding(shortcut: string): void {\n // Don't show if already dismissed\n try {\n if (localStorage.getItem(STORAGE_KEY)) return;\n } catch {\n return; // localStorage not available\n }\n\n const host = document.createElement('div');\n host.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483646;';\n document.body.appendChild(host);\n\n const shadow = host.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = `\n .banner {\n position: fixed;\n bottom: 20px;\n left: 50%;\n transform: translateX(-50%);\n background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);\n border: 1px solid #334155;\n border-radius: 12px;\n padding: 12px 20px;\n display: flex;\n gap: 12px;\n align-items: center;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 8px 32px rgba(0,0,0,0.4);\n animation: slideUp 0.4s ease;\n max-width: 480px;\n }\n @keyframes slideUp {\n from { opacity: 0; transform: translateX(-50%) translateY(20px); }\n to { opacity: 1; transform: translateX(-50%) translateY(0); }\n }\n .icon {\n font-size: 20px;\n flex-shrink: 0;\n }\n .text {\n color: #e2e8f0;\n font-size: 13px;\n line-height: 1.4;\n }\n .text strong {\n color: #60a5fa;\n }\n .kbd {\n display: inline-block;\n background: #334155;\n color: #e2e8f0;\n padding: 1px 6px;\n border-radius: 4px;\n font-size: 12px;\n font-family: monospace;\n border: 1px solid #475569;\n }\n .close-btn {\n background: none;\n border: none;\n color: #64748b;\n cursor: pointer;\n padding: 4px;\n font-size: 16px;\n flex-shrink: 0;\n }\n .close-btn:hover { color: #94a3b8; }\n `;\n shadow.appendChild(style);\n\n const shortcutDisplay = shortcut.split('+').map(k =>\n k.charAt(0).toUpperCase() + k.slice(1)\n ).join(' + ');\n\n const banner = document.createElement('div');\n banner.className = 'banner';\n banner.innerHTML = `\n <span class=\"icon\">\\u{1F3AF}</span>\n <span class=\"text\">\n <strong>UI Context Kit</strong> is ready!\n Press <kbd class=\"kbd\">${shortcutDisplay}</kbd> to select any UI element and capture its context for AI.\n Use <strong>Shift+Click</strong> for multi-select, <strong>Ctrl+Shift+F</strong> to freeze state.\n </span>\n <button class=\"close-btn\" title=\"Dismiss\">\\u2715</button>\n `;\n shadow.appendChild(banner);\n\n banner.querySelector('.close-btn')!.addEventListener('click', () => {\n host.remove();\n try {\n localStorage.setItem(STORAGE_KEY, '1');\n } catch { /* ignore */ }\n });\n\n // Auto-dismiss after 8 seconds\n setTimeout(() => {\n if (host.parentNode) {\n banner.style.transition = 'opacity 0.3s ease';\n banner.style.opacity = '0';\n setTimeout(() => host.remove(), 300);\n }\n }, 8000);\n}\n","import { createOverlay } from './ui/overlay';\nimport { showToast } from './ui/toast';\nimport { createToolbar } from './ui/toolbar';\nimport { createSelectionHandler } from './selection';\nimport { sendContext, initTransport } from './transport';\nimport { extractContext, extractSource } from './context-extractor';\nimport { showOnboarding } from './ui/onboarding';\nimport type { ElementContext } from './types';\n\nexport type { ElementContext, SourceLocation } from './types';\n\nexport interface UIContextOptions {\n shortcut?: string;\n wsUrl?: string;\n}\n\nexport function initUIContext(options: UIContextOptions = {}) {\n const { shortcut = 'alt+x' } = options;\n\n initTransport(options.wsUrl);\n\n let overlay: ReturnType<typeof createOverlay> | null = null;\n let toolbar: ReturnType<typeof createToolbar> | null = null;\n let isFrozen = false;\n let frozenObservers: MutationObserver[] = [];\n\n const selection = createSelectionHandler({\n onHover(el) {\n if (!el) {\n overlay?.highlight(null);\n return;\n }\n const rect = el.getBoundingClientRect();\n const source = extractSource(el);\n const label = source\n ? `${source.component || el.tagName.toLowerCase()} \\u00b7 ${source.file}:${source.line}`\n : el.tagName.toLowerCase();\n overlay?.highlight(rect, label);\n },\n async onSelect(context: ElementContext) {\n showToast('Capturing context...');\n const success = await sendContext(context);\n if (success) {\n showToast('Context captured!');\n } else {\n showToast('Failed to send context. Is the dev server running?');\n }\n },\n onSelectionChange(count) {\n toolbar?.updateBadge(count);\n },\n });\n\n function activate() {\n if (selection.isActive) return;\n overlay = createOverlay();\n toolbar = createToolbar({\n onCapture() {\n if (selection.selectedElement) {\n const context = extractContext(selection.selectedElement);\n sendContext(context);\n }\n },\n async onCaptureAll() {\n if (selection.multiSelectedCount === 0) {\n showToast('No elements selected. Use Shift+Click to select multiple.');\n return;\n }\n showToast(`Capturing ${selection.multiSelectedCount} elements...`);\n const contexts = await selection.captureMultiSelection();\n const success = await sendContext(contexts);\n if (success) {\n showToast(`${contexts.length} elements captured!`);\n selection.clearMultiSelection();\n } else {\n showToast('Failed to send context. Is the dev server running?');\n }\n },\n onClose() { deactivate(); },\n onFreeze() { toggleFreeze(); },\n });\n selection.activate();\n showToast('UI Context active \\u2014 click to capture, Shift+click for multi-select');\n }\n\n function deactivate() {\n if (isFrozen) unfreezeDOM();\n selection.deactivate();\n overlay?.destroy();\n toolbar?.destroy();\n overlay = null;\n toolbar = null;\n }\n\n function toggleFreeze() {\n if (isFrozen) {\n unfreezeDOM();\n showToast('DOM unfrozen');\n } else {\n freezeDOM();\n showToast('DOM frozen \\u2014 hover states preserved');\n }\n toolbar?.updateFreezeState(isFrozen);\n }\n\n function freezeDOM() {\n isFrozen = true;\n // Disconnect all existing MutationObservers by creating a blocking one\n // This prevents DOM updates (dropdowns closing, tooltips hiding, etc.)\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n // Revert added/removed nodes\n for (const node of mutation.addedNodes) {\n if (node instanceof HTMLElement && !node.id?.includes('ui-context')) {\n node.remove();\n }\n }\n // Revert attribute changes\n if (mutation.type === 'attributes' && mutation.target instanceof HTMLElement) {\n if (!mutation.target.id?.includes('ui-context')) {\n const old = mutation.oldValue;\n if (old !== null) {\n mutation.target.setAttribute(mutation.attributeName!, old);\n }\n }\n }\n }\n });\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeOldValue: true,\n });\n frozenObservers.push(observer);\n }\n\n function unfreezeDOM() {\n isFrozen = false;\n for (const obs of frozenObservers) {\n obs.disconnect();\n }\n frozenObservers = [];\n }\n\n // Register keyboard shortcuts\n document.addEventListener('keydown', (e) => {\n // Main shortcut (Alt+X)\n const keys = shortcut.split('+');\n const needsAlt = keys.includes('alt');\n const needsCtrl = keys.includes('ctrl');\n const needsShift = keys.includes('shift');\n const mainKey = keys[keys.length - 1].toLowerCase();\n const mainCode = /^[a-z]$/.test(mainKey) ? 'Key' + mainKey.toUpperCase() : /^[0-9]$/.test(mainKey) ? 'Digit' + mainKey : '';\n\n if (\n e.altKey === needsAlt &&\n e.ctrlKey === needsCtrl &&\n e.shiftKey === needsShift &&\n (mainCode ? e.code === mainCode : e.key.toLowerCase() === mainKey)\n ) {\n e.preventDefault();\n if (selection.isActive) {\n deactivate();\n } else {\n activate();\n }\n return;\n }\n\n // Freeze shortcut: Ctrl+Shift+F (only when active)\n if (selection.isActive && e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'f') {\n e.preventDefault();\n toggleFreeze();\n }\n });\n\n // Show onboarding on first use\n showOnboarding(shortcut);\n\n return { activate, deactivate };\n}\n","'use client';\n\nimport { useEffect } from 'react';\n\ninterface UIContextDevToolsProps {\n /** URL of the context server. Default: http://localhost:19638 */\n serverUrl?: string;\n /** Toggle shortcut. Default: 'alt+x' */\n shortcut?: string;\n}\n\nexport function UIContextDevTools({ serverUrl, shortcut }: UIContextDevToolsProps = {}) {\n useEffect(() => {\n let cleanup: (() => void) | undefined;\n\n import('./index').then(({ initUIContext }) => {\n const ctx = initUIContext({\n ...(serverUrl && { wsUrl: serverUrl }),\n ...(shortcut && { shortcut }),\n });\n cleanup = () => ctx.deactivate();\n });\n\n return () => {\n cleanup?.();\n };\n }, []);\n\n return null;\n}\n"],"mappings":"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","names":["serverUrl","initUIContext"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ui-context-kit/overlay",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Browser overlay for selecting UI elements and extracting context",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -23,18 +23,20 @@
|
|
|
23
23
|
"require": "./dist/inject.cjs"
|
|
24
24
|
}
|
|
25
25
|
},
|
|
26
|
-
"files": [
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"dev": "tsup --watch"
|
|
30
|
-
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist"
|
|
28
|
+
],
|
|
31
29
|
"peerDependencies": {
|
|
32
30
|
"react": ">=18.0.0",
|
|
33
31
|
"react-dom": ">=18.0.0"
|
|
34
32
|
},
|
|
35
33
|
"peerDependenciesMeta": {
|
|
36
|
-
"react": {
|
|
37
|
-
|
|
34
|
+
"react": {
|
|
35
|
+
"optional": true
|
|
36
|
+
},
|
|
37
|
+
"react-dom": {
|
|
38
|
+
"optional": true
|
|
39
|
+
}
|
|
38
40
|
},
|
|
39
41
|
"devDependencies": {
|
|
40
42
|
"@types/react": "^18.2.0",
|
|
@@ -43,5 +45,9 @@
|
|
|
43
45
|
"react-dom": "^18.2.0",
|
|
44
46
|
"tsup": "^8.0.0",
|
|
45
47
|
"typescript": "^5.4.0"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"build": "tsup",
|
|
51
|
+
"dev": "tsup --watch"
|
|
46
52
|
}
|
|
47
|
-
}
|
|
53
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ui/overlay.ts","../src/ui/toast.ts","../src/ui/toolbar.ts","../src/fiber-walker.ts","../src/context-extractor.ts","../src/screenshot.ts","../src/selection.ts","../src/transport.ts","../src/ui/onboarding.ts","../src/index.ts"],"sourcesContent":["let hostEl: HTMLDivElement | null = null;\nlet shadowRoot: ShadowRoot | null = null;\nlet highlightEl: HTMLDivElement | null = null;\n\nexport function createOverlay(): { highlight: (rect: DOMRect | null, label?: string) => void; destroy: () => void } {\n hostEl = document.createElement('div');\n hostEl.id = 'ui-context-host';\n hostEl.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;pointer-events:none;';\n document.body.appendChild(hostEl);\n\n shadowRoot = hostEl.attachShadow({ mode: 'open' });\n\n const style = document.createElement('style');\n style.textContent = `\n .highlight {\n position: fixed;\n border: 2px solid #3b82f6;\n background: rgba(59, 130, 246, 0.1);\n pointer-events: none;\n transition: all 0.1s ease;\n border-radius: 4px;\n z-index: 2147483647;\n }\n .highlight-label {\n position: absolute;\n top: -24px;\n left: -2px;\n background: #3b82f6;\n color: white;\n font-size: 11px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n padding: 2px 6px;\n border-radius: 3px 3px 0 0;\n white-space: nowrap;\n pointer-events: none;\n }\n `;\n shadowRoot.appendChild(style);\n\n highlightEl = document.createElement('div');\n highlightEl.className = 'highlight';\n highlightEl.style.display = 'none';\n\n const labelEl = document.createElement('div');\n labelEl.className = 'highlight-label';\n highlightEl.appendChild(labelEl);\n\n shadowRoot.appendChild(highlightEl);\n\n return {\n highlight(rect: DOMRect | null, label?: string) {\n if (!rect || !highlightEl) {\n if (highlightEl) highlightEl.style.display = 'none';\n return;\n }\n highlightEl.style.display = 'block';\n highlightEl.style.top = rect.top + 'px';\n highlightEl.style.left = rect.left + 'px';\n highlightEl.style.width = rect.width + 'px';\n highlightEl.style.height = rect.height + 'px';\n const lbl = highlightEl.querySelector('.highlight-label') as HTMLDivElement;\n if (lbl && label) {\n lbl.textContent = label;\n lbl.style.display = 'block';\n } else if (lbl) {\n lbl.style.display = 'none';\n }\n },\n destroy() {\n hostEl?.remove();\n hostEl = null;\n shadowRoot = null;\n highlightEl = null;\n },\n };\n}\n","let toastContainer: HTMLDivElement | null = null;\nlet toastShadow: ShadowRoot | null = null;\n\nfunction ensureContainer() {\n if (toastContainer) return;\n toastContainer = document.createElement('div');\n toastContainer.id = 'ui-context-toast';\n toastContainer.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;pointer-events:none;';\n document.body.appendChild(toastContainer);\n toastShadow = toastContainer.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = `\n .toast {\n position: fixed;\n bottom: 24px;\n right: 24px;\n background: #1e293b;\n color: #f1f5f9;\n padding: 12px 20px;\n border-radius: 8px;\n font-size: 13px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 4px 12px rgba(0,0,0,0.3);\n pointer-events: auto;\n animation: slideIn 0.3s ease, fadeOut 0.3s ease 2.7s;\n z-index: 2147483647;\n }\n @keyframes slideIn { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }\n @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } }\n `;\n toastShadow.appendChild(style);\n}\n\nexport function showToast(message: string, duration = 3000) {\n ensureContainer();\n if (!toastShadow) return;\n const el = document.createElement('div');\n el.className = 'toast';\n el.textContent = message;\n toastShadow.appendChild(el);\n setTimeout(() => el.remove(), duration);\n}\n","export function createToolbar(opts: {\n onCapture: () => void;\n onCaptureAll?: () => void;\n onClose: () => void;\n onFreeze?: () => void;\n}): { el: HTMLElement; destroy: () => void; updateBadge: (count: number) => void; updateFreezeState: (frozen: boolean) => void } {\n const host = document.createElement('div');\n host.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;';\n document.body.appendChild(host);\n\n const shadow = host.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = `\n .toolbar {\n position: fixed;\n bottom: 24px;\n left: 50%;\n transform: translateX(-50%);\n background: #1e293b;\n border: 1px solid #334155;\n border-radius: 12px;\n padding: 8px 12px;\n display: flex;\n gap: 6px;\n align-items: center;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 4px 20px rgba(0,0,0,0.4);\n }\n .toolbar-btn {\n background: #3b82f6;\n color: white;\n border: none;\n padding: 6px 14px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n }\n .toolbar-btn:hover { background: #2563eb; }\n .toolbar-btn.secondary { background: #475569; }\n .toolbar-btn.secondary:hover { background: #64748b; }\n .toolbar-btn.freeze { background: #475569; }\n .toolbar-btn.freeze:hover { background: #64748b; }\n .toolbar-btn.freeze.active { background: #f59e0b; color: #1e293b; }\n .toolbar-btn.freeze.active:hover { background: #d97706; }\n .toolbar-label {\n color: #94a3b8;\n font-size: 12px;\n padding: 0 4px;\n }\n .badge {\n display: inline-block;\n background: #f59e0b;\n color: #1e293b;\n font-size: 10px;\n font-weight: 700;\n padding: 1px 5px;\n border-radius: 10px;\n margin-left: 4px;\n }\n .badge.hidden { display: none; }\n .divider {\n width: 1px;\n height: 20px;\n background: #334155;\n }\n `;\n shadow.appendChild(style);\n\n const toolbar = document.createElement('div');\n toolbar.className = 'toolbar';\n toolbar.innerHTML = `\n <span class=\"toolbar-label\">UI Context</span>\n <div class=\"divider\"></div>\n <button class=\"toolbar-btn capture\">Capture</button>\n <button class=\"toolbar-btn secondary capture-all\" style=\"display:none\">Capture All <span class=\"badge hidden\">0</span></button>\n <div class=\"divider\"></div>\n <button class=\"toolbar-btn freeze\" title=\"Freeze DOM (Ctrl+Shift+F)\">Freeze</button>\n <button class=\"toolbar-btn secondary close\">\\u2715</button>\n `;\n shadow.appendChild(toolbar);\n\n const captureBtn = toolbar.querySelector('.capture') as HTMLButtonElement;\n const captureAllBtn = toolbar.querySelector('.capture-all') as HTMLButtonElement;\n const freezeBtn = toolbar.querySelector('.freeze') as HTMLButtonElement;\n const closeBtn = toolbar.querySelector('.close') as HTMLButtonElement;\n const badge = toolbar.querySelector('.badge') as HTMLSpanElement;\n\n captureBtn.addEventListener('click', opts.onCapture);\n captureAllBtn.addEventListener('click', () => opts.onCaptureAll?.());\n freezeBtn.addEventListener('click', () => opts.onFreeze?.());\n closeBtn.addEventListener('click', opts.onClose);\n\n return {\n el: host,\n destroy() { host.remove(); },\n updateBadge(count: number) {\n if (count > 0) {\n captureAllBtn.style.display = '';\n badge.textContent = String(count);\n badge.classList.remove('hidden');\n } else {\n captureAllBtn.style.display = 'none';\n badge.classList.add('hidden');\n }\n },\n updateFreezeState(frozen: boolean) {\n if (frozen) {\n freezeBtn.classList.add('active');\n freezeBtn.textContent = 'Frozen';\n } else {\n freezeBtn.classList.remove('active');\n freezeBtn.textContent = 'Freeze';\n }\n },\n };\n}\n","export function extractComponentHierarchy(el: HTMLElement): string[] {\n const fiber = getFiber(el);\n if (!fiber) return [];\n\n const hierarchy: string[] = [];\n let current = fiber;\n\n while (current) {\n if (typeof current.type === 'function' || typeof current.type === 'object') {\n const name = typeof current.type === 'function'\n ? current.type.displayName || current.type.name\n : current.type?.displayName || current.type?.render?.displayName || current.type?.render?.name;\n if (name && !name.startsWith('_') && name !== 'Fragment') {\n hierarchy.unshift(name);\n }\n }\n current = current.return;\n }\n\n return hierarchy;\n}\n\nfunction getFiber(el: HTMLElement): any {\n const key = Object.keys(el).find(\n k => k.startsWith('__reactFiber$') || k.startsWith('__reactInternalInstance$')\n );\n return key ? (el as any)[key] : null;\n}\n","import { ElementContext, SourceLocation } from './types';\nimport { extractComponentHierarchy } from './fiber-walker';\n\nconst STYLE_PROPERTIES = [\n 'padding', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft',\n 'margin', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft',\n 'backgroundColor', 'color', 'fontSize', 'fontWeight', 'fontFamily',\n 'borderRadius', 'display', 'flexDirection', 'justifyContent', 'alignItems',\n 'gap', 'width', 'height', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight',\n 'overflow', 'position', 'zIndex', 'opacity', 'border', 'boxShadow',\n 'lineHeight', 'letterSpacing', 'textAlign',\n];\n\nexport function extractSource(el: HTMLElement): SourceLocation | null {\n const file = el.getAttribute('data-source-file');\n const line = el.getAttribute('data-source-line');\n const col = el.getAttribute('data-source-col');\n if (!file || !line) return null;\n return {\n file,\n line: parseInt(line, 10),\n col: parseInt(col || '0', 10),\n component: el.getAttribute('data-source-component') || undefined,\n };\n}\n\nexport function extractContext(el: HTMLElement): ElementContext {\n const computed = getComputedStyle(el);\n const rect = el.getBoundingClientRect();\n const styles: Record<string, string> = {};\n for (const prop of STYLE_PROPERTIES) {\n const value = computed.getPropertyValue(\n prop.replace(/[A-Z]/g, m => '-' + m.toLowerCase())\n );\n if (value && value !== 'none' && value !== 'normal' && value !== 'auto' && value !== '0px' && value !== 'rgba(0, 0, 0, 0)') {\n styles[prop] = value;\n }\n }\n\n return {\n source: extractSource(el),\n tagName: el.tagName.toLowerCase(),\n classes: typeof el.className === 'string' ? el.className : '',\n computedStyles: styles,\n dimensions: { width: rect.width, height: rect.height, x: rect.x, y: rect.y },\n componentHierarchy: extractComponentHierarchy(el),\n url: window.location.href,\n };\n}\n","export async function captureElementScreenshot(el: HTMLElement): Promise<string | undefined> {\n try {\n // Use native canvas approach - works well for most elements\n // without requiring external dependencies like html2canvas\n const rect = el.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) return undefined;\n\n const canvas = document.createElement('canvas');\n const dpr = window.devicePixelRatio || 1;\n const padding = 8; // visual padding around element\n\n const captureWidth = Math.ceil(rect.width + padding * 2);\n const captureHeight = Math.ceil(rect.height + padding * 2);\n\n canvas.width = captureWidth * dpr;\n canvas.height = captureHeight * dpr;\n canvas.style.width = captureWidth + 'px';\n canvas.style.height = captureHeight + 'px';\n\n const ctx = canvas.getContext('2d');\n if (!ctx) return undefined;\n\n ctx.scale(dpr, dpr);\n\n // Try using html-to-image approach via SVG foreignObject\n const screenshot = await captureViaSvgForeignObject(el, rect, ctx, canvas, padding);\n if (screenshot) return screenshot;\n\n // Fallback: capture visible viewport area containing the element\n return await captureViaRange(el, rect, canvas, ctx, padding);\n } catch {\n return undefined;\n }\n}\n\nasync function captureViaSvgForeignObject(\n el: HTMLElement,\n rect: DOMRect,\n ctx: CanvasRenderingContext2D,\n canvas: HTMLCanvasElement,\n padding: number,\n): Promise<string | undefined> {\n try {\n // Clone the element to avoid modifying the original\n const clone = el.cloneNode(true) as HTMLElement;\n\n // Copy computed styles inline\n copyComputedStyles(el, clone);\n\n const width = Math.ceil(rect.width + padding * 2);\n const height = Math.ceil(rect.height + padding * 2);\n\n const svgNs = 'http://www.w3.org/2000/svg';\n const svg = document.createElementNS(svgNs, 'svg');\n svg.setAttribute('width', String(width));\n svg.setAttribute('height', String(height));\n svg.setAttribute('xmlns', svgNs);\n\n const foreignObject = document.createElementNS(svgNs, 'foreignObject');\n foreignObject.setAttribute('width', '100%');\n foreignObject.setAttribute('height', '100%');\n\n const container = document.createElement('div');\n container.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml');\n container.style.cssText = `\n width: ${width}px;\n height: ${height}px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: white;\n padding: ${padding}px;\n box-sizing: border-box;\n `;\n container.appendChild(clone);\n foreignObject.appendChild(container);\n svg.appendChild(foreignObject);\n\n const svgString = new XMLSerializer().serializeToString(svg);\n const svgBlob = new Blob([svgString], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(svgBlob);\n\n return new Promise<string | undefined>((resolve) => {\n const img = new Image();\n img.onload = () => {\n ctx.drawImage(img, 0, 0);\n URL.revokeObjectURL(url);\n try {\n resolve(canvas.toDataURL('image/png'));\n } catch {\n resolve(undefined);\n }\n };\n img.onerror = () => {\n URL.revokeObjectURL(url);\n resolve(undefined);\n };\n img.src = url;\n });\n } catch {\n return undefined;\n }\n}\n\nasync function captureViaRange(\n _el: HTMLElement,\n rect: DOMRect,\n canvas: HTMLCanvasElement,\n ctx: CanvasRenderingContext2D,\n padding: number,\n): Promise<string | undefined> {\n // Fallback: draw a placeholder with element info\n try {\n const width = canvas.width / (window.devicePixelRatio || 1);\n const height = canvas.height / (window.devicePixelRatio || 1);\n\n ctx.fillStyle = '#f8fafc';\n ctx.fillRect(0, 0, width, height);\n ctx.strokeStyle = '#3b82f6';\n ctx.lineWidth = 2;\n ctx.strokeRect(padding, padding, rect.width, rect.height);\n\n ctx.fillStyle = '#64748b';\n ctx.font = '11px -apple-system, BlinkMacSystemFont, sans-serif';\n ctx.fillText(\n `${Math.round(rect.width)} x ${Math.round(rect.height)}px`,\n padding + 4,\n padding + rect.height / 2 + 4,\n );\n\n return canvas.toDataURL('image/png');\n } catch {\n return undefined;\n }\n}\n\nfunction copyComputedStyles(source: HTMLElement, target: HTMLElement): void {\n const computed = getComputedStyle(source);\n const important = [\n 'display', 'width', 'height', 'padding', 'margin', 'border',\n 'border-radius', 'background', 'background-color', 'color',\n 'font-size', 'font-weight', 'font-family', 'line-height',\n 'text-align', 'box-shadow', 'opacity', 'flex-direction',\n 'justify-content', 'align-items', 'gap', 'overflow',\n ];\n for (const prop of important) {\n target.style.setProperty(prop, computed.getPropertyValue(prop));\n }\n\n // Recurse for children\n const sourceChildren = source.children;\n const targetChildren = target.children;\n for (let i = 0; i < sourceChildren.length && i < targetChildren.length; i++) {\n if (sourceChildren[i] instanceof HTMLElement && targetChildren[i] instanceof HTMLElement) {\n copyComputedStyles(sourceChildren[i] as HTMLElement, targetChildren[i] as HTMLElement);\n }\n }\n}\n","import { extractContext } from './context-extractor';\nimport { captureElementScreenshot } from './screenshot';\nimport { ElementContext } from './types';\n\ntype SelectionCallback = (context: ElementContext) => void;\ntype MultiSelectionCallback = (contexts: ElementContext[]) => void;\n\nexport function createSelectionHandler(opts: {\n onHover: (el: HTMLElement | null) => void;\n onSelect: SelectionCallback;\n onMultiSelect?: MultiSelectionCallback;\n onSelectionChange?: (count: number) => void;\n}) {\n let isActive = false;\n let selectedEl: HTMLElement | null = null;\n const multiSelected: Set<HTMLElement> = new Set();\n\n function handleMouseMove(e: MouseEvent) {\n if (!isActive) return;\n const target = e.target as HTMLElement;\n if (target.id === 'ui-context-host' || target.id === 'ui-context-toast' || target.closest('#ui-context-host')) return;\n opts.onHover(target);\n }\n\n function handleClick(e: MouseEvent) {\n if (!isActive) return;\n e.preventDefault();\n e.stopPropagation();\n\n const target = e.target as HTMLElement;\n if (target.id === 'ui-context-host' || target.closest('#ui-context-host')) return;\n\n // Shift+Click: add to multi-selection\n if (e.shiftKey) {\n if (multiSelected.has(target)) {\n multiSelected.delete(target);\n target.style.outline = '';\n } else {\n multiSelected.add(target);\n target.style.outline = '2px dashed #f59e0b';\n }\n opts.onSelectionChange?.(multiSelected.size);\n return;\n }\n\n selectedEl = target;\n const context = extractContext(target);\n\n captureElementScreenshot(target).then(screenshot => {\n if (screenshot) context.screenshotDataUrl = screenshot;\n opts.onSelect(context);\n });\n }\n\n return {\n activate() {\n isActive = true;\n document.addEventListener('mousemove', handleMouseMove, true);\n document.addEventListener('click', handleClick, true);\n document.body.style.cursor = 'crosshair';\n },\n deactivate() {\n isActive = false;\n selectedEl = null;\n // Clear multi-selection outlines\n for (const el of multiSelected) {\n el.style.outline = '';\n }\n multiSelected.clear();\n document.removeEventListener('mousemove', handleMouseMove, true);\n document.removeEventListener('click', handleClick, true);\n document.body.style.cursor = '';\n opts.onHover(null);\n },\n get isActive() { return isActive; },\n get selectedElement() { return selectedEl; },\n get multiSelectedElements() { return multiSelected; },\n get multiSelectedCount() { return multiSelected.size; },\n\n async captureMultiSelection(): Promise<ElementContext[]> {\n const contexts: ElementContext[] = [];\n for (const el of multiSelected) {\n const ctx = extractContext(el);\n const screenshot = await captureElementScreenshot(el);\n if (screenshot) ctx.screenshotDataUrl = screenshot;\n contexts.push(ctx);\n }\n return contexts;\n },\n\n clearMultiSelection() {\n for (const el of multiSelected) {\n el.style.outline = '';\n }\n multiSelected.clear();\n opts.onSelectionChange?.(0);\n },\n };\n}\n","import { ElementContext } from './types';\n\nconst DEFAULT_SERVER_PORT = 19638;\n\nlet serverUrl = '';\n\nexport function initTransport(url?: string) {\n serverUrl = url || `http://${location.hostname}:${DEFAULT_SERVER_PORT}`;\n}\n\nexport function sendContext(context: ElementContext | ElementContext[]): Promise<boolean> {\n return new Promise((resolve) => {\n try {\n // Strategy 1: Vite HMR WebSocket (for Vite projects)\n if (typeof import.meta !== 'undefined' && (import.meta as any).hot) {\n (import.meta as any).hot.send('ui-context:capture', context);\n resolve(true);\n return;\n }\n\n // Strategy 2: HTTP POST to standalone context server (for Next.js projects)\n fetch(`${serverUrl}/capture`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(context),\n })\n .then((res) => res.json())\n .then((result) => resolve(result.success === true))\n .catch(() => resolve(false));\n } catch {\n resolve(false);\n }\n });\n}\n","const STORAGE_KEY = 'ui-context-kit-onboarding-dismissed';\n\nexport function showOnboarding(shortcut: string): void {\n // Don't show if already dismissed\n try {\n if (localStorage.getItem(STORAGE_KEY)) return;\n } catch {\n return; // localStorage not available\n }\n\n const host = document.createElement('div');\n host.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483646;';\n document.body.appendChild(host);\n\n const shadow = host.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = `\n .banner {\n position: fixed;\n bottom: 20px;\n left: 50%;\n transform: translateX(-50%);\n background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);\n border: 1px solid #334155;\n border-radius: 12px;\n padding: 12px 20px;\n display: flex;\n gap: 12px;\n align-items: center;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 8px 32px rgba(0,0,0,0.4);\n animation: slideUp 0.4s ease;\n max-width: 480px;\n }\n @keyframes slideUp {\n from { opacity: 0; transform: translateX(-50%) translateY(20px); }\n to { opacity: 1; transform: translateX(-50%) translateY(0); }\n }\n .icon {\n font-size: 20px;\n flex-shrink: 0;\n }\n .text {\n color: #e2e8f0;\n font-size: 13px;\n line-height: 1.4;\n }\n .text strong {\n color: #60a5fa;\n }\n .kbd {\n display: inline-block;\n background: #334155;\n color: #e2e8f0;\n padding: 1px 6px;\n border-radius: 4px;\n font-size: 12px;\n font-family: monospace;\n border: 1px solid #475569;\n }\n .close-btn {\n background: none;\n border: none;\n color: #64748b;\n cursor: pointer;\n padding: 4px;\n font-size: 16px;\n flex-shrink: 0;\n }\n .close-btn:hover { color: #94a3b8; }\n `;\n shadow.appendChild(style);\n\n const shortcutDisplay = shortcut.split('+').map(k =>\n k.charAt(0).toUpperCase() + k.slice(1)\n ).join(' + ');\n\n const banner = document.createElement('div');\n banner.className = 'banner';\n banner.innerHTML = `\n <span class=\"icon\">\\u{1F3AF}</span>\n <span class=\"text\">\n <strong>UI Context Kit</strong> is ready!\n Press <kbd class=\"kbd\">${shortcutDisplay}</kbd> to select any UI element and capture its context for AI.\n Use <strong>Shift+Click</strong> for multi-select, <strong>Ctrl+Shift+F</strong> to freeze state.\n </span>\n <button class=\"close-btn\" title=\"Dismiss\">\\u2715</button>\n `;\n shadow.appendChild(banner);\n\n banner.querySelector('.close-btn')!.addEventListener('click', () => {\n host.remove();\n try {\n localStorage.setItem(STORAGE_KEY, '1');\n } catch { /* ignore */ }\n });\n\n // Auto-dismiss after 8 seconds\n setTimeout(() => {\n if (host.parentNode) {\n banner.style.transition = 'opacity 0.3s ease';\n banner.style.opacity = '0';\n setTimeout(() => host.remove(), 300);\n }\n }, 8000);\n}\n","import { createOverlay } from './ui/overlay';\nimport { showToast } from './ui/toast';\nimport { createToolbar } from './ui/toolbar';\nimport { createSelectionHandler } from './selection';\nimport { sendContext, initTransport } from './transport';\nimport { extractContext, extractSource } from './context-extractor';\nimport { showOnboarding } from './ui/onboarding';\nimport type { ElementContext } from './types';\n\nexport type { ElementContext, SourceLocation } from './types';\n\nexport interface UIContextOptions {\n shortcut?: string;\n wsUrl?: string;\n}\n\nexport function initUIContext(options: UIContextOptions = {}) {\n const { shortcut = 'alt+x' } = options;\n\n initTransport(options.wsUrl);\n\n let overlay: ReturnType<typeof createOverlay> | null = null;\n let toolbar: ReturnType<typeof createToolbar> | null = null;\n let isFrozen = false;\n let frozenObservers: MutationObserver[] = [];\n\n const selection = createSelectionHandler({\n onHover(el) {\n if (!el) {\n overlay?.highlight(null);\n return;\n }\n const rect = el.getBoundingClientRect();\n const source = extractSource(el);\n const label = source\n ? `${source.component || el.tagName.toLowerCase()} \\u00b7 ${source.file}:${source.line}`\n : el.tagName.toLowerCase();\n overlay?.highlight(rect, label);\n },\n async onSelect(context: ElementContext) {\n showToast('Capturing context...');\n const success = await sendContext(context);\n if (success) {\n showToast('Context captured!');\n } else {\n showToast('Failed to send context. Is the dev server running?');\n }\n },\n onSelectionChange(count) {\n toolbar?.updateBadge(count);\n },\n });\n\n function activate() {\n if (selection.isActive) return;\n overlay = createOverlay();\n toolbar = createToolbar({\n onCapture() {\n if (selection.selectedElement) {\n const context = extractContext(selection.selectedElement);\n sendContext(context);\n }\n },\n async onCaptureAll() {\n if (selection.multiSelectedCount === 0) {\n showToast('No elements selected. Use Shift+Click to select multiple.');\n return;\n }\n showToast(`Capturing ${selection.multiSelectedCount} elements...`);\n const contexts = await selection.captureMultiSelection();\n const success = await sendContext(contexts);\n if (success) {\n showToast(`${contexts.length} elements captured!`);\n selection.clearMultiSelection();\n } else {\n showToast('Failed to send context. Is the dev server running?');\n }\n },\n onClose() { deactivate(); },\n onFreeze() { toggleFreeze(); },\n });\n selection.activate();\n showToast('UI Context active \\u2014 click to capture, Shift+click for multi-select');\n }\n\n function deactivate() {\n if (isFrozen) unfreezeDOM();\n selection.deactivate();\n overlay?.destroy();\n toolbar?.destroy();\n overlay = null;\n toolbar = null;\n }\n\n function toggleFreeze() {\n if (isFrozen) {\n unfreezeDOM();\n showToast('DOM unfrozen');\n } else {\n freezeDOM();\n showToast('DOM frozen \\u2014 hover states preserved');\n }\n toolbar?.updateFreezeState(isFrozen);\n }\n\n function freezeDOM() {\n isFrozen = true;\n // Disconnect all existing MutationObservers by creating a blocking one\n // This prevents DOM updates (dropdowns closing, tooltips hiding, etc.)\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n // Revert added/removed nodes\n for (const node of mutation.addedNodes) {\n if (node instanceof HTMLElement && !node.id?.includes('ui-context')) {\n node.remove();\n }\n }\n // Revert attribute changes\n if (mutation.type === 'attributes' && mutation.target instanceof HTMLElement) {\n if (!mutation.target.id?.includes('ui-context')) {\n const old = mutation.oldValue;\n if (old !== null) {\n mutation.target.setAttribute(mutation.attributeName!, old);\n }\n }\n }\n }\n });\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeOldValue: true,\n });\n frozenObservers.push(observer);\n }\n\n function unfreezeDOM() {\n isFrozen = false;\n for (const obs of frozenObservers) {\n obs.disconnect();\n }\n frozenObservers = [];\n }\n\n // Register keyboard shortcuts\n document.addEventListener('keydown', (e) => {\n // Main shortcut (Alt+X)\n const keys = shortcut.split('+');\n const needsAlt = keys.includes('alt');\n const needsCtrl = keys.includes('ctrl');\n const needsShift = keys.includes('shift');\n const mainKey = keys[keys.length - 1].toLowerCase();\n const mainCode = /^[a-z]$/.test(mainKey) ? 'Key' + mainKey.toUpperCase() : /^[0-9]$/.test(mainKey) ? 'Digit' + mainKey : '';\n\n if (\n e.altKey === needsAlt &&\n e.ctrlKey === needsCtrl &&\n e.shiftKey === needsShift &&\n (mainCode ? e.code === mainCode : e.key.toLowerCase() === mainKey)\n ) {\n e.preventDefault();\n if (selection.isActive) {\n deactivate();\n } else {\n activate();\n }\n return;\n }\n\n // Freeze shortcut: Ctrl+Shift+F (only when active)\n if (selection.isActive && e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'f') {\n e.preventDefault();\n toggleFreeze();\n }\n });\n\n // Show onboarding on first use\n showOnboarding(shortcut);\n\n return { activate, deactivate };\n}\n"],"mappings":"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","names":[]}
|