@ui-context-kit/bridge 0.1.1 → 0.2.0

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/index.cjs CHANGED
@@ -813,8 +813,9 @@ function getOverlayCode(shortcut) {
813
813
  var needsCtrl = keys.indexOf('ctrl') !== -1;
814
814
  var needsShift = keys.indexOf('shift') !== -1;
815
815
  var mainKey = keys[keys.length - 1].toLowerCase();
816
+ var mainCode = /^[a-z]$/.test(mainKey) ? 'Key' + mainKey.toUpperCase() : /^[0-9]$/.test(mainKey) ? 'Digit' + mainKey : '';
816
817
 
817
- if (e.altKey === needsAlt && e.ctrlKey === needsCtrl && e.shiftKey === needsShift && e.key.toLowerCase() === mainKey) {
818
+ if (e.altKey === needsAlt && e.ctrlKey === needsCtrl && e.shiftKey === needsShift && (mainCode ? e.code === mainCode : e.key.toLowerCase() === mainKey)) {
818
819
  e.preventDefault();
819
820
  isActive ? deactivate() : activate();
820
821
  return;
@@ -883,11 +884,118 @@ function getOverlayCode(shortcut) {
883
884
  }
884
885
 
885
886
  // src/next-wrapper.ts
886
- function withUIContext(nextConfig = {}, _options) {
887
+ var import_path3 = __toESM(require("path"), 1);
888
+ var import_url = require("url");
889
+
890
+ // src/next-server.ts
891
+ var import_http = __toESM(require("http"), 1);
892
+ var DEFAULT_PORT = 19638;
893
+ var serverInstance = null;
894
+ function startContextServer(options = {}) {
895
+ if (serverInstance) return;
896
+ const port = DEFAULT_PORT;
897
+ const outputDir = options.outputDir || ".ui-context";
898
+ const shouldCopy = options.clipboard !== false;
899
+ const projectRoot = process.cwd();
900
+ serverInstance = import_http.default.createServer((req, res) => {
901
+ res.setHeader("Access-Control-Allow-Origin", "*");
902
+ res.setHeader("Access-Control-Allow-Methods", "POST, OPTIONS");
903
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type");
904
+ if (req.method === "OPTIONS") {
905
+ res.writeHead(204);
906
+ res.end();
907
+ return;
908
+ }
909
+ if (req.method === "POST" && req.url === "/capture") {
910
+ let body = "";
911
+ req.on("data", (chunk) => {
912
+ body += chunk;
913
+ });
914
+ req.on("end", async () => {
915
+ try {
916
+ const data = JSON.parse(body);
917
+ console.log(
918
+ `[ui-context-kit] Received context capture (${Array.isArray(data) ? data.length : 1} element${Array.isArray(data) && data.length > 1 ? "s" : ""})`
919
+ );
920
+ const filePath = await writeContext(data, projectRoot, outputDir);
921
+ if (shouldCopy) {
922
+ try {
923
+ const fs3 = await import("fs");
924
+ const content = fs3.readFileSync(filePath, "utf-8");
925
+ await copyToClipboard(content);
926
+ console.log("[ui-context-kit] Context copied to clipboard");
927
+ } catch {
928
+ }
929
+ }
930
+ res.writeHead(200, { "Content-Type": "application/json" });
931
+ res.end(JSON.stringify({ success: true }));
932
+ } catch (err) {
933
+ console.error("[ui-context-kit] Error writing context:", err);
934
+ res.writeHead(500, { "Content-Type": "application/json" });
935
+ res.end(JSON.stringify({ success: false, error: err.message }));
936
+ }
937
+ });
938
+ return;
939
+ }
940
+ res.writeHead(404);
941
+ res.end();
942
+ });
943
+ serverInstance.listen(port, () => {
944
+ console.log(`[ui-context-kit] Context server running on http://localhost:${port}`);
945
+ });
946
+ serverInstance.on("error", (err) => {
947
+ if (err.code === "EADDRINUSE") {
948
+ console.log(`[ui-context-kit] Context server already running on port ${port}`);
949
+ serverInstance = null;
950
+ } else {
951
+ console.error("[ui-context-kit] Context server error:", err);
952
+ serverInstance = null;
953
+ }
954
+ });
955
+ }
956
+
957
+ // src/next-wrapper.ts
958
+ var import_meta = {};
959
+ function resolveLoaderPath() {
960
+ try {
961
+ const __dirname2 = import_path3.default.dirname((0, import_url.fileURLToPath)(import_meta.url));
962
+ return import_path3.default.resolve(__dirname2, "next-loader.cjs");
963
+ } catch {
964
+ return import_path3.default.resolve(__dirname, "next-loader.cjs");
965
+ }
966
+ }
967
+ function withUIContext(nextConfig = {}, options) {
887
968
  if (process.env.NODE_ENV !== "development") return nextConfig;
969
+ startContextServer(options);
970
+ const loaderPath = resolveLoaderPath();
888
971
  return {
889
972
  ...nextConfig,
973
+ // Turbopack support
974
+ experimental: {
975
+ ...nextConfig.experimental,
976
+ turbo: {
977
+ ...nextConfig.experimental?.turbo,
978
+ rules: {
979
+ ...nextConfig.experimental?.turbo?.rules,
980
+ "*.tsx": {
981
+ loaders: [loaderPath],
982
+ as: "*.tsx"
983
+ },
984
+ "*.jsx": {
985
+ loaders: [loaderPath],
986
+ as: "*.jsx"
987
+ }
988
+ }
989
+ }
990
+ },
991
+ // Webpack support
890
992
  webpack(config, context) {
993
+ config.module.rules.unshift({
994
+ test: /\.(jsx|tsx)$/,
995
+ exclude: /node_modules/,
996
+ enforce: "pre",
997
+ use: [{ loader: loaderPath }]
998
+ });
891
999
  if (typeof nextConfig.webpack === "function") {
892
1000
  config = nextConfig.webpack(config, context);
893
1001
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/vite-plugin.ts","../src/context-writer.ts","../src/clipboard.ts","../src/ws-server.ts","../src/next-wrapper.ts"],"sourcesContent":["import { createVitePlugin } from './vite-plugin';\nimport { writeContext } from './context-writer';\nimport { withUIContext } from './next-wrapper';\nimport type { UIContextKitOptions } from './types';\n\n/**\n * Vite plugin for UI Context Kit.\n * Enables browser-based element selection and context capture for AI coding assistants.\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { uiContextKit } from '@ui-context-kit/bridge'\n * export default defineConfig({\n * plugins: [react(), uiContextKit()]\n * })\n * ```\n */\nexport function uiContextKit(options?: UIContextKitOptions) {\n return createVitePlugin(options);\n}\n\nexport { writeContext, withUIContext };\nexport type { UIContextKitOptions, ElementContext, SourceLocation } from './types';\n","import type { Plugin } from 'vite';\nimport path from 'path';\nimport fs from 'fs';\nimport { injectSourceAttributes } from '@ui-context-kit/babel-plugin';\nimport { setupWebSocket } from './ws-server';\nimport type { UIContextKitOptions } from './types';\n\nconst JSX_EXTENSIONS = /\\.(jsx|tsx)$/;\nconst VIRTUAL_MODULE_ID = 'virtual:ui-context-overlay';\nconst RESOLVED_VIRTUAL_MODULE_ID = '\\0' + VIRTUAL_MODULE_ID;\n\nexport function createVitePlugin(options: UIContextKitOptions = {}): Plugin[] {\n const {\n shortcut = 'alt+x',\n include,\n exclude = ['node_modules'],\n } = options;\n\n let projectRoot = '';\n\n const transformPlugin: Plugin = {\n name: 'ui-context-kit:transform',\n enforce: 'pre',\n apply: 'serve',\n\n configResolved(config) {\n projectRoot = config.root;\n },\n\n transform(code, id) {\n if (!JSX_EXTENSIONS.test(id)) return null;\n\n const relativePath = path.relative(projectRoot, id);\n if (exclude?.some(p => relativePath.includes(p))) return null;\n if (include && !include.some(p => relativePath.includes(p))) return null;\n if (id.includes('\\0') || id.includes('node_modules')) return null;\n\n const filePath = path.relative(projectRoot, id);\n\n let originalCode: string | undefined;\n try {\n originalCode = fs.readFileSync(id, 'utf-8');\n } catch {\n // ignore read errors\n }\n\n const result = injectSourceAttributes(code, filePath, originalCode);\n if (!result) return null;\n\n return { code: result.code, map: result.map };\n },\n };\n\n const overlayPlugin: Plugin = {\n name: 'ui-context-kit:overlay',\n apply: 'serve',\n\n resolveId(id) {\n if (id === VIRTUAL_MODULE_ID) return RESOLVED_VIRTUAL_MODULE_ID;\n },\n\n load(id) {\n if (id === RESOLVED_VIRTUAL_MODULE_ID) {\n return getOverlayCode(shortcut);\n }\n },\n\n configureServer(server) {\n setupWebSocket(server, options);\n },\n\n transformIndexHtml() {\n return [\n {\n tag: 'script',\n attrs: { type: 'module', src: `/@id/${VIRTUAL_MODULE_ID}` },\n injectTo: 'body' as const,\n },\n ];\n },\n };\n\n return [transformPlugin, overlayPlugin];\n}\n\nfunction getOverlayCode(shortcut: string): string {\n return `\n// UI Context Kit - Overlay (auto-injected in dev mode)\n(function() {\n if (typeof window === 'undefined') return;\n\n var isActive = false;\n var highlightEl = null;\n var toolbarEl = null;\n var selectedEl = null;\n var isFrozen = false;\n var frozenObservers = [];\n var multiSelected = new Set();\n\n var SHORTCUT = '${shortcut}';\n var ONBOARDING_KEY = 'ui-context-kit-onboarding-dismissed';\n\n // ---- Shadow DOM Overlay ----\n function createOverlay() {\n var host = document.createElement('div');\n host.id = 'ui-context-host';\n host.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;pointer-events:none;';\n document.body.appendChild(host);\n\n var shadow = host.attachShadow({ mode: 'open' });\n shadow.innerHTML = [\n '<style>',\n '.highlight { position:fixed; border:2px solid #3b82f6; background:rgba(59,130,246,0.08); pointer-events:none; transition:all 0.15s ease; border-radius:3px; display:none; }',\n '.highlight-label { position:absolute; top:-22px; left:-2px; background:#3b82f6; color:white; font-size:11px; font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif; padding:2px 8px; border-radius:3px 3px 0 0; white-space:nowrap; }',\n '.toolbar { position:fixed; bottom:20px; left:50%; transform:translateX(-50%); background:#0f172a; border:1px solid #334155; border-radius:12px; padding:8px 12px; display:flex; gap:6px; align-items:center; font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif; box-shadow:0 8px 32px rgba(0,0,0,0.5); pointer-events:auto; }',\n '.toolbar-label { color:#94a3b8; font-size:12px; padding:0 4px; }',\n '.toolbar-btn { color:white; border:none; padding:6px 14px; border-radius:6px; font-size:12px; font-weight:500; cursor:pointer; white-space:nowrap; }',\n '.toolbar-btn:hover { filter:brightness(1.15); }',\n '.toolbar-btn.primary { background:#3b82f6; }',\n '.toolbar-btn.secondary { background:#475569; }',\n '.toolbar-btn.freeze { background:#475569; }',\n '.toolbar-btn.freeze.active { background:#f59e0b; color:#1e293b; }',\n '.badge { display:inline-block; background:#f59e0b; color:#1e293b; font-size:10px; font-weight:700; padding:1px 5px; border-radius:10px; margin-left:4px; }',\n '.divider { width:1px; height:20px; background:#334155; }',\n '.toast { position:fixed; bottom:72px; left:50%; transform:translateX(-50%); background:#0f172a; color:#e2e8f0; padding:10px 20px; border-radius:8px; font-size:13px; font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif; box-shadow:0 4px 16px rgba(0,0,0,0.4); pointer-events:none; animation:toastIn 0.2s ease; }',\n '@keyframes toastIn { from { opacity:0; transform:translateX(-50%) translateY(8px); } }',\n '.banner { position:fixed; bottom:20px; left:50%; transform:translateX(-50%); background:linear-gradient(135deg,#0f172a 0%,#1e293b 100%); border:1px solid #334155; border-radius:12px; padding:12px 20px; display:flex; gap:12px; align-items:center; font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif; box-shadow:0 8px 32px rgba(0,0,0,0.4); animation:bannerIn 0.4s ease; max-width:480px; pointer-events:auto; }',\n '@keyframes bannerIn { from { opacity:0; transform:translateX(-50%) translateY(20px); } to { opacity:1; transform:translateX(-50%) translateY(0); } }',\n '.banner-text { color:#e2e8f0; font-size:13px; line-height:1.4; }',\n '.banner-text strong { color:#60a5fa; }',\n '.kbd { display:inline-block; background:#334155; color:#e2e8f0; padding:1px 6px; border-radius:4px; font-size:12px; font-family:monospace; border:1px solid #475569; }',\n '.banner-close { background:none; border:none; color:#64748b; cursor:pointer; padding:4px; font-size:16px; flex-shrink:0; }',\n '.banner-close:hover { color:#94a3b8; }',\n '</style>',\n '<div class=\"highlight\"><div class=\"highlight-label\"></div></div>',\n '<div class=\"toolbar\" style=\"display:none\">',\n ' <span class=\"toolbar-label\">UI Context</span>',\n ' <div class=\"divider\"></div>',\n ' <button class=\"toolbar-btn primary\" id=\"capture-btn\">Capture</button>',\n ' <button class=\"toolbar-btn primary\" id=\"capture-all-btn\" style=\"display:none\">Capture All <span class=\"badge\" id=\"multi-badge\" style=\"display:none\">0</span></button>',\n ' <div class=\"divider\"></div>',\n ' <button class=\"toolbar-btn freeze\" id=\"freeze-btn\" title=\"Freeze DOM (Ctrl+Shift+F)\">Freeze</button>',\n ' <button class=\"toolbar-btn secondary\" id=\"close-btn\">\\\\u2715</button>',\n '</div>',\n ].join('\\\\n');\n\n highlightEl = shadow.querySelector('.highlight');\n toolbarEl = shadow.querySelector('.toolbar');\n\n shadow.getElementById('close-btn').addEventListener('click', deactivate);\n shadow.getElementById('capture-btn').addEventListener('click', function() {\n if (selectedEl) captureAndSend(selectedEl);\n });\n shadow.getElementById('capture-all-btn').addEventListener('click', captureAllSelected);\n shadow.getElementById('freeze-btn').addEventListener('click', toggleFreeze);\n\n return { host: host, shadow: shadow };\n }\n\n var overlayRef = null;\n\n function showHighlight(el) {\n if (!highlightEl || !el) { highlightEl && (highlightEl.style.display = 'none'); return; }\n var rect = el.getBoundingClientRect();\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\n var label = highlightEl.querySelector('.highlight-label');\n var src = el.getAttribute('data-source-file');\n var line = el.getAttribute('data-source-line');\n var comp = el.getAttribute('data-source-component');\n label.textContent = src\n ? (comp || el.tagName.toLowerCase()) + ' \\\\u00b7 ' + src + ':' + line\n : el.tagName.toLowerCase();\n }\n\n function showToast(msg, duration) {\n if (!overlayRef) return;\n duration = duration || 3000;\n var t = document.createElement('div');\n t.className = 'toast';\n t.textContent = msg;\n overlayRef.shadow.appendChild(t);\n setTimeout(function() { t.remove(); }, duration);\n }\n\n // ---- React Fiber Hierarchy ----\n function getComponentHierarchy(el) {\n var fiberKey = Object.keys(el).find(function(k) {\n return k.startsWith('__reactFiber$') || k.startsWith('__reactInternalInstance$');\n });\n if (!fiberKey) return [];\n var hierarchy = [];\n var fiber = el[fiberKey];\n while (fiber) {\n if (typeof fiber.type === 'function') {\n var name = fiber.type.displayName || fiber.type.name;\n if (name && !name.startsWith('_') && name !== 'Fragment') hierarchy.unshift(name);\n } else if (typeof fiber.type === 'object' && fiber.type) {\n var name = fiber.type.displayName || (fiber.type.render && (fiber.type.render.displayName || fiber.type.render.name));\n if (name && !name.startsWith('_') && name !== 'Fragment') hierarchy.unshift(name);\n }\n fiber = fiber.return;\n }\n return hierarchy;\n }\n\n // ---- Computed Styles ----\n var STYLE_PROPS = [\n 'padding','padding-top','padding-right','padding-bottom','padding-left',\n 'margin','margin-top','margin-right','margin-bottom','margin-left',\n 'background-color','color','font-size','font-weight','font-family',\n 'border-radius','display','flex-direction','justify-content','align-items',\n 'gap','width','height','overflow','position','z-index','opacity',\n 'border','box-shadow','line-height','letter-spacing','text-align'\n ];\n\n function extractContext(el) {\n var computed = getComputedStyle(el);\n var rect = el.getBoundingClientRect();\n var styles = {};\n for (var i = 0; i < STYLE_PROPS.length; i++) {\n var p = STYLE_PROPS[i];\n var v = computed.getPropertyValue(p);\n if (v && v !== 'none' && v !== 'normal' && v !== 'auto' && v !== '0px' && v !== 'rgba(0, 0, 0, 0)') {\n styles[p] = v;\n }\n }\n\n var file = el.getAttribute('data-source-file');\n var line = el.getAttribute('data-source-line');\n var col = el.getAttribute('data-source-col');\n var component = el.getAttribute('data-source-component');\n\n return {\n source: file ? { file: file, line: parseInt(line||'0'), col: parseInt(col||'0'), component: component || undefined } : null,\n tagName: el.tagName.toLowerCase(),\n classes: el.className || '',\n computedStyles: styles,\n dimensions: { width: rect.width, height: rect.height, x: rect.x, y: rect.y },\n componentHierarchy: getComponentHierarchy(el),\n url: location.href\n };\n }\n\n // ---- Screenshot ----\n function captureScreenshot(el) {\n return new Promise(function(resolve) {\n try {\n var rect = el.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) { resolve(undefined); return; }\n\n var canvas = document.createElement('canvas');\n var dpr = window.devicePixelRatio || 1;\n var pad = 8;\n var w = Math.ceil(rect.width + pad * 2);\n var h = Math.ceil(rect.height + pad * 2);\n canvas.width = w * dpr;\n canvas.height = h * dpr;\n\n var ctx = canvas.getContext('2d');\n if (!ctx) { resolve(undefined); return; }\n ctx.scale(dpr, dpr);\n\n // Try SVG foreignObject approach\n var clone = el.cloneNode(true);\n copyStyles(el, clone);\n\n var svgNs = 'http://www.w3.org/2000/svg';\n var svg = document.createElementNS(svgNs, 'svg');\n svg.setAttribute('width', String(w));\n svg.setAttribute('height', String(h));\n svg.setAttribute('xmlns', svgNs);\n\n var fo = document.createElementNS(svgNs, 'foreignObject');\n fo.setAttribute('width', '100%');\n fo.setAttribute('height', '100%');\n\n var container = document.createElement('div');\n container.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml');\n container.style.cssText = 'width:' + w + 'px;height:' + h + 'px;display:flex;align-items:center;justify-content:center;background:white;padding:' + pad + 'px;box-sizing:border-box;';\n container.appendChild(clone);\n fo.appendChild(container);\n svg.appendChild(fo);\n\n var svgStr = new XMLSerializer().serializeToString(svg);\n var blob = new Blob([svgStr], { type: 'image/svg+xml;charset=utf-8' });\n var url = URL.createObjectURL(blob);\n\n var img = new Image();\n img.onload = function() {\n ctx.drawImage(img, 0, 0);\n URL.revokeObjectURL(url);\n try { resolve(canvas.toDataURL('image/png')); } catch(e) { resolve(undefined); }\n };\n img.onerror = function() {\n URL.revokeObjectURL(url);\n // Fallback: placeholder\n ctx.fillStyle = '#f8fafc';\n ctx.fillRect(0, 0, w, h);\n ctx.strokeStyle = '#3b82f6';\n ctx.lineWidth = 2;\n ctx.strokeRect(pad, pad, rect.width, rect.height);\n ctx.fillStyle = '#64748b';\n ctx.font = '11px -apple-system, BlinkMacSystemFont, sans-serif';\n ctx.fillText(Math.round(rect.width) + ' x ' + Math.round(rect.height) + 'px', pad + 4, pad + rect.height / 2 + 4);\n try { resolve(canvas.toDataURL('image/png')); } catch(e) { resolve(undefined); }\n };\n img.src = url;\n } catch(e) {\n resolve(undefined);\n }\n });\n }\n\n function copyStyles(src, tgt) {\n var cs = getComputedStyle(src);\n var props = ['display','width','height','padding','margin','border','border-radius','background','background-color','color','font-size','font-weight','font-family','line-height','text-align','box-shadow','opacity','flex-direction','justify-content','align-items','gap','overflow'];\n for (var i = 0; i < props.length; i++) {\n tgt.style.setProperty(props[i], cs.getPropertyValue(props[i]));\n }\n var sc = src.children, tc = tgt.children;\n for (var j = 0; j < sc.length && j < tc.length; j++) {\n if (sc[j] instanceof HTMLElement && tc[j] instanceof HTMLElement) copyStyles(sc[j], tc[j]);\n }\n }\n\n // ---- Capture & Send ----\n function captureAndSend(el) {\n showToast('Capturing context...');\n var ctx = extractContext(el);\n\n captureScreenshot(el).then(function(screenshot) {\n if (screenshot) ctx.screenshotDataUrl = screenshot;\n\n if (import.meta.hot) {\n import.meta.hot.send('ui-context:capture', ctx);\n import.meta.hot.on('ui-context:capture-result', function(result) {\n if (result.success) {\n showToast('Context captured! Check .ui-context/latest.md');\n } else {\n showToast('Capture failed: ' + (result.error || 'unknown error'));\n }\n });\n }\n });\n }\n\n function captureAllSelected() {\n if (multiSelected.size === 0) {\n showToast('No elements selected. Use Shift+Click to select multiple.');\n return;\n }\n showToast('Capturing ' + multiSelected.size + ' elements...');\n\n var elements = Array.from(multiSelected);\n var contexts = [];\n var pending = elements.length;\n\n elements.forEach(function(el) {\n var ctx = extractContext(el);\n captureScreenshot(el).then(function(screenshot) {\n if (screenshot) ctx.screenshotDataUrl = screenshot;\n contexts.push(ctx);\n pending--;\n if (pending === 0) {\n if (import.meta.hot) {\n import.meta.hot.send('ui-context:capture', contexts);\n import.meta.hot.on('ui-context:capture-result', function(result) {\n if (result.success) {\n showToast(contexts.length + ' elements captured!');\n clearMultiSelection();\n } else {\n showToast('Capture failed: ' + (result.error || 'unknown error'));\n }\n });\n }\n }\n });\n });\n }\n\n function updateMultiBadge() {\n if (!overlayRef) return;\n var btn = overlayRef.shadow.getElementById('capture-all-btn');\n var badge = overlayRef.shadow.getElementById('multi-badge');\n if (multiSelected.size > 0) {\n btn.style.display = '';\n badge.style.display = '';\n badge.textContent = String(multiSelected.size);\n } else {\n btn.style.display = 'none';\n badge.style.display = 'none';\n }\n }\n\n function clearMultiSelection() {\n multiSelected.forEach(function(el) { el.style.outline = ''; });\n multiSelected.clear();\n updateMultiBadge();\n }\n\n // ---- Freeze Mode ----\n function toggleFreeze() {\n if (isFrozen) {\n unfreezeDOM();\n showToast('DOM unfrozen');\n } else {\n freezeDOM();\n showToast('DOM frozen — hover states preserved');\n }\n var btn = overlayRef && overlayRef.shadow.getElementById('freeze-btn');\n if (btn) {\n if (isFrozen) {\n btn.classList.add('active');\n btn.textContent = 'Frozen';\n } else {\n btn.classList.remove('active');\n btn.textContent = 'Freeze';\n }\n }\n }\n\n function freezeDOM() {\n isFrozen = true;\n var observer = new MutationObserver(function(mutations) {\n for (var i = 0; i < mutations.length; i++) {\n var m = mutations[i];\n for (var j = 0; j < m.addedNodes.length; j++) {\n var node = m.addedNodes[j];\n if (node instanceof HTMLElement && !(node.id && node.id.indexOf('ui-context') !== -1)) {\n node.remove();\n }\n }\n if (m.type === 'attributes' && m.target instanceof HTMLElement) {\n if (!(m.target.id && m.target.id.indexOf('ui-context') !== -1)) {\n var old = m.oldValue;\n if (old !== null && m.attributeName) {\n m.target.setAttribute(m.attributeName, old);\n }\n }\n }\n }\n });\n observer.observe(document.body, {\n childList: true, subtree: true, attributes: true, attributeOldValue: true\n });\n frozenObservers.push(observer);\n }\n\n function unfreezeDOM() {\n isFrozen = false;\n frozenObservers.forEach(function(obs) { obs.disconnect(); });\n frozenObservers = [];\n }\n\n // ---- Event Handlers ----\n function isOverlayEl(t) {\n return t.id === 'ui-context-host' || (t.closest && t.closest('#ui-context-host'));\n }\n\n function onMouseMove(e) {\n if (!isActive) return;\n var t = e.target;\n if (isOverlayEl(t)) return;\n showHighlight(t);\n }\n\n function onClick(e) {\n if (!isActive) return;\n var t = e.target;\n if (isOverlayEl(t)) return;\n e.preventDefault();\n e.stopPropagation();\n\n // Shift+Click: multi-select\n if (e.shiftKey) {\n if (multiSelected.has(t)) {\n multiSelected.delete(t);\n t.style.outline = '';\n } else {\n multiSelected.add(t);\n t.style.outline = '2px dashed #f59e0b';\n }\n updateMultiBadge();\n return;\n }\n\n selectedEl = t;\n captureAndSend(t);\n }\n\n // ---- Activate / Deactivate ----\n function activate() {\n if (isActive) return;\n isActive = true;\n overlayRef = createOverlay();\n toolbarEl.style.display = 'flex';\n document.addEventListener('mousemove', onMouseMove, true);\n document.addEventListener('click', onClick, true);\n document.body.style.cursor = 'crosshair';\n showToast('Click to capture, Shift+click for multi-select', 2000);\n }\n\n function deactivate() {\n if (!isActive) return;\n isActive = false;\n selectedEl = null;\n if (isFrozen) unfreezeDOM();\n clearMultiSelection();\n document.removeEventListener('mousemove', onMouseMove, true);\n document.removeEventListener('click', onClick, true);\n document.body.style.cursor = '';\n if (overlayRef) {\n overlayRef.host.remove();\n overlayRef = null;\n highlightEl = null;\n toolbarEl = null;\n }\n }\n\n // ---- Keyboard Shortcuts ----\n document.addEventListener('keydown', function(e) {\n var keys = SHORTCUT.split('+');\n var needsAlt = keys.indexOf('alt') !== -1;\n var needsCtrl = keys.indexOf('ctrl') !== -1;\n var needsShift = keys.indexOf('shift') !== -1;\n var mainKey = keys[keys.length - 1].toLowerCase();\n\n if (e.altKey === needsAlt && e.ctrlKey === needsCtrl && e.shiftKey === needsShift && e.key.toLowerCase() === mainKey) {\n e.preventDefault();\n isActive ? deactivate() : activate();\n return;\n }\n\n // Freeze: Ctrl+Shift+F (only when active)\n if (isActive && e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'f') {\n e.preventDefault();\n toggleFreeze();\n }\n });\n\n // ---- Onboarding Banner ----\n function showOnboarding() {\n try { if (localStorage.getItem(ONBOARDING_KEY)) return; } catch(e) { return; }\n\n // Wait for overlay ref to be set up\n var bannerHost = document.createElement('div');\n bannerHost.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483646;pointer-events:none;';\n document.body.appendChild(bannerHost);\n var bannerShadow = bannerHost.attachShadow({ mode: 'open' });\n\n var shortcutDisplay = SHORTCUT.split('+').map(function(k) { return k.charAt(0).toUpperCase() + k.slice(1); }).join(' + ');\n\n bannerShadow.innerHTML = [\n '<style>',\n '.banner { position:fixed; bottom:20px; left:50%; transform:translateX(-50%); background:linear-gradient(135deg,#0f172a 0%,#1e293b 100%); border:1px solid #334155; border-radius:12px; padding:12px 20px; display:flex; gap:12px; align-items:center; font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif; box-shadow:0 8px 32px rgba(0,0,0,0.4); animation:bannerIn 0.4s ease; max-width:480px; pointer-events:auto; }',\n '@keyframes bannerIn { from { opacity:0; transform:translateX(-50%) translateY(20px); } to { opacity:1; transform:translateX(-50%) translateY(0); } }',\n '.text { color:#e2e8f0; font-size:13px; line-height:1.4; }',\n '.text strong { color:#60a5fa; }',\n '.kbd { display:inline-block; background:#334155; color:#e2e8f0; padding:1px 6px; border-radius:4px; font-size:12px; font-family:monospace; border:1px solid #475569; }',\n '.close { background:none; border:none; color:#64748b; cursor:pointer; padding:4px; font-size:16px; flex-shrink:0; }',\n '.close:hover { color:#94a3b8; }',\n '</style>',\n '<div class=\"banner\">',\n ' <span style=\"font-size:20px\">\\\\u{1F3AF}</span>',\n ' <span class=\"text\">',\n ' <strong>UI Context Kit</strong> is ready! Press <kbd class=\"kbd\">' + shortcutDisplay + '</kbd> to capture any UI element for AI.',\n ' <strong>Shift+Click</strong> for multi-select, <strong>Ctrl+Shift+F</strong> to freeze state.',\n ' </span>',\n ' <button class=\"close\" title=\"Dismiss\">\\\\u2715</button>',\n '</div>',\n ].join('\\\\n');\n\n bannerShadow.querySelector('.close').addEventListener('click', function() {\n bannerHost.remove();\n try { localStorage.setItem(ONBOARDING_KEY, '1'); } catch(e) {}\n });\n\n setTimeout(function() {\n if (bannerHost.parentNode) {\n var banner = bannerShadow.querySelector('.banner');\n if (banner) {\n banner.style.transition = 'opacity 0.3s ease';\n banner.style.opacity = '0';\n setTimeout(function() { bannerHost.remove(); }, 300);\n }\n }\n }, 8000);\n }\n\n showOnboarding();\n console.log('[ui-context-kit] Ready. Press ' + SHORTCUT + ' to activate.');\n})();\n `;\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { ElementContext } from './types';\n\nexport async function writeContext(\n context: ElementContext | ElementContext[],\n projectRoot: string,\n outputDir: string,\n): Promise<string> {\n const outPath = path.resolve(projectRoot, outputDir);\n const capturesDir = path.join(outPath, 'captures');\n\n // Ensure output directories exist\n fs.mkdirSync(outPath, { recursive: true });\n fs.mkdirSync(path.join(outPath, 'screenshots'), { recursive: true });\n fs.mkdirSync(capturesDir, { recursive: true });\n\n const contexts = Array.isArray(context) ? context : [context];\n\n // Save screenshots if available\n const screenshotPaths: (string | undefined)[] = [];\n for (const ctx of contexts) {\n if (ctx.screenshotDataUrl) {\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const filename = `capture-${timestamp}.png`;\n const relPath = `./screenshots/${filename}`;\n const base64 = ctx.screenshotDataUrl.replace(/^data:image\\/\\w+;base64,/, '');\n fs.writeFileSync(path.join(outPath, 'screenshots', filename), Buffer.from(base64, 'base64'));\n screenshotPaths.push(relPath);\n } else {\n screenshotPaths.push(undefined);\n }\n }\n\n // Read source code snippets\n const sourceSnippets: string[] = [];\n for (const ctx of contexts) {\n if (ctx.source) {\n sourceSnippets.push(readSourceSnippet(\n path.resolve(projectRoot, ctx.source.file),\n ctx.source.line,\n 10,\n ));\n } else {\n sourceSnippets.push('');\n }\n }\n\n // Build markdown\n const md = contexts.length === 1\n ? buildMarkdown(contexts[0], sourceSnippets[0], screenshotPaths[0])\n : buildMultiMarkdown(contexts, sourceSnippets, screenshotPaths);\n\n // Write latest.md\n const latestPath = path.join(outPath, 'latest.md');\n fs.writeFileSync(latestPath, md, 'utf-8');\n\n // Write timestamped capture file for history\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const capturePath = path.join(capturesDir, `${timestamp}.md`);\n fs.writeFileSync(capturePath, md, 'utf-8');\n\n // Update history.md (append summary, keep last 20 entries)\n updateHistory(outPath, contexts, timestamp);\n\n // Clean up old captures (keep last 50)\n cleanupOldCaptures(capturesDir, 50);\n\n console.log(`[ui-context-kit] Context written to ${path.relative(projectRoot, latestPath)}`);\n console.log(`[ui-context-kit] History saved to ${path.relative(projectRoot, capturePath)}`);\n\n return latestPath;\n}\n\nfunction updateHistory(outPath: string, contexts: ElementContext[], timestamp: string): void {\n const historyPath = path.join(outPath, 'history.md');\n\n // Build summary for this capture\n const lines: string[] = [];\n const time = timestamp.replace(/T/, ' ').replace(/-(\\d{2})-(\\d{2})-(\\d+)Z?$/, ':$1:$2');\n\n for (const ctx of contexts) {\n const component = ctx.source?.component || ctx.tagName;\n const file = ctx.source ? `${ctx.source.file}:${ctx.source.line}` : '';\n lines.push(`- **${component}** ${file ? `(\\`${file}\\`)` : ''} — ${ctx.url}`);\n }\n\n const entry = `### ${time}\\n${lines.join('\\n')}\\n\\n`;\n\n // Read existing history or create new\n let existing = '';\n try {\n existing = fs.readFileSync(historyPath, 'utf-8');\n } catch {\n existing = '# UI Context Capture History\\n\\n';\n }\n\n // Insert after the header line\n const headerEnd = existing.indexOf('\\n\\n');\n if (headerEnd !== -1) {\n const header = existing.slice(0, headerEnd + 2);\n const body = existing.slice(headerEnd + 2);\n existing = header + entry + body;\n } else {\n existing += entry;\n }\n\n // Keep only last 20 entries\n const entries = existing.split(/(?=### )/);\n const header = entries[0]; // everything before first ###\n const captureEntries = entries.slice(1);\n if (captureEntries.length > 20) {\n existing = header + captureEntries.slice(0, 20).join('');\n }\n\n fs.writeFileSync(historyPath, existing, 'utf-8');\n}\n\nfunction cleanupOldCaptures(capturesDir: string, maxFiles: number): void {\n try {\n const files = fs.readdirSync(capturesDir)\n .filter(f => f.endsWith('.md'))\n .sort()\n .reverse();\n\n for (let i = maxFiles; i < files.length; i++) {\n fs.unlinkSync(path.join(capturesDir, files[i]));\n }\n } catch {\n // ignore cleanup errors\n }\n}\n\nfunction readSourceSnippet(filePath: string, targetLine: number, contextLines: number): string {\n try {\n const content = fs.readFileSync(filePath, 'utf-8');\n const lines = content.split('\\n');\n const start = Math.max(0, targetLine - contextLines - 1);\n const end = Math.min(lines.length, targetLine + contextLines);\n\n return lines\n .slice(start, end)\n .map((line, i) => {\n const lineNum = start + i + 1;\n const marker = lineNum === targetLine ? ' // <-- target' : '';\n return `${line}${marker}`;\n })\n .join('\\n');\n } catch {\n return '// Source file not found';\n }\n}\n\nfunction buildMarkdown(\n context: ElementContext,\n sourceSnippet: string,\n screenshotPath?: string,\n): string {\n const { source, tagName, classes, computedStyles, dimensions, componentHierarchy, url } = context;\n\n const lines: string[] = ['# UI Context Capture', ''];\n\n // Target Element section\n lines.push('## Target Element');\n if (source) {\n if (source.component) {\n lines.push(`- **Component**: \\`${source.component}\\` in \\`${source.file}:${source.line}\\``);\n } else {\n lines.push(`- **File**: \\`${source.file}:${source.line}\\``);\n }\n }\n lines.push(`- **URL**: ${url}`);\n lines.push(`- **Tag**: \\`<${tagName}>\\``);\n lines.push('');\n\n // Source Code section\n if (source && sourceSnippet) {\n const startLine = Math.max(1, source.line - 10);\n const endLine = source.line + 10;\n lines.push('## Source Code');\n lines.push('```tsx');\n lines.push(`// ${source.file}:${startLine}-${endLine}`);\n lines.push(sourceSnippet);\n lines.push('```');\n lines.push('');\n }\n\n // Styling section\n lines.push('## Styling');\n if (classes) {\n lines.push(`- **Classes**: \\`${classes}\\``);\n }\n\n const styleEntries = Object.entries(computedStyles);\n if (styleEntries.length > 0) {\n lines.push(`- **Computed**: ${styleEntries.map(([k, v]) => `${camelToKebab(k)}: ${v}`).join(', ')}`);\n }\n\n lines.push(`- **Dimensions**: ${Math.round(dimensions.width)}x${Math.round(dimensions.height)}px at (${Math.round(dimensions.x)}, ${Math.round(dimensions.y)})`);\n lines.push('');\n\n // Component Hierarchy section\n if (componentHierarchy.length > 0) {\n lines.push('## Component Hierarchy');\n lines.push(componentHierarchy.join(' > '));\n lines.push('');\n }\n\n // Screenshot section\n if (screenshotPath) {\n lines.push('## Screenshot');\n lines.push(`![element](${screenshotPath})`);\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\nfunction buildMultiMarkdown(\n contexts: ElementContext[],\n sourceSnippets: string[],\n screenshotPaths: (string | undefined)[],\n): string {\n const lines: string[] = [\n `# UI Context Capture (${contexts.length} elements)`,\n '',\n ];\n\n for (let i = 0; i < contexts.length; i++) {\n const ctx = contexts[i];\n const snippet = sourceSnippets[i];\n const screenshot = screenshotPaths[i];\n\n lines.push(`---`);\n lines.push('');\n lines.push(`## Element ${i + 1}: \\`<${ctx.tagName}>\\`${ctx.source?.component ? ` (${ctx.source.component})` : ''}`);\n lines.push('');\n\n if (ctx.source) {\n if (ctx.source.component) {\n lines.push(`- **Component**: \\`${ctx.source.component}\\` in \\`${ctx.source.file}:${ctx.source.line}\\``);\n } else {\n lines.push(`- **File**: \\`${ctx.source.file}:${ctx.source.line}\\``);\n }\n }\n lines.push(`- **URL**: ${ctx.url}`);\n lines.push('');\n\n if (ctx.source && snippet) {\n const startLine = Math.max(1, ctx.source.line - 10);\n const endLine = ctx.source.line + 10;\n lines.push('### Source Code');\n lines.push('```tsx');\n lines.push(`// ${ctx.source.file}:${startLine}-${endLine}`);\n lines.push(snippet);\n lines.push('```');\n lines.push('');\n }\n\n lines.push('### Styling');\n if (ctx.classes) {\n lines.push(`- **Classes**: \\`${ctx.classes}\\``);\n }\n const styleEntries = Object.entries(ctx.computedStyles);\n if (styleEntries.length > 0) {\n lines.push(`- **Computed**: ${styleEntries.map(([k, v]) => `${camelToKebab(k)}: ${v}`).join(', ')}`);\n }\n lines.push(`- **Dimensions**: ${Math.round(ctx.dimensions.width)}x${Math.round(ctx.dimensions.height)}px at (${Math.round(ctx.dimensions.x)}, ${Math.round(ctx.dimensions.y)})`);\n lines.push('');\n\n if (ctx.componentHierarchy.length > 0) {\n lines.push('### Component Hierarchy');\n lines.push(ctx.componentHierarchy.join(' > '));\n lines.push('');\n }\n\n if (screenshot) {\n lines.push('### Screenshot');\n lines.push(`![element ${i + 1}](${screenshot})`);\n lines.push('');\n }\n }\n\n return lines.join('\\n');\n}\n\nfunction camelToKebab(str: string): string {\n return str.replace(/[A-Z]/g, m => '-' + m.toLowerCase());\n}\n","import { exec } from 'child_process';\nimport { platform } from 'os';\n\nexport function copyToClipboard(text: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const os = platform();\n let cmd: string;\n\n if (os === 'darwin') {\n cmd = 'pbcopy';\n } else if (os === 'linux') {\n cmd = 'xclip -selection clipboard';\n } else if (os === 'win32') {\n cmd = 'clip';\n } else {\n reject(new Error(`Unsupported platform: ${os}`));\n return;\n }\n\n const proc = exec(cmd, (err) => {\n if (err) reject(err);\n else resolve();\n });\n\n proc.stdin?.write(text);\n proc.stdin?.end();\n });\n}\n","import type { ViteDevServer } from 'vite';\nimport { writeContext } from './context-writer';\nimport { copyToClipboard } from './clipboard';\nimport type { ElementContext, UIContextKitOptions } from './types';\n\nexport function setupWebSocket(server: ViteDevServer, options: UIContextKitOptions): void {\n const root = server.config.root;\n const outputDir = options.outputDir || '.ui-context';\n const shouldCopy = options.clipboard !== false;\n\n server.ws.on('ui-context:capture', async (data: ElementContext | ElementContext[], client) => {\n try {\n const count = Array.isArray(data) ? data.length : 1;\n console.log(`[ui-context-kit] Received context capture (${count} element${count > 1 ? 's' : ''})`);\n\n const filePath = await writeContext(data, root, outputDir);\n\n if (shouldCopy) {\n try {\n const fs = await import('fs');\n const content = fs.readFileSync(filePath, 'utf-8');\n await copyToClipboard(content);\n console.log('[ui-context-kit] Context copied to clipboard');\n } catch (e) {\n console.warn('[ui-context-kit] Could not copy to clipboard:', e);\n }\n }\n\n client.send('ui-context:capture-result', { success: true });\n } catch (err: any) {\n console.error('[ui-context-kit] Error writing context:', err);\n client.send('ui-context:capture-result', { success: false, error: err.message });\n }\n });\n}\n","import type { UIContextKitOptions } from './types';\n\n/**\n * Wraps a Next.js config to add ui-context-kit babel plugin in development.\n *\n * Usage:\n * ```js\n * // next.config.js\n * const { withUIContext } = require('@ui-context-kit/bridge');\n * module.exports = withUIContext(nextConfig);\n * ```\n */\nexport function withUIContext(nextConfig: any = {}, _options?: UIContextKitOptions) {\n if (process.env.NODE_ENV !== 'development') return nextConfig;\n\n return {\n ...nextConfig,\n webpack(config: any, context: any) {\n // Add babel-loader with our plugin for JSX/TSX files\n // Note: This is a simplified approach. For production use,\n // users should configure babel.config.js directly.\n\n if (typeof nextConfig.webpack === 'function') {\n config = nextConfig.webpack(config, context);\n }\n\n return config;\n },\n };\n}\n"],"mappings":"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AA;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;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;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;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;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;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;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;AAmf5B;;;AI1kBO,SAAS,cAAc,aAAkB,CAAC,GAAG,UAAgC;AAClF,MAAI,QAAQ,IAAI,aAAa,cAAe,QAAO;AAEnD,SAAO;AAAA,IACL,GAAG;AAAA,IACH,QAAQ,QAAa,SAAc;AAKjC,UAAI,OAAO,WAAW,YAAY,YAAY;AAC5C,iBAAS,WAAW,QAAQ,QAAQ,OAAO;AAAA,MAC7C;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;ALXO,SAAS,aAAa,SAA+B;AAC1D,SAAO,iBAAiB,OAAO;AACjC;","names":["import_path","import_fs","path","fs","timestamp","header","fs","path","fs"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/vite-plugin.ts","../src/context-writer.ts","../src/clipboard.ts","../src/ws-server.ts","../src/next-wrapper.ts","../src/next-server.ts"],"sourcesContent":["import { createVitePlugin } from './vite-plugin';\nimport { writeContext } from './context-writer';\nimport { withUIContext } from './next-wrapper';\nimport type { UIContextKitOptions } from './types';\n\n/**\n * Vite plugin for UI Context Kit.\n * Enables browser-based element selection and context capture for AI coding assistants.\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { uiContextKit } from '@ui-context-kit/bridge'\n * export default defineConfig({\n * plugins: [react(), uiContextKit()]\n * })\n * ```\n */\nexport function uiContextKit(options?: UIContextKitOptions) {\n return createVitePlugin(options);\n}\n\nexport { writeContext, withUIContext };\nexport type { UIContextKitOptions, ElementContext, SourceLocation } from './types';\n","import type { Plugin } from 'vite';\nimport path from 'path';\nimport fs from 'fs';\nimport { injectSourceAttributes } from '@ui-context-kit/babel-plugin';\nimport { setupWebSocket } from './ws-server';\nimport type { UIContextKitOptions } from './types';\n\nconst JSX_EXTENSIONS = /\\.(jsx|tsx)$/;\nconst VIRTUAL_MODULE_ID = 'virtual:ui-context-overlay';\nconst RESOLVED_VIRTUAL_MODULE_ID = '\\0' + VIRTUAL_MODULE_ID;\n\nexport function createVitePlugin(options: UIContextKitOptions = {}): Plugin[] {\n const {\n shortcut = 'alt+x',\n include,\n exclude = ['node_modules'],\n } = options;\n\n let projectRoot = '';\n\n const transformPlugin: Plugin = {\n name: 'ui-context-kit:transform',\n enforce: 'pre',\n apply: 'serve',\n\n configResolved(config) {\n projectRoot = config.root;\n },\n\n transform(code, id) {\n if (!JSX_EXTENSIONS.test(id)) return null;\n\n const relativePath = path.relative(projectRoot, id);\n if (exclude?.some(p => relativePath.includes(p))) return null;\n if (include && !include.some(p => relativePath.includes(p))) return null;\n if (id.includes('\\0') || id.includes('node_modules')) return null;\n\n const filePath = path.relative(projectRoot, id);\n\n let originalCode: string | undefined;\n try {\n originalCode = fs.readFileSync(id, 'utf-8');\n } catch {\n // ignore read errors\n }\n\n const result = injectSourceAttributes(code, filePath, originalCode);\n if (!result) return null;\n\n return { code: result.code, map: result.map };\n },\n };\n\n const overlayPlugin: Plugin = {\n name: 'ui-context-kit:overlay',\n apply: 'serve',\n\n resolveId(id) {\n if (id === VIRTUAL_MODULE_ID) return RESOLVED_VIRTUAL_MODULE_ID;\n },\n\n load(id) {\n if (id === RESOLVED_VIRTUAL_MODULE_ID) {\n return getOverlayCode(shortcut);\n }\n },\n\n configureServer(server) {\n setupWebSocket(server, options);\n },\n\n transformIndexHtml() {\n return [\n {\n tag: 'script',\n attrs: { type: 'module', src: `/@id/${VIRTUAL_MODULE_ID}` },\n injectTo: 'body' as const,\n },\n ];\n },\n };\n\n return [transformPlugin, overlayPlugin];\n}\n\nfunction getOverlayCode(shortcut: string): string {\n return `\n// UI Context Kit - Overlay (auto-injected in dev mode)\n(function() {\n if (typeof window === 'undefined') return;\n\n var isActive = false;\n var highlightEl = null;\n var toolbarEl = null;\n var selectedEl = null;\n var isFrozen = false;\n var frozenObservers = [];\n var multiSelected = new Set();\n\n var SHORTCUT = '${shortcut}';\n var ONBOARDING_KEY = 'ui-context-kit-onboarding-dismissed';\n\n // ---- Shadow DOM Overlay ----\n function createOverlay() {\n var host = document.createElement('div');\n host.id = 'ui-context-host';\n host.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;pointer-events:none;';\n document.body.appendChild(host);\n\n var shadow = host.attachShadow({ mode: 'open' });\n shadow.innerHTML = [\n '<style>',\n '.highlight { position:fixed; border:2px solid #3b82f6; background:rgba(59,130,246,0.08); pointer-events:none; transition:all 0.15s ease; border-radius:3px; display:none; }',\n '.highlight-label { position:absolute; top:-22px; left:-2px; background:#3b82f6; color:white; font-size:11px; font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif; padding:2px 8px; border-radius:3px 3px 0 0; white-space:nowrap; }',\n '.toolbar { position:fixed; bottom:20px; left:50%; transform:translateX(-50%); background:#0f172a; border:1px solid #334155; border-radius:12px; padding:8px 12px; display:flex; gap:6px; align-items:center; font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif; box-shadow:0 8px 32px rgba(0,0,0,0.5); pointer-events:auto; }',\n '.toolbar-label { color:#94a3b8; font-size:12px; padding:0 4px; }',\n '.toolbar-btn { color:white; border:none; padding:6px 14px; border-radius:6px; font-size:12px; font-weight:500; cursor:pointer; white-space:nowrap; }',\n '.toolbar-btn:hover { filter:brightness(1.15); }',\n '.toolbar-btn.primary { background:#3b82f6; }',\n '.toolbar-btn.secondary { background:#475569; }',\n '.toolbar-btn.freeze { background:#475569; }',\n '.toolbar-btn.freeze.active { background:#f59e0b; color:#1e293b; }',\n '.badge { display:inline-block; background:#f59e0b; color:#1e293b; font-size:10px; font-weight:700; padding:1px 5px; border-radius:10px; margin-left:4px; }',\n '.divider { width:1px; height:20px; background:#334155; }',\n '.toast { position:fixed; bottom:72px; left:50%; transform:translateX(-50%); background:#0f172a; color:#e2e8f0; padding:10px 20px; border-radius:8px; font-size:13px; font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif; box-shadow:0 4px 16px rgba(0,0,0,0.4); pointer-events:none; animation:toastIn 0.2s ease; }',\n '@keyframes toastIn { from { opacity:0; transform:translateX(-50%) translateY(8px); } }',\n '.banner { position:fixed; bottom:20px; left:50%; transform:translateX(-50%); background:linear-gradient(135deg,#0f172a 0%,#1e293b 100%); border:1px solid #334155; border-radius:12px; padding:12px 20px; display:flex; gap:12px; align-items:center; font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif; box-shadow:0 8px 32px rgba(0,0,0,0.4); animation:bannerIn 0.4s ease; max-width:480px; pointer-events:auto; }',\n '@keyframes bannerIn { from { opacity:0; transform:translateX(-50%) translateY(20px); } to { opacity:1; transform:translateX(-50%) translateY(0); } }',\n '.banner-text { color:#e2e8f0; font-size:13px; line-height:1.4; }',\n '.banner-text strong { color:#60a5fa; }',\n '.kbd { display:inline-block; background:#334155; color:#e2e8f0; padding:1px 6px; border-radius:4px; font-size:12px; font-family:monospace; border:1px solid #475569; }',\n '.banner-close { background:none; border:none; color:#64748b; cursor:pointer; padding:4px; font-size:16px; flex-shrink:0; }',\n '.banner-close:hover { color:#94a3b8; }',\n '</style>',\n '<div class=\"highlight\"><div class=\"highlight-label\"></div></div>',\n '<div class=\"toolbar\" style=\"display:none\">',\n ' <span class=\"toolbar-label\">UI Context</span>',\n ' <div class=\"divider\"></div>',\n ' <button class=\"toolbar-btn primary\" id=\"capture-btn\">Capture</button>',\n ' <button class=\"toolbar-btn primary\" id=\"capture-all-btn\" style=\"display:none\">Capture All <span class=\"badge\" id=\"multi-badge\" style=\"display:none\">0</span></button>',\n ' <div class=\"divider\"></div>',\n ' <button class=\"toolbar-btn freeze\" id=\"freeze-btn\" title=\"Freeze DOM (Ctrl+Shift+F)\">Freeze</button>',\n ' <button class=\"toolbar-btn secondary\" id=\"close-btn\">\\\\u2715</button>',\n '</div>',\n ].join('\\\\n');\n\n highlightEl = shadow.querySelector('.highlight');\n toolbarEl = shadow.querySelector('.toolbar');\n\n shadow.getElementById('close-btn').addEventListener('click', deactivate);\n shadow.getElementById('capture-btn').addEventListener('click', function() {\n if (selectedEl) captureAndSend(selectedEl);\n });\n shadow.getElementById('capture-all-btn').addEventListener('click', captureAllSelected);\n shadow.getElementById('freeze-btn').addEventListener('click', toggleFreeze);\n\n return { host: host, shadow: shadow };\n }\n\n var overlayRef = null;\n\n function showHighlight(el) {\n if (!highlightEl || !el) { highlightEl && (highlightEl.style.display = 'none'); return; }\n var rect = el.getBoundingClientRect();\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\n var label = highlightEl.querySelector('.highlight-label');\n var src = el.getAttribute('data-source-file');\n var line = el.getAttribute('data-source-line');\n var comp = el.getAttribute('data-source-component');\n label.textContent = src\n ? (comp || el.tagName.toLowerCase()) + ' \\\\u00b7 ' + src + ':' + line\n : el.tagName.toLowerCase();\n }\n\n function showToast(msg, duration) {\n if (!overlayRef) return;\n duration = duration || 3000;\n var t = document.createElement('div');\n t.className = 'toast';\n t.textContent = msg;\n overlayRef.shadow.appendChild(t);\n setTimeout(function() { t.remove(); }, duration);\n }\n\n // ---- React Fiber Hierarchy ----\n function getComponentHierarchy(el) {\n var fiberKey = Object.keys(el).find(function(k) {\n return k.startsWith('__reactFiber$') || k.startsWith('__reactInternalInstance$');\n });\n if (!fiberKey) return [];\n var hierarchy = [];\n var fiber = el[fiberKey];\n while (fiber) {\n if (typeof fiber.type === 'function') {\n var name = fiber.type.displayName || fiber.type.name;\n if (name && !name.startsWith('_') && name !== 'Fragment') hierarchy.unshift(name);\n } else if (typeof fiber.type === 'object' && fiber.type) {\n var name = fiber.type.displayName || (fiber.type.render && (fiber.type.render.displayName || fiber.type.render.name));\n if (name && !name.startsWith('_') && name !== 'Fragment') hierarchy.unshift(name);\n }\n fiber = fiber.return;\n }\n return hierarchy;\n }\n\n // ---- Computed Styles ----\n var STYLE_PROPS = [\n 'padding','padding-top','padding-right','padding-bottom','padding-left',\n 'margin','margin-top','margin-right','margin-bottom','margin-left',\n 'background-color','color','font-size','font-weight','font-family',\n 'border-radius','display','flex-direction','justify-content','align-items',\n 'gap','width','height','overflow','position','z-index','opacity',\n 'border','box-shadow','line-height','letter-spacing','text-align'\n ];\n\n function extractContext(el) {\n var computed = getComputedStyle(el);\n var rect = el.getBoundingClientRect();\n var styles = {};\n for (var i = 0; i < STYLE_PROPS.length; i++) {\n var p = STYLE_PROPS[i];\n var v = computed.getPropertyValue(p);\n if (v && v !== 'none' && v !== 'normal' && v !== 'auto' && v !== '0px' && v !== 'rgba(0, 0, 0, 0)') {\n styles[p] = v;\n }\n }\n\n var file = el.getAttribute('data-source-file');\n var line = el.getAttribute('data-source-line');\n var col = el.getAttribute('data-source-col');\n var component = el.getAttribute('data-source-component');\n\n return {\n source: file ? { file: file, line: parseInt(line||'0'), col: parseInt(col||'0'), component: component || undefined } : null,\n tagName: el.tagName.toLowerCase(),\n classes: el.className || '',\n computedStyles: styles,\n dimensions: { width: rect.width, height: rect.height, x: rect.x, y: rect.y },\n componentHierarchy: getComponentHierarchy(el),\n url: location.href\n };\n }\n\n // ---- Screenshot ----\n function captureScreenshot(el) {\n return new Promise(function(resolve) {\n try {\n var rect = el.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) { resolve(undefined); return; }\n\n var canvas = document.createElement('canvas');\n var dpr = window.devicePixelRatio || 1;\n var pad = 8;\n var w = Math.ceil(rect.width + pad * 2);\n var h = Math.ceil(rect.height + pad * 2);\n canvas.width = w * dpr;\n canvas.height = h * dpr;\n\n var ctx = canvas.getContext('2d');\n if (!ctx) { resolve(undefined); return; }\n ctx.scale(dpr, dpr);\n\n // Try SVG foreignObject approach\n var clone = el.cloneNode(true);\n copyStyles(el, clone);\n\n var svgNs = 'http://www.w3.org/2000/svg';\n var svg = document.createElementNS(svgNs, 'svg');\n svg.setAttribute('width', String(w));\n svg.setAttribute('height', String(h));\n svg.setAttribute('xmlns', svgNs);\n\n var fo = document.createElementNS(svgNs, 'foreignObject');\n fo.setAttribute('width', '100%');\n fo.setAttribute('height', '100%');\n\n var container = document.createElement('div');\n container.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml');\n container.style.cssText = 'width:' + w + 'px;height:' + h + 'px;display:flex;align-items:center;justify-content:center;background:white;padding:' + pad + 'px;box-sizing:border-box;';\n container.appendChild(clone);\n fo.appendChild(container);\n svg.appendChild(fo);\n\n var svgStr = new XMLSerializer().serializeToString(svg);\n var blob = new Blob([svgStr], { type: 'image/svg+xml;charset=utf-8' });\n var url = URL.createObjectURL(blob);\n\n var img = new Image();\n img.onload = function() {\n ctx.drawImage(img, 0, 0);\n URL.revokeObjectURL(url);\n try { resolve(canvas.toDataURL('image/png')); } catch(e) { resolve(undefined); }\n };\n img.onerror = function() {\n URL.revokeObjectURL(url);\n // Fallback: placeholder\n ctx.fillStyle = '#f8fafc';\n ctx.fillRect(0, 0, w, h);\n ctx.strokeStyle = '#3b82f6';\n ctx.lineWidth = 2;\n ctx.strokeRect(pad, pad, rect.width, rect.height);\n ctx.fillStyle = '#64748b';\n ctx.font = '11px -apple-system, BlinkMacSystemFont, sans-serif';\n ctx.fillText(Math.round(rect.width) + ' x ' + Math.round(rect.height) + 'px', pad + 4, pad + rect.height / 2 + 4);\n try { resolve(canvas.toDataURL('image/png')); } catch(e) { resolve(undefined); }\n };\n img.src = url;\n } catch(e) {\n resolve(undefined);\n }\n });\n }\n\n function copyStyles(src, tgt) {\n var cs = getComputedStyle(src);\n var props = ['display','width','height','padding','margin','border','border-radius','background','background-color','color','font-size','font-weight','font-family','line-height','text-align','box-shadow','opacity','flex-direction','justify-content','align-items','gap','overflow'];\n for (var i = 0; i < props.length; i++) {\n tgt.style.setProperty(props[i], cs.getPropertyValue(props[i]));\n }\n var sc = src.children, tc = tgt.children;\n for (var j = 0; j < sc.length && j < tc.length; j++) {\n if (sc[j] instanceof HTMLElement && tc[j] instanceof HTMLElement) copyStyles(sc[j], tc[j]);\n }\n }\n\n // ---- Capture & Send ----\n function captureAndSend(el) {\n showToast('Capturing context...');\n var ctx = extractContext(el);\n\n captureScreenshot(el).then(function(screenshot) {\n if (screenshot) ctx.screenshotDataUrl = screenshot;\n\n if (import.meta.hot) {\n import.meta.hot.send('ui-context:capture', ctx);\n import.meta.hot.on('ui-context:capture-result', function(result) {\n if (result.success) {\n showToast('Context captured! Check .ui-context/latest.md');\n } else {\n showToast('Capture failed: ' + (result.error || 'unknown error'));\n }\n });\n }\n });\n }\n\n function captureAllSelected() {\n if (multiSelected.size === 0) {\n showToast('No elements selected. Use Shift+Click to select multiple.');\n return;\n }\n showToast('Capturing ' + multiSelected.size + ' elements...');\n\n var elements = Array.from(multiSelected);\n var contexts = [];\n var pending = elements.length;\n\n elements.forEach(function(el) {\n var ctx = extractContext(el);\n captureScreenshot(el).then(function(screenshot) {\n if (screenshot) ctx.screenshotDataUrl = screenshot;\n contexts.push(ctx);\n pending--;\n if (pending === 0) {\n if (import.meta.hot) {\n import.meta.hot.send('ui-context:capture', contexts);\n import.meta.hot.on('ui-context:capture-result', function(result) {\n if (result.success) {\n showToast(contexts.length + ' elements captured!');\n clearMultiSelection();\n } else {\n showToast('Capture failed: ' + (result.error || 'unknown error'));\n }\n });\n }\n }\n });\n });\n }\n\n function updateMultiBadge() {\n if (!overlayRef) return;\n var btn = overlayRef.shadow.getElementById('capture-all-btn');\n var badge = overlayRef.shadow.getElementById('multi-badge');\n if (multiSelected.size > 0) {\n btn.style.display = '';\n badge.style.display = '';\n badge.textContent = String(multiSelected.size);\n } else {\n btn.style.display = 'none';\n badge.style.display = 'none';\n }\n }\n\n function clearMultiSelection() {\n multiSelected.forEach(function(el) { el.style.outline = ''; });\n multiSelected.clear();\n updateMultiBadge();\n }\n\n // ---- Freeze Mode ----\n function toggleFreeze() {\n if (isFrozen) {\n unfreezeDOM();\n showToast('DOM unfrozen');\n } else {\n freezeDOM();\n showToast('DOM frozen — hover states preserved');\n }\n var btn = overlayRef && overlayRef.shadow.getElementById('freeze-btn');\n if (btn) {\n if (isFrozen) {\n btn.classList.add('active');\n btn.textContent = 'Frozen';\n } else {\n btn.classList.remove('active');\n btn.textContent = 'Freeze';\n }\n }\n }\n\n function freezeDOM() {\n isFrozen = true;\n var observer = new MutationObserver(function(mutations) {\n for (var i = 0; i < mutations.length; i++) {\n var m = mutations[i];\n for (var j = 0; j < m.addedNodes.length; j++) {\n var node = m.addedNodes[j];\n if (node instanceof HTMLElement && !(node.id && node.id.indexOf('ui-context') !== -1)) {\n node.remove();\n }\n }\n if (m.type === 'attributes' && m.target instanceof HTMLElement) {\n if (!(m.target.id && m.target.id.indexOf('ui-context') !== -1)) {\n var old = m.oldValue;\n if (old !== null && m.attributeName) {\n m.target.setAttribute(m.attributeName, old);\n }\n }\n }\n }\n });\n observer.observe(document.body, {\n childList: true, subtree: true, attributes: true, attributeOldValue: true\n });\n frozenObservers.push(observer);\n }\n\n function unfreezeDOM() {\n isFrozen = false;\n frozenObservers.forEach(function(obs) { obs.disconnect(); });\n frozenObservers = [];\n }\n\n // ---- Event Handlers ----\n function isOverlayEl(t) {\n return t.id === 'ui-context-host' || (t.closest && t.closest('#ui-context-host'));\n }\n\n function onMouseMove(e) {\n if (!isActive) return;\n var t = e.target;\n if (isOverlayEl(t)) return;\n showHighlight(t);\n }\n\n function onClick(e) {\n if (!isActive) return;\n var t = e.target;\n if (isOverlayEl(t)) return;\n e.preventDefault();\n e.stopPropagation();\n\n // Shift+Click: multi-select\n if (e.shiftKey) {\n if (multiSelected.has(t)) {\n multiSelected.delete(t);\n t.style.outline = '';\n } else {\n multiSelected.add(t);\n t.style.outline = '2px dashed #f59e0b';\n }\n updateMultiBadge();\n return;\n }\n\n selectedEl = t;\n captureAndSend(t);\n }\n\n // ---- Activate / Deactivate ----\n function activate() {\n if (isActive) return;\n isActive = true;\n overlayRef = createOverlay();\n toolbarEl.style.display = 'flex';\n document.addEventListener('mousemove', onMouseMove, true);\n document.addEventListener('click', onClick, true);\n document.body.style.cursor = 'crosshair';\n showToast('Click to capture, Shift+click for multi-select', 2000);\n }\n\n function deactivate() {\n if (!isActive) return;\n isActive = false;\n selectedEl = null;\n if (isFrozen) unfreezeDOM();\n clearMultiSelection();\n document.removeEventListener('mousemove', onMouseMove, true);\n document.removeEventListener('click', onClick, true);\n document.body.style.cursor = '';\n if (overlayRef) {\n overlayRef.host.remove();\n overlayRef = null;\n highlightEl = null;\n toolbarEl = null;\n }\n }\n\n // ---- Keyboard Shortcuts ----\n document.addEventListener('keydown', function(e) {\n var keys = SHORTCUT.split('+');\n var needsAlt = keys.indexOf('alt') !== -1;\n var needsCtrl = keys.indexOf('ctrl') !== -1;\n var needsShift = keys.indexOf('shift') !== -1;\n var mainKey = keys[keys.length - 1].toLowerCase();\n var mainCode = /^[a-z]$/.test(mainKey) ? 'Key' + mainKey.toUpperCase() : /^[0-9]$/.test(mainKey) ? 'Digit' + mainKey : '';\n\n if (e.altKey === needsAlt && e.ctrlKey === needsCtrl && e.shiftKey === needsShift && (mainCode ? e.code === mainCode : e.key.toLowerCase() === mainKey)) {\n e.preventDefault();\n isActive ? deactivate() : activate();\n return;\n }\n\n // Freeze: Ctrl+Shift+F (only when active)\n if (isActive && e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'f') {\n e.preventDefault();\n toggleFreeze();\n }\n });\n\n // ---- Onboarding Banner ----\n function showOnboarding() {\n try { if (localStorage.getItem(ONBOARDING_KEY)) return; } catch(e) { return; }\n\n // Wait for overlay ref to be set up\n var bannerHost = document.createElement('div');\n bannerHost.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483646;pointer-events:none;';\n document.body.appendChild(bannerHost);\n var bannerShadow = bannerHost.attachShadow({ mode: 'open' });\n\n var shortcutDisplay = SHORTCUT.split('+').map(function(k) { return k.charAt(0).toUpperCase() + k.slice(1); }).join(' + ');\n\n bannerShadow.innerHTML = [\n '<style>',\n '.banner { position:fixed; bottom:20px; left:50%; transform:translateX(-50%); background:linear-gradient(135deg,#0f172a 0%,#1e293b 100%); border:1px solid #334155; border-radius:12px; padding:12px 20px; display:flex; gap:12px; align-items:center; font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif; box-shadow:0 8px 32px rgba(0,0,0,0.4); animation:bannerIn 0.4s ease; max-width:480px; pointer-events:auto; }',\n '@keyframes bannerIn { from { opacity:0; transform:translateX(-50%) translateY(20px); } to { opacity:1; transform:translateX(-50%) translateY(0); } }',\n '.text { color:#e2e8f0; font-size:13px; line-height:1.4; }',\n '.text strong { color:#60a5fa; }',\n '.kbd { display:inline-block; background:#334155; color:#e2e8f0; padding:1px 6px; border-radius:4px; font-size:12px; font-family:monospace; border:1px solid #475569; }',\n '.close { background:none; border:none; color:#64748b; cursor:pointer; padding:4px; font-size:16px; flex-shrink:0; }',\n '.close:hover { color:#94a3b8; }',\n '</style>',\n '<div class=\"banner\">',\n ' <span style=\"font-size:20px\">\\\\u{1F3AF}</span>',\n ' <span class=\"text\">',\n ' <strong>UI Context Kit</strong> is ready! Press <kbd class=\"kbd\">' + shortcutDisplay + '</kbd> to capture any UI element for AI.',\n ' <strong>Shift+Click</strong> for multi-select, <strong>Ctrl+Shift+F</strong> to freeze state.',\n ' </span>',\n ' <button class=\"close\" title=\"Dismiss\">\\\\u2715</button>',\n '</div>',\n ].join('\\\\n');\n\n bannerShadow.querySelector('.close').addEventListener('click', function() {\n bannerHost.remove();\n try { localStorage.setItem(ONBOARDING_KEY, '1'); } catch(e) {}\n });\n\n setTimeout(function() {\n if (bannerHost.parentNode) {\n var banner = bannerShadow.querySelector('.banner');\n if (banner) {\n banner.style.transition = 'opacity 0.3s ease';\n banner.style.opacity = '0';\n setTimeout(function() { bannerHost.remove(); }, 300);\n }\n }\n }, 8000);\n }\n\n showOnboarding();\n console.log('[ui-context-kit] Ready. Press ' + SHORTCUT + ' to activate.');\n})();\n `;\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { ElementContext } from './types';\n\nexport async function writeContext(\n context: ElementContext | ElementContext[],\n projectRoot: string,\n outputDir: string,\n): Promise<string> {\n const outPath = path.resolve(projectRoot, outputDir);\n const capturesDir = path.join(outPath, 'captures');\n\n // Ensure output directories exist\n fs.mkdirSync(outPath, { recursive: true });\n fs.mkdirSync(path.join(outPath, 'screenshots'), { recursive: true });\n fs.mkdirSync(capturesDir, { recursive: true });\n\n const contexts = Array.isArray(context) ? context : [context];\n\n // Save screenshots if available\n const screenshotPaths: (string | undefined)[] = [];\n for (const ctx of contexts) {\n if (ctx.screenshotDataUrl) {\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const filename = `capture-${timestamp}.png`;\n const relPath = `./screenshots/${filename}`;\n const base64 = ctx.screenshotDataUrl.replace(/^data:image\\/\\w+;base64,/, '');\n fs.writeFileSync(path.join(outPath, 'screenshots', filename), Buffer.from(base64, 'base64'));\n screenshotPaths.push(relPath);\n } else {\n screenshotPaths.push(undefined);\n }\n }\n\n // Read source code snippets\n const sourceSnippets: string[] = [];\n for (const ctx of contexts) {\n if (ctx.source) {\n sourceSnippets.push(readSourceSnippet(\n path.resolve(projectRoot, ctx.source.file),\n ctx.source.line,\n 10,\n ));\n } else {\n sourceSnippets.push('');\n }\n }\n\n // Build markdown\n const md = contexts.length === 1\n ? buildMarkdown(contexts[0], sourceSnippets[0], screenshotPaths[0])\n : buildMultiMarkdown(contexts, sourceSnippets, screenshotPaths);\n\n // Write latest.md\n const latestPath = path.join(outPath, 'latest.md');\n fs.writeFileSync(latestPath, md, 'utf-8');\n\n // Write timestamped capture file for history\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const capturePath = path.join(capturesDir, `${timestamp}.md`);\n fs.writeFileSync(capturePath, md, 'utf-8');\n\n // Update history.md (append summary, keep last 20 entries)\n updateHistory(outPath, contexts, timestamp);\n\n // Clean up old captures (keep last 50)\n cleanupOldCaptures(capturesDir, 50);\n\n console.log(`[ui-context-kit] Context written to ${path.relative(projectRoot, latestPath)}`);\n console.log(`[ui-context-kit] History saved to ${path.relative(projectRoot, capturePath)}`);\n\n return latestPath;\n}\n\nfunction updateHistory(outPath: string, contexts: ElementContext[], timestamp: string): void {\n const historyPath = path.join(outPath, 'history.md');\n\n // Build summary for this capture\n const lines: string[] = [];\n const time = timestamp.replace(/T/, ' ').replace(/-(\\d{2})-(\\d{2})-(\\d+)Z?$/, ':$1:$2');\n\n for (const ctx of contexts) {\n const component = ctx.source?.component || ctx.tagName;\n const file = ctx.source ? `${ctx.source.file}:${ctx.source.line}` : '';\n lines.push(`- **${component}** ${file ? `(\\`${file}\\`)` : ''} — ${ctx.url}`);\n }\n\n const entry = `### ${time}\\n${lines.join('\\n')}\\n\\n`;\n\n // Read existing history or create new\n let existing = '';\n try {\n existing = fs.readFileSync(historyPath, 'utf-8');\n } catch {\n existing = '# UI Context Capture History\\n\\n';\n }\n\n // Insert after the header line\n const headerEnd = existing.indexOf('\\n\\n');\n if (headerEnd !== -1) {\n const header = existing.slice(0, headerEnd + 2);\n const body = existing.slice(headerEnd + 2);\n existing = header + entry + body;\n } else {\n existing += entry;\n }\n\n // Keep only last 20 entries\n const entries = existing.split(/(?=### )/);\n const header = entries[0]; // everything before first ###\n const captureEntries = entries.slice(1);\n if (captureEntries.length > 20) {\n existing = header + captureEntries.slice(0, 20).join('');\n }\n\n fs.writeFileSync(historyPath, existing, 'utf-8');\n}\n\nfunction cleanupOldCaptures(capturesDir: string, maxFiles: number): void {\n try {\n const files = fs.readdirSync(capturesDir)\n .filter(f => f.endsWith('.md'))\n .sort()\n .reverse();\n\n for (let i = maxFiles; i < files.length; i++) {\n fs.unlinkSync(path.join(capturesDir, files[i]));\n }\n } catch {\n // ignore cleanup errors\n }\n}\n\nfunction readSourceSnippet(filePath: string, targetLine: number, contextLines: number): string {\n try {\n const content = fs.readFileSync(filePath, 'utf-8');\n const lines = content.split('\\n');\n const start = Math.max(0, targetLine - contextLines - 1);\n const end = Math.min(lines.length, targetLine + contextLines);\n\n return lines\n .slice(start, end)\n .map((line, i) => {\n const lineNum = start + i + 1;\n const marker = lineNum === targetLine ? ' // <-- target' : '';\n return `${line}${marker}`;\n })\n .join('\\n');\n } catch {\n return '// Source file not found';\n }\n}\n\nfunction buildMarkdown(\n context: ElementContext,\n sourceSnippet: string,\n screenshotPath?: string,\n): string {\n const { source, tagName, classes, computedStyles, dimensions, componentHierarchy, url } = context;\n\n const lines: string[] = ['# UI Context Capture', ''];\n\n // Target Element section\n lines.push('## Target Element');\n if (source) {\n if (source.component) {\n lines.push(`- **Component**: \\`${source.component}\\` in \\`${source.file}:${source.line}\\``);\n } else {\n lines.push(`- **File**: \\`${source.file}:${source.line}\\``);\n }\n }\n lines.push(`- **URL**: ${url}`);\n lines.push(`- **Tag**: \\`<${tagName}>\\``);\n lines.push('');\n\n // Source Code section\n if (source && sourceSnippet) {\n const startLine = Math.max(1, source.line - 10);\n const endLine = source.line + 10;\n lines.push('## Source Code');\n lines.push('```tsx');\n lines.push(`// ${source.file}:${startLine}-${endLine}`);\n lines.push(sourceSnippet);\n lines.push('```');\n lines.push('');\n }\n\n // Styling section\n lines.push('## Styling');\n if (classes) {\n lines.push(`- **Classes**: \\`${classes}\\``);\n }\n\n const styleEntries = Object.entries(computedStyles);\n if (styleEntries.length > 0) {\n lines.push(`- **Computed**: ${styleEntries.map(([k, v]) => `${camelToKebab(k)}: ${v}`).join(', ')}`);\n }\n\n lines.push(`- **Dimensions**: ${Math.round(dimensions.width)}x${Math.round(dimensions.height)}px at (${Math.round(dimensions.x)}, ${Math.round(dimensions.y)})`);\n lines.push('');\n\n // Component Hierarchy section\n if (componentHierarchy.length > 0) {\n lines.push('## Component Hierarchy');\n lines.push(componentHierarchy.join(' > '));\n lines.push('');\n }\n\n // Screenshot section\n if (screenshotPath) {\n lines.push('## Screenshot');\n lines.push(`![element](${screenshotPath})`);\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\nfunction buildMultiMarkdown(\n contexts: ElementContext[],\n sourceSnippets: string[],\n screenshotPaths: (string | undefined)[],\n): string {\n const lines: string[] = [\n `# UI Context Capture (${contexts.length} elements)`,\n '',\n ];\n\n for (let i = 0; i < contexts.length; i++) {\n const ctx = contexts[i];\n const snippet = sourceSnippets[i];\n const screenshot = screenshotPaths[i];\n\n lines.push(`---`);\n lines.push('');\n lines.push(`## Element ${i + 1}: \\`<${ctx.tagName}>\\`${ctx.source?.component ? ` (${ctx.source.component})` : ''}`);\n lines.push('');\n\n if (ctx.source) {\n if (ctx.source.component) {\n lines.push(`- **Component**: \\`${ctx.source.component}\\` in \\`${ctx.source.file}:${ctx.source.line}\\``);\n } else {\n lines.push(`- **File**: \\`${ctx.source.file}:${ctx.source.line}\\``);\n }\n }\n lines.push(`- **URL**: ${ctx.url}`);\n lines.push('');\n\n if (ctx.source && snippet) {\n const startLine = Math.max(1, ctx.source.line - 10);\n const endLine = ctx.source.line + 10;\n lines.push('### Source Code');\n lines.push('```tsx');\n lines.push(`// ${ctx.source.file}:${startLine}-${endLine}`);\n lines.push(snippet);\n lines.push('```');\n lines.push('');\n }\n\n lines.push('### Styling');\n if (ctx.classes) {\n lines.push(`- **Classes**: \\`${ctx.classes}\\``);\n }\n const styleEntries = Object.entries(ctx.computedStyles);\n if (styleEntries.length > 0) {\n lines.push(`- **Computed**: ${styleEntries.map(([k, v]) => `${camelToKebab(k)}: ${v}`).join(', ')}`);\n }\n lines.push(`- **Dimensions**: ${Math.round(ctx.dimensions.width)}x${Math.round(ctx.dimensions.height)}px at (${Math.round(ctx.dimensions.x)}, ${Math.round(ctx.dimensions.y)})`);\n lines.push('');\n\n if (ctx.componentHierarchy.length > 0) {\n lines.push('### Component Hierarchy');\n lines.push(ctx.componentHierarchy.join(' > '));\n lines.push('');\n }\n\n if (screenshot) {\n lines.push('### Screenshot');\n lines.push(`![element ${i + 1}](${screenshot})`);\n lines.push('');\n }\n }\n\n return lines.join('\\n');\n}\n\nfunction camelToKebab(str: string): string {\n return str.replace(/[A-Z]/g, m => '-' + m.toLowerCase());\n}\n","import { exec } from 'child_process';\nimport { platform } from 'os';\n\nexport function copyToClipboard(text: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const os = platform();\n let cmd: string;\n\n if (os === 'darwin') {\n cmd = 'pbcopy';\n } else if (os === 'linux') {\n cmd = 'xclip -selection clipboard';\n } else if (os === 'win32') {\n cmd = 'clip';\n } else {\n reject(new Error(`Unsupported platform: ${os}`));\n return;\n }\n\n const proc = exec(cmd, (err) => {\n if (err) reject(err);\n else resolve();\n });\n\n proc.stdin?.write(text);\n proc.stdin?.end();\n });\n}\n","import type { ViteDevServer } from 'vite';\nimport { writeContext } from './context-writer';\nimport { copyToClipboard } from './clipboard';\nimport type { ElementContext, UIContextKitOptions } from './types';\n\nexport function setupWebSocket(server: ViteDevServer, options: UIContextKitOptions): void {\n const root = server.config.root;\n const outputDir = options.outputDir || '.ui-context';\n const shouldCopy = options.clipboard !== false;\n\n server.ws.on('ui-context:capture', async (data: ElementContext | ElementContext[], client) => {\n try {\n const count = Array.isArray(data) ? data.length : 1;\n console.log(`[ui-context-kit] Received context capture (${count} element${count > 1 ? 's' : ''})`);\n\n const filePath = await writeContext(data, root, outputDir);\n\n if (shouldCopy) {\n try {\n const fs = await import('fs');\n const content = fs.readFileSync(filePath, 'utf-8');\n await copyToClipboard(content);\n console.log('[ui-context-kit] Context copied to clipboard');\n } catch (e) {\n console.warn('[ui-context-kit] Could not copy to clipboard:', e);\n }\n }\n\n client.send('ui-context:capture-result', { success: true });\n } catch (err: any) {\n console.error('[ui-context-kit] Error writing context:', err);\n client.send('ui-context:capture-result', { success: false, error: err.message });\n }\n });\n}\n","import path from 'path';\nimport { fileURLToPath } from 'url';\nimport { startContextServer } from './next-server';\nimport type { UIContextKitOptions } from './types';\n\n/**\n * Resolves the path to the next-loader.cjs file in the dist directory.\n */\nfunction resolveLoaderPath(): string {\n try {\n // ESM: import.meta.url is available\n const __dirname = path.dirname(fileURLToPath(import.meta.url));\n return path.resolve(__dirname, 'next-loader.cjs');\n } catch {\n // CJS fallback: __dirname is available\n return path.resolve(__dirname, 'next-loader.cjs');\n }\n}\n\n/**\n * Wraps a Next.js config to add ui-context-kit source attribute injection in development.\n * Supports both webpack and Turbopack.\n *\n * Also starts a standalone HTTP context server (port 19638) so the browser overlay\n * can send captured context without Vite's HMR WebSocket.\n *\n * Usage:\n * ```js\n * // next.config.mjs\n * import { withUIContext } from '@ui-context-kit/bridge';\n * export default withUIContext({ /* your config *\\/ });\n * ```\n */\nexport function withUIContext(nextConfig: any = {}, options?: UIContextKitOptions) {\n if (process.env.NODE_ENV !== 'development') return nextConfig;\n\n // Start the standalone context server for receiving captures\n startContextServer(options);\n\n const loaderPath = resolveLoaderPath();\n\n return {\n ...nextConfig,\n\n // Turbopack support\n experimental: {\n ...nextConfig.experimental,\n turbo: {\n ...nextConfig.experimental?.turbo,\n rules: {\n ...nextConfig.experimental?.turbo?.rules,\n '*.tsx': {\n loaders: [loaderPath],\n as: '*.tsx',\n },\n '*.jsx': {\n loaders: [loaderPath],\n as: '*.jsx',\n },\n },\n },\n },\n\n // Webpack support\n webpack(config: any, context: any) {\n config.module.rules.unshift({\n test: /\\.(jsx|tsx)$/,\n exclude: /node_modules/,\n enforce: 'pre' as const,\n use: [{ loader: loaderPath }],\n });\n\n if (typeof nextConfig.webpack === 'function') {\n config = nextConfig.webpack(config, context);\n }\n\n return config;\n },\n };\n}\n","import http from 'http';\nimport { writeContext } from './context-writer';\nimport { copyToClipboard } from './clipboard';\nimport type { UIContextKitOptions } from './types';\n\nconst DEFAULT_PORT = 19638;\nlet serverInstance: http.Server | null = null;\n\n/**\n * Starts a standalone HTTP server for receiving UI context captures.\n * Used by Next.js projects where Vite's HMR WebSocket is not available.\n *\n * The overlay's transport sends HTTP POST to /capture with the context data.\n */\nexport function startContextServer(options: UIContextKitOptions = {}): void {\n if (serverInstance) return;\n\n const port = DEFAULT_PORT;\n const outputDir = options.outputDir || '.ui-context';\n const shouldCopy = options.clipboard !== false;\n const projectRoot = process.cwd();\n\n serverInstance = http.createServer((req, res) => {\n // CORS headers for cross-port requests\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n if (req.method === 'POST' && req.url === '/capture') {\n let body = '';\n req.on('data', (chunk: string) => {\n body += chunk;\n });\n req.on('end', async () => {\n try {\n const data = JSON.parse(body);\n console.log(\n `[ui-context-kit] Received context capture (${Array.isArray(data) ? data.length : 1} element${Array.isArray(data) && data.length > 1 ? 's' : ''})`,\n );\n\n const filePath = await writeContext(data, projectRoot, outputDir);\n\n if (shouldCopy) {\n try {\n const fs = await import('fs');\n const content = fs.readFileSync(filePath, 'utf-8');\n await copyToClipboard(content);\n console.log('[ui-context-kit] Context copied to clipboard');\n } catch {\n // clipboard copy is best-effort\n }\n }\n\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ success: true }));\n } catch (err: any) {\n console.error('[ui-context-kit] Error writing context:', err);\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ success: false, error: err.message }));\n }\n });\n return;\n }\n\n res.writeHead(404);\n res.end();\n });\n\n serverInstance.listen(port, () => {\n console.log(`[ui-context-kit] Context server running on http://localhost:${port}`);\n });\n\n serverInstance.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n console.log(`[ui-context-kit] Context server already running on port ${port}`);\n serverInstance = null;\n } else {\n console.error('[ui-context-kit] Context server error:', err);\n serverInstance = null;\n }\n });\n}\n"],"mappings":"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AA;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;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;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;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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","names":["import_path","import_fs","path","fs","timestamp","header","fs","path","fs","import_path","http","fs","__dirname","path"]}
package/dist/index.d.cts CHANGED
@@ -36,16 +36,20 @@ interface UIContextKitOptions {
36
36
  declare function writeContext(context: ElementContext | ElementContext[], projectRoot: string, outputDir: string): Promise<string>;
37
37
 
38
38
  /**
39
- * Wraps a Next.js config to add ui-context-kit babel plugin in development.
39
+ * Wraps a Next.js config to add ui-context-kit source attribute injection in development.
40
+ * Supports both webpack and Turbopack.
41
+ *
42
+ * Also starts a standalone HTTP context server (port 19638) so the browser overlay
43
+ * can send captured context without Vite's HMR WebSocket.
40
44
  *
41
45
  * Usage:
42
46
  * ```js
43
- * // next.config.js
44
- * const { withUIContext } = require('@ui-context-kit/bridge');
45
- * module.exports = withUIContext(nextConfig);
47
+ * // next.config.mjs
48
+ * import { withUIContext } from '@ui-context-kit/bridge';
49
+ * export default withUIContext({ /* your config *\/ });
46
50
  * ```
47
51
  */
48
- declare function withUIContext(nextConfig?: any, _options?: UIContextKitOptions): any;
52
+ declare function withUIContext(nextConfig?: any, options?: UIContextKitOptions): any;
49
53
 
50
54
  /**
51
55
  * Vite plugin for UI Context Kit.
package/dist/index.d.ts CHANGED
@@ -36,16 +36,20 @@ interface UIContextKitOptions {
36
36
  declare function writeContext(context: ElementContext | ElementContext[], projectRoot: string, outputDir: string): Promise<string>;
37
37
 
38
38
  /**
39
- * Wraps a Next.js config to add ui-context-kit babel plugin in development.
39
+ * Wraps a Next.js config to add ui-context-kit source attribute injection in development.
40
+ * Supports both webpack and Turbopack.
41
+ *
42
+ * Also starts a standalone HTTP context server (port 19638) so the browser overlay
43
+ * can send captured context without Vite's HMR WebSocket.
40
44
  *
41
45
  * Usage:
42
46
  * ```js
43
- * // next.config.js
44
- * const { withUIContext } = require('@ui-context-kit/bridge');
45
- * module.exports = withUIContext(nextConfig);
47
+ * // next.config.mjs
48
+ * import { withUIContext } from '@ui-context-kit/bridge';
49
+ * export default withUIContext({ /* your config *\/ });
46
50
  * ```
47
51
  */
48
- declare function withUIContext(nextConfig?: any, _options?: UIContextKitOptions): any;
52
+ declare function withUIContext(nextConfig?: any, options?: UIContextKitOptions): any;
49
53
 
50
54
  /**
51
55
  * Vite plugin for UI Context Kit.
package/dist/index.js CHANGED
@@ -775,8 +775,9 @@ function getOverlayCode(shortcut) {
775
775
  var needsCtrl = keys.indexOf('ctrl') !== -1;
776
776
  var needsShift = keys.indexOf('shift') !== -1;
777
777
  var mainKey = keys[keys.length - 1].toLowerCase();
778
+ var mainCode = /^[a-z]$/.test(mainKey) ? 'Key' + mainKey.toUpperCase() : /^[0-9]$/.test(mainKey) ? 'Digit' + mainKey : '';
778
779
 
779
- if (e.altKey === needsAlt && e.ctrlKey === needsCtrl && e.shiftKey === needsShift && e.key.toLowerCase() === mainKey) {
780
+ if (e.altKey === needsAlt && e.ctrlKey === needsCtrl && e.shiftKey === needsShift && (mainCode ? e.code === mainCode : e.key.toLowerCase() === mainKey)) {
780
781
  e.preventDefault();
781
782
  isActive ? deactivate() : activate();
782
783
  return;
@@ -845,11 +846,117 @@ function getOverlayCode(shortcut) {
845
846
  }
846
847
 
847
848
  // src/next-wrapper.ts
848
- function withUIContext(nextConfig = {}, _options) {
849
+ import path3 from "path";
850
+ import { fileURLToPath } from "url";
851
+
852
+ // src/next-server.ts
853
+ import http from "http";
854
+ var DEFAULT_PORT = 19638;
855
+ var serverInstance = null;
856
+ function startContextServer(options = {}) {
857
+ if (serverInstance) return;
858
+ const port = DEFAULT_PORT;
859
+ const outputDir = options.outputDir || ".ui-context";
860
+ const shouldCopy = options.clipboard !== false;
861
+ const projectRoot = process.cwd();
862
+ serverInstance = http.createServer((req, res) => {
863
+ res.setHeader("Access-Control-Allow-Origin", "*");
864
+ res.setHeader("Access-Control-Allow-Methods", "POST, OPTIONS");
865
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type");
866
+ if (req.method === "OPTIONS") {
867
+ res.writeHead(204);
868
+ res.end();
869
+ return;
870
+ }
871
+ if (req.method === "POST" && req.url === "/capture") {
872
+ let body = "";
873
+ req.on("data", (chunk) => {
874
+ body += chunk;
875
+ });
876
+ req.on("end", async () => {
877
+ try {
878
+ const data = JSON.parse(body);
879
+ console.log(
880
+ `[ui-context-kit] Received context capture (${Array.isArray(data) ? data.length : 1} element${Array.isArray(data) && data.length > 1 ? "s" : ""})`
881
+ );
882
+ const filePath = await writeContext(data, projectRoot, outputDir);
883
+ if (shouldCopy) {
884
+ try {
885
+ const fs3 = await import("fs");
886
+ const content = fs3.readFileSync(filePath, "utf-8");
887
+ await copyToClipboard(content);
888
+ console.log("[ui-context-kit] Context copied to clipboard");
889
+ } catch {
890
+ }
891
+ }
892
+ res.writeHead(200, { "Content-Type": "application/json" });
893
+ res.end(JSON.stringify({ success: true }));
894
+ } catch (err) {
895
+ console.error("[ui-context-kit] Error writing context:", err);
896
+ res.writeHead(500, { "Content-Type": "application/json" });
897
+ res.end(JSON.stringify({ success: false, error: err.message }));
898
+ }
899
+ });
900
+ return;
901
+ }
902
+ res.writeHead(404);
903
+ res.end();
904
+ });
905
+ serverInstance.listen(port, () => {
906
+ console.log(`[ui-context-kit] Context server running on http://localhost:${port}`);
907
+ });
908
+ serverInstance.on("error", (err) => {
909
+ if (err.code === "EADDRINUSE") {
910
+ console.log(`[ui-context-kit] Context server already running on port ${port}`);
911
+ serverInstance = null;
912
+ } else {
913
+ console.error("[ui-context-kit] Context server error:", err);
914
+ serverInstance = null;
915
+ }
916
+ });
917
+ }
918
+
919
+ // src/next-wrapper.ts
920
+ function resolveLoaderPath() {
921
+ try {
922
+ const __dirname2 = path3.dirname(fileURLToPath(import.meta.url));
923
+ return path3.resolve(__dirname2, "next-loader.cjs");
924
+ } catch {
925
+ return path3.resolve(__dirname, "next-loader.cjs");
926
+ }
927
+ }
928
+ function withUIContext(nextConfig = {}, options) {
849
929
  if (process.env.NODE_ENV !== "development") return nextConfig;
930
+ startContextServer(options);
931
+ const loaderPath = resolveLoaderPath();
850
932
  return {
851
933
  ...nextConfig,
934
+ // Turbopack support
935
+ experimental: {
936
+ ...nextConfig.experimental,
937
+ turbo: {
938
+ ...nextConfig.experimental?.turbo,
939
+ rules: {
940
+ ...nextConfig.experimental?.turbo?.rules,
941
+ "*.tsx": {
942
+ loaders: [loaderPath],
943
+ as: "*.tsx"
944
+ },
945
+ "*.jsx": {
946
+ loaders: [loaderPath],
947
+ as: "*.jsx"
948
+ }
949
+ }
950
+ }
951
+ },
952
+ // Webpack support
852
953
  webpack(config, context) {
954
+ config.module.rules.unshift({
955
+ test: /\.(jsx|tsx)$/,
956
+ exclude: /node_modules/,
957
+ enforce: "pre",
958
+ use: [{ loader: loaderPath }]
959
+ });
853
960
  if (typeof nextConfig.webpack === "function") {
854
961
  config = nextConfig.webpack(config, context);
855
962
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/vite-plugin.ts","../src/context-writer.ts","../src/clipboard.ts","../src/ws-server.ts","../src/next-wrapper.ts","../src/index.ts"],"sourcesContent":["import type { Plugin } from 'vite';\nimport path from 'path';\nimport fs from 'fs';\nimport { injectSourceAttributes } from '@ui-context-kit/babel-plugin';\nimport { setupWebSocket } from './ws-server';\nimport type { UIContextKitOptions } from './types';\n\nconst JSX_EXTENSIONS = /\\.(jsx|tsx)$/;\nconst VIRTUAL_MODULE_ID = 'virtual:ui-context-overlay';\nconst RESOLVED_VIRTUAL_MODULE_ID = '\\0' + VIRTUAL_MODULE_ID;\n\nexport function createVitePlugin(options: UIContextKitOptions = {}): Plugin[] {\n const {\n shortcut = 'alt+x',\n include,\n exclude = ['node_modules'],\n } = options;\n\n let projectRoot = '';\n\n const transformPlugin: Plugin = {\n name: 'ui-context-kit:transform',\n enforce: 'pre',\n apply: 'serve',\n\n configResolved(config) {\n projectRoot = config.root;\n },\n\n transform(code, id) {\n if (!JSX_EXTENSIONS.test(id)) return null;\n\n const relativePath = path.relative(projectRoot, id);\n if (exclude?.some(p => relativePath.includes(p))) return null;\n if (include && !include.some(p => relativePath.includes(p))) return null;\n if (id.includes('\\0') || id.includes('node_modules')) return null;\n\n const filePath = path.relative(projectRoot, id);\n\n let originalCode: string | undefined;\n try {\n originalCode = fs.readFileSync(id, 'utf-8');\n } catch {\n // ignore read errors\n }\n\n const result = injectSourceAttributes(code, filePath, originalCode);\n if (!result) return null;\n\n return { code: result.code, map: result.map };\n },\n };\n\n const overlayPlugin: Plugin = {\n name: 'ui-context-kit:overlay',\n apply: 'serve',\n\n resolveId(id) {\n if (id === VIRTUAL_MODULE_ID) return RESOLVED_VIRTUAL_MODULE_ID;\n },\n\n load(id) {\n if (id === RESOLVED_VIRTUAL_MODULE_ID) {\n return getOverlayCode(shortcut);\n }\n },\n\n configureServer(server) {\n setupWebSocket(server, options);\n },\n\n transformIndexHtml() {\n return [\n {\n tag: 'script',\n attrs: { type: 'module', src: `/@id/${VIRTUAL_MODULE_ID}` },\n injectTo: 'body' as const,\n },\n ];\n },\n };\n\n return [transformPlugin, overlayPlugin];\n}\n\nfunction getOverlayCode(shortcut: string): string {\n return `\n// UI Context Kit - Overlay (auto-injected in dev mode)\n(function() {\n if (typeof window === 'undefined') return;\n\n var isActive = false;\n var highlightEl = null;\n var toolbarEl = null;\n var selectedEl = null;\n var isFrozen = false;\n var frozenObservers = [];\n var multiSelected = new Set();\n\n var SHORTCUT = '${shortcut}';\n var ONBOARDING_KEY = 'ui-context-kit-onboarding-dismissed';\n\n // ---- Shadow DOM Overlay ----\n function createOverlay() {\n var host = document.createElement('div');\n host.id = 'ui-context-host';\n host.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;pointer-events:none;';\n document.body.appendChild(host);\n\n var shadow = host.attachShadow({ mode: 'open' });\n shadow.innerHTML = [\n '<style>',\n '.highlight { position:fixed; border:2px solid #3b82f6; background:rgba(59,130,246,0.08); pointer-events:none; transition:all 0.15s ease; border-radius:3px; display:none; }',\n '.highlight-label { position:absolute; top:-22px; left:-2px; background:#3b82f6; color:white; font-size:11px; font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif; padding:2px 8px; border-radius:3px 3px 0 0; white-space:nowrap; }',\n '.toolbar { position:fixed; bottom:20px; left:50%; transform:translateX(-50%); background:#0f172a; border:1px solid #334155; border-radius:12px; padding:8px 12px; display:flex; gap:6px; align-items:center; font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif; box-shadow:0 8px 32px rgba(0,0,0,0.5); pointer-events:auto; }',\n '.toolbar-label { color:#94a3b8; font-size:12px; padding:0 4px; }',\n '.toolbar-btn { color:white; border:none; padding:6px 14px; border-radius:6px; font-size:12px; font-weight:500; cursor:pointer; white-space:nowrap; }',\n '.toolbar-btn:hover { filter:brightness(1.15); }',\n '.toolbar-btn.primary { background:#3b82f6; }',\n '.toolbar-btn.secondary { background:#475569; }',\n '.toolbar-btn.freeze { background:#475569; }',\n '.toolbar-btn.freeze.active { background:#f59e0b; color:#1e293b; }',\n '.badge { display:inline-block; background:#f59e0b; color:#1e293b; font-size:10px; font-weight:700; padding:1px 5px; border-radius:10px; margin-left:4px; }',\n '.divider { width:1px; height:20px; background:#334155; }',\n '.toast { position:fixed; bottom:72px; left:50%; transform:translateX(-50%); background:#0f172a; color:#e2e8f0; padding:10px 20px; border-radius:8px; font-size:13px; font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif; box-shadow:0 4px 16px rgba(0,0,0,0.4); pointer-events:none; animation:toastIn 0.2s ease; }',\n '@keyframes toastIn { from { opacity:0; transform:translateX(-50%) translateY(8px); } }',\n '.banner { position:fixed; bottom:20px; left:50%; transform:translateX(-50%); background:linear-gradient(135deg,#0f172a 0%,#1e293b 100%); border:1px solid #334155; border-radius:12px; padding:12px 20px; display:flex; gap:12px; align-items:center; font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif; box-shadow:0 8px 32px rgba(0,0,0,0.4); animation:bannerIn 0.4s ease; max-width:480px; pointer-events:auto; }',\n '@keyframes bannerIn { from { opacity:0; transform:translateX(-50%) translateY(20px); } to { opacity:1; transform:translateX(-50%) translateY(0); } }',\n '.banner-text { color:#e2e8f0; font-size:13px; line-height:1.4; }',\n '.banner-text strong { color:#60a5fa; }',\n '.kbd { display:inline-block; background:#334155; color:#e2e8f0; padding:1px 6px; border-radius:4px; font-size:12px; font-family:monospace; border:1px solid #475569; }',\n '.banner-close { background:none; border:none; color:#64748b; cursor:pointer; padding:4px; font-size:16px; flex-shrink:0; }',\n '.banner-close:hover { color:#94a3b8; }',\n '</style>',\n '<div class=\"highlight\"><div class=\"highlight-label\"></div></div>',\n '<div class=\"toolbar\" style=\"display:none\">',\n ' <span class=\"toolbar-label\">UI Context</span>',\n ' <div class=\"divider\"></div>',\n ' <button class=\"toolbar-btn primary\" id=\"capture-btn\">Capture</button>',\n ' <button class=\"toolbar-btn primary\" id=\"capture-all-btn\" style=\"display:none\">Capture All <span class=\"badge\" id=\"multi-badge\" style=\"display:none\">0</span></button>',\n ' <div class=\"divider\"></div>',\n ' <button class=\"toolbar-btn freeze\" id=\"freeze-btn\" title=\"Freeze DOM (Ctrl+Shift+F)\">Freeze</button>',\n ' <button class=\"toolbar-btn secondary\" id=\"close-btn\">\\\\u2715</button>',\n '</div>',\n ].join('\\\\n');\n\n highlightEl = shadow.querySelector('.highlight');\n toolbarEl = shadow.querySelector('.toolbar');\n\n shadow.getElementById('close-btn').addEventListener('click', deactivate);\n shadow.getElementById('capture-btn').addEventListener('click', function() {\n if (selectedEl) captureAndSend(selectedEl);\n });\n shadow.getElementById('capture-all-btn').addEventListener('click', captureAllSelected);\n shadow.getElementById('freeze-btn').addEventListener('click', toggleFreeze);\n\n return { host: host, shadow: shadow };\n }\n\n var overlayRef = null;\n\n function showHighlight(el) {\n if (!highlightEl || !el) { highlightEl && (highlightEl.style.display = 'none'); return; }\n var rect = el.getBoundingClientRect();\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\n var label = highlightEl.querySelector('.highlight-label');\n var src = el.getAttribute('data-source-file');\n var line = el.getAttribute('data-source-line');\n var comp = el.getAttribute('data-source-component');\n label.textContent = src\n ? (comp || el.tagName.toLowerCase()) + ' \\\\u00b7 ' + src + ':' + line\n : el.tagName.toLowerCase();\n }\n\n function showToast(msg, duration) {\n if (!overlayRef) return;\n duration = duration || 3000;\n var t = document.createElement('div');\n t.className = 'toast';\n t.textContent = msg;\n overlayRef.shadow.appendChild(t);\n setTimeout(function() { t.remove(); }, duration);\n }\n\n // ---- React Fiber Hierarchy ----\n function getComponentHierarchy(el) {\n var fiberKey = Object.keys(el).find(function(k) {\n return k.startsWith('__reactFiber$') || k.startsWith('__reactInternalInstance$');\n });\n if (!fiberKey) return [];\n var hierarchy = [];\n var fiber = el[fiberKey];\n while (fiber) {\n if (typeof fiber.type === 'function') {\n var name = fiber.type.displayName || fiber.type.name;\n if (name && !name.startsWith('_') && name !== 'Fragment') hierarchy.unshift(name);\n } else if (typeof fiber.type === 'object' && fiber.type) {\n var name = fiber.type.displayName || (fiber.type.render && (fiber.type.render.displayName || fiber.type.render.name));\n if (name && !name.startsWith('_') && name !== 'Fragment') hierarchy.unshift(name);\n }\n fiber = fiber.return;\n }\n return hierarchy;\n }\n\n // ---- Computed Styles ----\n var STYLE_PROPS = [\n 'padding','padding-top','padding-right','padding-bottom','padding-left',\n 'margin','margin-top','margin-right','margin-bottom','margin-left',\n 'background-color','color','font-size','font-weight','font-family',\n 'border-radius','display','flex-direction','justify-content','align-items',\n 'gap','width','height','overflow','position','z-index','opacity',\n 'border','box-shadow','line-height','letter-spacing','text-align'\n ];\n\n function extractContext(el) {\n var computed = getComputedStyle(el);\n var rect = el.getBoundingClientRect();\n var styles = {};\n for (var i = 0; i < STYLE_PROPS.length; i++) {\n var p = STYLE_PROPS[i];\n var v = computed.getPropertyValue(p);\n if (v && v !== 'none' && v !== 'normal' && v !== 'auto' && v !== '0px' && v !== 'rgba(0, 0, 0, 0)') {\n styles[p] = v;\n }\n }\n\n var file = el.getAttribute('data-source-file');\n var line = el.getAttribute('data-source-line');\n var col = el.getAttribute('data-source-col');\n var component = el.getAttribute('data-source-component');\n\n return {\n source: file ? { file: file, line: parseInt(line||'0'), col: parseInt(col||'0'), component: component || undefined } : null,\n tagName: el.tagName.toLowerCase(),\n classes: el.className || '',\n computedStyles: styles,\n dimensions: { width: rect.width, height: rect.height, x: rect.x, y: rect.y },\n componentHierarchy: getComponentHierarchy(el),\n url: location.href\n };\n }\n\n // ---- Screenshot ----\n function captureScreenshot(el) {\n return new Promise(function(resolve) {\n try {\n var rect = el.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) { resolve(undefined); return; }\n\n var canvas = document.createElement('canvas');\n var dpr = window.devicePixelRatio || 1;\n var pad = 8;\n var w = Math.ceil(rect.width + pad * 2);\n var h = Math.ceil(rect.height + pad * 2);\n canvas.width = w * dpr;\n canvas.height = h * dpr;\n\n var ctx = canvas.getContext('2d');\n if (!ctx) { resolve(undefined); return; }\n ctx.scale(dpr, dpr);\n\n // Try SVG foreignObject approach\n var clone = el.cloneNode(true);\n copyStyles(el, clone);\n\n var svgNs = 'http://www.w3.org/2000/svg';\n var svg = document.createElementNS(svgNs, 'svg');\n svg.setAttribute('width', String(w));\n svg.setAttribute('height', String(h));\n svg.setAttribute('xmlns', svgNs);\n\n var fo = document.createElementNS(svgNs, 'foreignObject');\n fo.setAttribute('width', '100%');\n fo.setAttribute('height', '100%');\n\n var container = document.createElement('div');\n container.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml');\n container.style.cssText = 'width:' + w + 'px;height:' + h + 'px;display:flex;align-items:center;justify-content:center;background:white;padding:' + pad + 'px;box-sizing:border-box;';\n container.appendChild(clone);\n fo.appendChild(container);\n svg.appendChild(fo);\n\n var svgStr = new XMLSerializer().serializeToString(svg);\n var blob = new Blob([svgStr], { type: 'image/svg+xml;charset=utf-8' });\n var url = URL.createObjectURL(blob);\n\n var img = new Image();\n img.onload = function() {\n ctx.drawImage(img, 0, 0);\n URL.revokeObjectURL(url);\n try { resolve(canvas.toDataURL('image/png')); } catch(e) { resolve(undefined); }\n };\n img.onerror = function() {\n URL.revokeObjectURL(url);\n // Fallback: placeholder\n ctx.fillStyle = '#f8fafc';\n ctx.fillRect(0, 0, w, h);\n ctx.strokeStyle = '#3b82f6';\n ctx.lineWidth = 2;\n ctx.strokeRect(pad, pad, rect.width, rect.height);\n ctx.fillStyle = '#64748b';\n ctx.font = '11px -apple-system, BlinkMacSystemFont, sans-serif';\n ctx.fillText(Math.round(rect.width) + ' x ' + Math.round(rect.height) + 'px', pad + 4, pad + rect.height / 2 + 4);\n try { resolve(canvas.toDataURL('image/png')); } catch(e) { resolve(undefined); }\n };\n img.src = url;\n } catch(e) {\n resolve(undefined);\n }\n });\n }\n\n function copyStyles(src, tgt) {\n var cs = getComputedStyle(src);\n var props = ['display','width','height','padding','margin','border','border-radius','background','background-color','color','font-size','font-weight','font-family','line-height','text-align','box-shadow','opacity','flex-direction','justify-content','align-items','gap','overflow'];\n for (var i = 0; i < props.length; i++) {\n tgt.style.setProperty(props[i], cs.getPropertyValue(props[i]));\n }\n var sc = src.children, tc = tgt.children;\n for (var j = 0; j < sc.length && j < tc.length; j++) {\n if (sc[j] instanceof HTMLElement && tc[j] instanceof HTMLElement) copyStyles(sc[j], tc[j]);\n }\n }\n\n // ---- Capture & Send ----\n function captureAndSend(el) {\n showToast('Capturing context...');\n var ctx = extractContext(el);\n\n captureScreenshot(el).then(function(screenshot) {\n if (screenshot) ctx.screenshotDataUrl = screenshot;\n\n if (import.meta.hot) {\n import.meta.hot.send('ui-context:capture', ctx);\n import.meta.hot.on('ui-context:capture-result', function(result) {\n if (result.success) {\n showToast('Context captured! Check .ui-context/latest.md');\n } else {\n showToast('Capture failed: ' + (result.error || 'unknown error'));\n }\n });\n }\n });\n }\n\n function captureAllSelected() {\n if (multiSelected.size === 0) {\n showToast('No elements selected. Use Shift+Click to select multiple.');\n return;\n }\n showToast('Capturing ' + multiSelected.size + ' elements...');\n\n var elements = Array.from(multiSelected);\n var contexts = [];\n var pending = elements.length;\n\n elements.forEach(function(el) {\n var ctx = extractContext(el);\n captureScreenshot(el).then(function(screenshot) {\n if (screenshot) ctx.screenshotDataUrl = screenshot;\n contexts.push(ctx);\n pending--;\n if (pending === 0) {\n if (import.meta.hot) {\n import.meta.hot.send('ui-context:capture', contexts);\n import.meta.hot.on('ui-context:capture-result', function(result) {\n if (result.success) {\n showToast(contexts.length + ' elements captured!');\n clearMultiSelection();\n } else {\n showToast('Capture failed: ' + (result.error || 'unknown error'));\n }\n });\n }\n }\n });\n });\n }\n\n function updateMultiBadge() {\n if (!overlayRef) return;\n var btn = overlayRef.shadow.getElementById('capture-all-btn');\n var badge = overlayRef.shadow.getElementById('multi-badge');\n if (multiSelected.size > 0) {\n btn.style.display = '';\n badge.style.display = '';\n badge.textContent = String(multiSelected.size);\n } else {\n btn.style.display = 'none';\n badge.style.display = 'none';\n }\n }\n\n function clearMultiSelection() {\n multiSelected.forEach(function(el) { el.style.outline = ''; });\n multiSelected.clear();\n updateMultiBadge();\n }\n\n // ---- Freeze Mode ----\n function toggleFreeze() {\n if (isFrozen) {\n unfreezeDOM();\n showToast('DOM unfrozen');\n } else {\n freezeDOM();\n showToast('DOM frozen — hover states preserved');\n }\n var btn = overlayRef && overlayRef.shadow.getElementById('freeze-btn');\n if (btn) {\n if (isFrozen) {\n btn.classList.add('active');\n btn.textContent = 'Frozen';\n } else {\n btn.classList.remove('active');\n btn.textContent = 'Freeze';\n }\n }\n }\n\n function freezeDOM() {\n isFrozen = true;\n var observer = new MutationObserver(function(mutations) {\n for (var i = 0; i < mutations.length; i++) {\n var m = mutations[i];\n for (var j = 0; j < m.addedNodes.length; j++) {\n var node = m.addedNodes[j];\n if (node instanceof HTMLElement && !(node.id && node.id.indexOf('ui-context') !== -1)) {\n node.remove();\n }\n }\n if (m.type === 'attributes' && m.target instanceof HTMLElement) {\n if (!(m.target.id && m.target.id.indexOf('ui-context') !== -1)) {\n var old = m.oldValue;\n if (old !== null && m.attributeName) {\n m.target.setAttribute(m.attributeName, old);\n }\n }\n }\n }\n });\n observer.observe(document.body, {\n childList: true, subtree: true, attributes: true, attributeOldValue: true\n });\n frozenObservers.push(observer);\n }\n\n function unfreezeDOM() {\n isFrozen = false;\n frozenObservers.forEach(function(obs) { obs.disconnect(); });\n frozenObservers = [];\n }\n\n // ---- Event Handlers ----\n function isOverlayEl(t) {\n return t.id === 'ui-context-host' || (t.closest && t.closest('#ui-context-host'));\n }\n\n function onMouseMove(e) {\n if (!isActive) return;\n var t = e.target;\n if (isOverlayEl(t)) return;\n showHighlight(t);\n }\n\n function onClick(e) {\n if (!isActive) return;\n var t = e.target;\n if (isOverlayEl(t)) return;\n e.preventDefault();\n e.stopPropagation();\n\n // Shift+Click: multi-select\n if (e.shiftKey) {\n if (multiSelected.has(t)) {\n multiSelected.delete(t);\n t.style.outline = '';\n } else {\n multiSelected.add(t);\n t.style.outline = '2px dashed #f59e0b';\n }\n updateMultiBadge();\n return;\n }\n\n selectedEl = t;\n captureAndSend(t);\n }\n\n // ---- Activate / Deactivate ----\n function activate() {\n if (isActive) return;\n isActive = true;\n overlayRef = createOverlay();\n toolbarEl.style.display = 'flex';\n document.addEventListener('mousemove', onMouseMove, true);\n document.addEventListener('click', onClick, true);\n document.body.style.cursor = 'crosshair';\n showToast('Click to capture, Shift+click for multi-select', 2000);\n }\n\n function deactivate() {\n if (!isActive) return;\n isActive = false;\n selectedEl = null;\n if (isFrozen) unfreezeDOM();\n clearMultiSelection();\n document.removeEventListener('mousemove', onMouseMove, true);\n document.removeEventListener('click', onClick, true);\n document.body.style.cursor = '';\n if (overlayRef) {\n overlayRef.host.remove();\n overlayRef = null;\n highlightEl = null;\n toolbarEl = null;\n }\n }\n\n // ---- Keyboard Shortcuts ----\n document.addEventListener('keydown', function(e) {\n var keys = SHORTCUT.split('+');\n var needsAlt = keys.indexOf('alt') !== -1;\n var needsCtrl = keys.indexOf('ctrl') !== -1;\n var needsShift = keys.indexOf('shift') !== -1;\n var mainKey = keys[keys.length - 1].toLowerCase();\n\n if (e.altKey === needsAlt && e.ctrlKey === needsCtrl && e.shiftKey === needsShift && e.key.toLowerCase() === mainKey) {\n e.preventDefault();\n isActive ? deactivate() : activate();\n return;\n }\n\n // Freeze: Ctrl+Shift+F (only when active)\n if (isActive && e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'f') {\n e.preventDefault();\n toggleFreeze();\n }\n });\n\n // ---- Onboarding Banner ----\n function showOnboarding() {\n try { if (localStorage.getItem(ONBOARDING_KEY)) return; } catch(e) { return; }\n\n // Wait for overlay ref to be set up\n var bannerHost = document.createElement('div');\n bannerHost.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483646;pointer-events:none;';\n document.body.appendChild(bannerHost);\n var bannerShadow = bannerHost.attachShadow({ mode: 'open' });\n\n var shortcutDisplay = SHORTCUT.split('+').map(function(k) { return k.charAt(0).toUpperCase() + k.slice(1); }).join(' + ');\n\n bannerShadow.innerHTML = [\n '<style>',\n '.banner { position:fixed; bottom:20px; left:50%; transform:translateX(-50%); background:linear-gradient(135deg,#0f172a 0%,#1e293b 100%); border:1px solid #334155; border-radius:12px; padding:12px 20px; display:flex; gap:12px; align-items:center; font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif; box-shadow:0 8px 32px rgba(0,0,0,0.4); animation:bannerIn 0.4s ease; max-width:480px; pointer-events:auto; }',\n '@keyframes bannerIn { from { opacity:0; transform:translateX(-50%) translateY(20px); } to { opacity:1; transform:translateX(-50%) translateY(0); } }',\n '.text { color:#e2e8f0; font-size:13px; line-height:1.4; }',\n '.text strong { color:#60a5fa; }',\n '.kbd { display:inline-block; background:#334155; color:#e2e8f0; padding:1px 6px; border-radius:4px; font-size:12px; font-family:monospace; border:1px solid #475569; }',\n '.close { background:none; border:none; color:#64748b; cursor:pointer; padding:4px; font-size:16px; flex-shrink:0; }',\n '.close:hover { color:#94a3b8; }',\n '</style>',\n '<div class=\"banner\">',\n ' <span style=\"font-size:20px\">\\\\u{1F3AF}</span>',\n ' <span class=\"text\">',\n ' <strong>UI Context Kit</strong> is ready! Press <kbd class=\"kbd\">' + shortcutDisplay + '</kbd> to capture any UI element for AI.',\n ' <strong>Shift+Click</strong> for multi-select, <strong>Ctrl+Shift+F</strong> to freeze state.',\n ' </span>',\n ' <button class=\"close\" title=\"Dismiss\">\\\\u2715</button>',\n '</div>',\n ].join('\\\\n');\n\n bannerShadow.querySelector('.close').addEventListener('click', function() {\n bannerHost.remove();\n try { localStorage.setItem(ONBOARDING_KEY, '1'); } catch(e) {}\n });\n\n setTimeout(function() {\n if (bannerHost.parentNode) {\n var banner = bannerShadow.querySelector('.banner');\n if (banner) {\n banner.style.transition = 'opacity 0.3s ease';\n banner.style.opacity = '0';\n setTimeout(function() { bannerHost.remove(); }, 300);\n }\n }\n }, 8000);\n }\n\n showOnboarding();\n console.log('[ui-context-kit] Ready. Press ' + SHORTCUT + ' to activate.');\n})();\n `;\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { ElementContext } from './types';\n\nexport async function writeContext(\n context: ElementContext | ElementContext[],\n projectRoot: string,\n outputDir: string,\n): Promise<string> {\n const outPath = path.resolve(projectRoot, outputDir);\n const capturesDir = path.join(outPath, 'captures');\n\n // Ensure output directories exist\n fs.mkdirSync(outPath, { recursive: true });\n fs.mkdirSync(path.join(outPath, 'screenshots'), { recursive: true });\n fs.mkdirSync(capturesDir, { recursive: true });\n\n const contexts = Array.isArray(context) ? context : [context];\n\n // Save screenshots if available\n const screenshotPaths: (string | undefined)[] = [];\n for (const ctx of contexts) {\n if (ctx.screenshotDataUrl) {\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const filename = `capture-${timestamp}.png`;\n const relPath = `./screenshots/${filename}`;\n const base64 = ctx.screenshotDataUrl.replace(/^data:image\\/\\w+;base64,/, '');\n fs.writeFileSync(path.join(outPath, 'screenshots', filename), Buffer.from(base64, 'base64'));\n screenshotPaths.push(relPath);\n } else {\n screenshotPaths.push(undefined);\n }\n }\n\n // Read source code snippets\n const sourceSnippets: string[] = [];\n for (const ctx of contexts) {\n if (ctx.source) {\n sourceSnippets.push(readSourceSnippet(\n path.resolve(projectRoot, ctx.source.file),\n ctx.source.line,\n 10,\n ));\n } else {\n sourceSnippets.push('');\n }\n }\n\n // Build markdown\n const md = contexts.length === 1\n ? buildMarkdown(contexts[0], sourceSnippets[0], screenshotPaths[0])\n : buildMultiMarkdown(contexts, sourceSnippets, screenshotPaths);\n\n // Write latest.md\n const latestPath = path.join(outPath, 'latest.md');\n fs.writeFileSync(latestPath, md, 'utf-8');\n\n // Write timestamped capture file for history\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const capturePath = path.join(capturesDir, `${timestamp}.md`);\n fs.writeFileSync(capturePath, md, 'utf-8');\n\n // Update history.md (append summary, keep last 20 entries)\n updateHistory(outPath, contexts, timestamp);\n\n // Clean up old captures (keep last 50)\n cleanupOldCaptures(capturesDir, 50);\n\n console.log(`[ui-context-kit] Context written to ${path.relative(projectRoot, latestPath)}`);\n console.log(`[ui-context-kit] History saved to ${path.relative(projectRoot, capturePath)}`);\n\n return latestPath;\n}\n\nfunction updateHistory(outPath: string, contexts: ElementContext[], timestamp: string): void {\n const historyPath = path.join(outPath, 'history.md');\n\n // Build summary for this capture\n const lines: string[] = [];\n const time = timestamp.replace(/T/, ' ').replace(/-(\\d{2})-(\\d{2})-(\\d+)Z?$/, ':$1:$2');\n\n for (const ctx of contexts) {\n const component = ctx.source?.component || ctx.tagName;\n const file = ctx.source ? `${ctx.source.file}:${ctx.source.line}` : '';\n lines.push(`- **${component}** ${file ? `(\\`${file}\\`)` : ''} — ${ctx.url}`);\n }\n\n const entry = `### ${time}\\n${lines.join('\\n')}\\n\\n`;\n\n // Read existing history or create new\n let existing = '';\n try {\n existing = fs.readFileSync(historyPath, 'utf-8');\n } catch {\n existing = '# UI Context Capture History\\n\\n';\n }\n\n // Insert after the header line\n const headerEnd = existing.indexOf('\\n\\n');\n if (headerEnd !== -1) {\n const header = existing.slice(0, headerEnd + 2);\n const body = existing.slice(headerEnd + 2);\n existing = header + entry + body;\n } else {\n existing += entry;\n }\n\n // Keep only last 20 entries\n const entries = existing.split(/(?=### )/);\n const header = entries[0]; // everything before first ###\n const captureEntries = entries.slice(1);\n if (captureEntries.length > 20) {\n existing = header + captureEntries.slice(0, 20).join('');\n }\n\n fs.writeFileSync(historyPath, existing, 'utf-8');\n}\n\nfunction cleanupOldCaptures(capturesDir: string, maxFiles: number): void {\n try {\n const files = fs.readdirSync(capturesDir)\n .filter(f => f.endsWith('.md'))\n .sort()\n .reverse();\n\n for (let i = maxFiles; i < files.length; i++) {\n fs.unlinkSync(path.join(capturesDir, files[i]));\n }\n } catch {\n // ignore cleanup errors\n }\n}\n\nfunction readSourceSnippet(filePath: string, targetLine: number, contextLines: number): string {\n try {\n const content = fs.readFileSync(filePath, 'utf-8');\n const lines = content.split('\\n');\n const start = Math.max(0, targetLine - contextLines - 1);\n const end = Math.min(lines.length, targetLine + contextLines);\n\n return lines\n .slice(start, end)\n .map((line, i) => {\n const lineNum = start + i + 1;\n const marker = lineNum === targetLine ? ' // <-- target' : '';\n return `${line}${marker}`;\n })\n .join('\\n');\n } catch {\n return '// Source file not found';\n }\n}\n\nfunction buildMarkdown(\n context: ElementContext,\n sourceSnippet: string,\n screenshotPath?: string,\n): string {\n const { source, tagName, classes, computedStyles, dimensions, componentHierarchy, url } = context;\n\n const lines: string[] = ['# UI Context Capture', ''];\n\n // Target Element section\n lines.push('## Target Element');\n if (source) {\n if (source.component) {\n lines.push(`- **Component**: \\`${source.component}\\` in \\`${source.file}:${source.line}\\``);\n } else {\n lines.push(`- **File**: \\`${source.file}:${source.line}\\``);\n }\n }\n lines.push(`- **URL**: ${url}`);\n lines.push(`- **Tag**: \\`<${tagName}>\\``);\n lines.push('');\n\n // Source Code section\n if (source && sourceSnippet) {\n const startLine = Math.max(1, source.line - 10);\n const endLine = source.line + 10;\n lines.push('## Source Code');\n lines.push('```tsx');\n lines.push(`// ${source.file}:${startLine}-${endLine}`);\n lines.push(sourceSnippet);\n lines.push('```');\n lines.push('');\n }\n\n // Styling section\n lines.push('## Styling');\n if (classes) {\n lines.push(`- **Classes**: \\`${classes}\\``);\n }\n\n const styleEntries = Object.entries(computedStyles);\n if (styleEntries.length > 0) {\n lines.push(`- **Computed**: ${styleEntries.map(([k, v]) => `${camelToKebab(k)}: ${v}`).join(', ')}`);\n }\n\n lines.push(`- **Dimensions**: ${Math.round(dimensions.width)}x${Math.round(dimensions.height)}px at (${Math.round(dimensions.x)}, ${Math.round(dimensions.y)})`);\n lines.push('');\n\n // Component Hierarchy section\n if (componentHierarchy.length > 0) {\n lines.push('## Component Hierarchy');\n lines.push(componentHierarchy.join(' > '));\n lines.push('');\n }\n\n // Screenshot section\n if (screenshotPath) {\n lines.push('## Screenshot');\n lines.push(`![element](${screenshotPath})`);\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\nfunction buildMultiMarkdown(\n contexts: ElementContext[],\n sourceSnippets: string[],\n screenshotPaths: (string | undefined)[],\n): string {\n const lines: string[] = [\n `# UI Context Capture (${contexts.length} elements)`,\n '',\n ];\n\n for (let i = 0; i < contexts.length; i++) {\n const ctx = contexts[i];\n const snippet = sourceSnippets[i];\n const screenshot = screenshotPaths[i];\n\n lines.push(`---`);\n lines.push('');\n lines.push(`## Element ${i + 1}: \\`<${ctx.tagName}>\\`${ctx.source?.component ? ` (${ctx.source.component})` : ''}`);\n lines.push('');\n\n if (ctx.source) {\n if (ctx.source.component) {\n lines.push(`- **Component**: \\`${ctx.source.component}\\` in \\`${ctx.source.file}:${ctx.source.line}\\``);\n } else {\n lines.push(`- **File**: \\`${ctx.source.file}:${ctx.source.line}\\``);\n }\n }\n lines.push(`- **URL**: ${ctx.url}`);\n lines.push('');\n\n if (ctx.source && snippet) {\n const startLine = Math.max(1, ctx.source.line - 10);\n const endLine = ctx.source.line + 10;\n lines.push('### Source Code');\n lines.push('```tsx');\n lines.push(`// ${ctx.source.file}:${startLine}-${endLine}`);\n lines.push(snippet);\n lines.push('```');\n lines.push('');\n }\n\n lines.push('### Styling');\n if (ctx.classes) {\n lines.push(`- **Classes**: \\`${ctx.classes}\\``);\n }\n const styleEntries = Object.entries(ctx.computedStyles);\n if (styleEntries.length > 0) {\n lines.push(`- **Computed**: ${styleEntries.map(([k, v]) => `${camelToKebab(k)}: ${v}`).join(', ')}`);\n }\n lines.push(`- **Dimensions**: ${Math.round(ctx.dimensions.width)}x${Math.round(ctx.dimensions.height)}px at (${Math.round(ctx.dimensions.x)}, ${Math.round(ctx.dimensions.y)})`);\n lines.push('');\n\n if (ctx.componentHierarchy.length > 0) {\n lines.push('### Component Hierarchy');\n lines.push(ctx.componentHierarchy.join(' > '));\n lines.push('');\n }\n\n if (screenshot) {\n lines.push('### Screenshot');\n lines.push(`![element ${i + 1}](${screenshot})`);\n lines.push('');\n }\n }\n\n return lines.join('\\n');\n}\n\nfunction camelToKebab(str: string): string {\n return str.replace(/[A-Z]/g, m => '-' + m.toLowerCase());\n}\n","import { exec } from 'child_process';\nimport { platform } from 'os';\n\nexport function copyToClipboard(text: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const os = platform();\n let cmd: string;\n\n if (os === 'darwin') {\n cmd = 'pbcopy';\n } else if (os === 'linux') {\n cmd = 'xclip -selection clipboard';\n } else if (os === 'win32') {\n cmd = 'clip';\n } else {\n reject(new Error(`Unsupported platform: ${os}`));\n return;\n }\n\n const proc = exec(cmd, (err) => {\n if (err) reject(err);\n else resolve();\n });\n\n proc.stdin?.write(text);\n proc.stdin?.end();\n });\n}\n","import type { ViteDevServer } from 'vite';\nimport { writeContext } from './context-writer';\nimport { copyToClipboard } from './clipboard';\nimport type { ElementContext, UIContextKitOptions } from './types';\n\nexport function setupWebSocket(server: ViteDevServer, options: UIContextKitOptions): void {\n const root = server.config.root;\n const outputDir = options.outputDir || '.ui-context';\n const shouldCopy = options.clipboard !== false;\n\n server.ws.on('ui-context:capture', async (data: ElementContext | ElementContext[], client) => {\n try {\n const count = Array.isArray(data) ? data.length : 1;\n console.log(`[ui-context-kit] Received context capture (${count} element${count > 1 ? 's' : ''})`);\n\n const filePath = await writeContext(data, root, outputDir);\n\n if (shouldCopy) {\n try {\n const fs = await import('fs');\n const content = fs.readFileSync(filePath, 'utf-8');\n await copyToClipboard(content);\n console.log('[ui-context-kit] Context copied to clipboard');\n } catch (e) {\n console.warn('[ui-context-kit] Could not copy to clipboard:', e);\n }\n }\n\n client.send('ui-context:capture-result', { success: true });\n } catch (err: any) {\n console.error('[ui-context-kit] Error writing context:', err);\n client.send('ui-context:capture-result', { success: false, error: err.message });\n }\n });\n}\n","import type { UIContextKitOptions } from './types';\n\n/**\n * Wraps a Next.js config to add ui-context-kit babel plugin in development.\n *\n * Usage:\n * ```js\n * // next.config.js\n * const { withUIContext } = require('@ui-context-kit/bridge');\n * module.exports = withUIContext(nextConfig);\n * ```\n */\nexport function withUIContext(nextConfig: any = {}, _options?: UIContextKitOptions) {\n if (process.env.NODE_ENV !== 'development') return nextConfig;\n\n return {\n ...nextConfig,\n webpack(config: any, context: any) {\n // Add babel-loader with our plugin for JSX/TSX files\n // Note: This is a simplified approach. For production use,\n // users should configure babel.config.js directly.\n\n if (typeof nextConfig.webpack === 'function') {\n config = nextConfig.webpack(config, context);\n }\n\n return config;\n },\n };\n}\n","import { createVitePlugin } from './vite-plugin';\nimport { writeContext } from './context-writer';\nimport { withUIContext } from './next-wrapper';\nimport type { UIContextKitOptions } from './types';\n\n/**\n * Vite plugin for UI Context Kit.\n * Enables browser-based element selection and context capture for AI coding assistants.\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { uiContextKit } from '@ui-context-kit/bridge'\n * export default defineConfig({\n * plugins: [react(), uiContextKit()]\n * })\n * ```\n */\nexport function uiContextKit(options?: UIContextKitOptions) {\n return createVitePlugin(options);\n}\n\nexport { writeContext, withUIContext };\nexport type { UIContextKitOptions, ElementContext, SourceLocation } from './types';\n"],"mappings":"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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;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;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;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;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;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;AAmf5B;;;AI1kBO,SAAS,cAAc,aAAkB,CAAC,GAAG,UAAgC;AAClF,MAAI,QAAQ,IAAI,aAAa,cAAe,QAAO;AAEnD,SAAO;AAAA,IACL,GAAG;AAAA,IACH,QAAQ,QAAa,SAAc;AAKjC,UAAI,OAAO,WAAW,YAAY,YAAY;AAC5C,iBAAS,WAAW,QAAQ,QAAQ,OAAO;AAAA,MAC7C;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;ACXO,SAAS,aAAa,SAA+B;AAC1D,SAAO,iBAAiB,OAAO;AACjC;","names":["path","fs","timestamp","header","fs","path","fs"]}
1
+ {"version":3,"sources":["../src/vite-plugin.ts","../src/context-writer.ts","../src/clipboard.ts","../src/ws-server.ts","../src/next-wrapper.ts","../src/next-server.ts","../src/index.ts"],"sourcesContent":["import type { Plugin } from 'vite';\nimport path from 'path';\nimport fs from 'fs';\nimport { injectSourceAttributes } from '@ui-context-kit/babel-plugin';\nimport { setupWebSocket } from './ws-server';\nimport type { UIContextKitOptions } from './types';\n\nconst JSX_EXTENSIONS = /\\.(jsx|tsx)$/;\nconst VIRTUAL_MODULE_ID = 'virtual:ui-context-overlay';\nconst RESOLVED_VIRTUAL_MODULE_ID = '\\0' + VIRTUAL_MODULE_ID;\n\nexport function createVitePlugin(options: UIContextKitOptions = {}): Plugin[] {\n const {\n shortcut = 'alt+x',\n include,\n exclude = ['node_modules'],\n } = options;\n\n let projectRoot = '';\n\n const transformPlugin: Plugin = {\n name: 'ui-context-kit:transform',\n enforce: 'pre',\n apply: 'serve',\n\n configResolved(config) {\n projectRoot = config.root;\n },\n\n transform(code, id) {\n if (!JSX_EXTENSIONS.test(id)) return null;\n\n const relativePath = path.relative(projectRoot, id);\n if (exclude?.some(p => relativePath.includes(p))) return null;\n if (include && !include.some(p => relativePath.includes(p))) return null;\n if (id.includes('\\0') || id.includes('node_modules')) return null;\n\n const filePath = path.relative(projectRoot, id);\n\n let originalCode: string | undefined;\n try {\n originalCode = fs.readFileSync(id, 'utf-8');\n } catch {\n // ignore read errors\n }\n\n const result = injectSourceAttributes(code, filePath, originalCode);\n if (!result) return null;\n\n return { code: result.code, map: result.map };\n },\n };\n\n const overlayPlugin: Plugin = {\n name: 'ui-context-kit:overlay',\n apply: 'serve',\n\n resolveId(id) {\n if (id === VIRTUAL_MODULE_ID) return RESOLVED_VIRTUAL_MODULE_ID;\n },\n\n load(id) {\n if (id === RESOLVED_VIRTUAL_MODULE_ID) {\n return getOverlayCode(shortcut);\n }\n },\n\n configureServer(server) {\n setupWebSocket(server, options);\n },\n\n transformIndexHtml() {\n return [\n {\n tag: 'script',\n attrs: { type: 'module', src: `/@id/${VIRTUAL_MODULE_ID}` },\n injectTo: 'body' as const,\n },\n ];\n },\n };\n\n return [transformPlugin, overlayPlugin];\n}\n\nfunction getOverlayCode(shortcut: string): string {\n return `\n// UI Context Kit - Overlay (auto-injected in dev mode)\n(function() {\n if (typeof window === 'undefined') return;\n\n var isActive = false;\n var highlightEl = null;\n var toolbarEl = null;\n var selectedEl = null;\n var isFrozen = false;\n var frozenObservers = [];\n var multiSelected = new Set();\n\n var SHORTCUT = '${shortcut}';\n var ONBOARDING_KEY = 'ui-context-kit-onboarding-dismissed';\n\n // ---- Shadow DOM Overlay ----\n function createOverlay() {\n var host = document.createElement('div');\n host.id = 'ui-context-host';\n host.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;pointer-events:none;';\n document.body.appendChild(host);\n\n var shadow = host.attachShadow({ mode: 'open' });\n shadow.innerHTML = [\n '<style>',\n '.highlight { position:fixed; border:2px solid #3b82f6; background:rgba(59,130,246,0.08); pointer-events:none; transition:all 0.15s ease; border-radius:3px; display:none; }',\n '.highlight-label { position:absolute; top:-22px; left:-2px; background:#3b82f6; color:white; font-size:11px; font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif; padding:2px 8px; border-radius:3px 3px 0 0; white-space:nowrap; }',\n '.toolbar { position:fixed; bottom:20px; left:50%; transform:translateX(-50%); background:#0f172a; border:1px solid #334155; border-radius:12px; padding:8px 12px; display:flex; gap:6px; align-items:center; font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif; box-shadow:0 8px 32px rgba(0,0,0,0.5); pointer-events:auto; }',\n '.toolbar-label { color:#94a3b8; font-size:12px; padding:0 4px; }',\n '.toolbar-btn { color:white; border:none; padding:6px 14px; border-radius:6px; font-size:12px; font-weight:500; cursor:pointer; white-space:nowrap; }',\n '.toolbar-btn:hover { filter:brightness(1.15); }',\n '.toolbar-btn.primary { background:#3b82f6; }',\n '.toolbar-btn.secondary { background:#475569; }',\n '.toolbar-btn.freeze { background:#475569; }',\n '.toolbar-btn.freeze.active { background:#f59e0b; color:#1e293b; }',\n '.badge { display:inline-block; background:#f59e0b; color:#1e293b; font-size:10px; font-weight:700; padding:1px 5px; border-radius:10px; margin-left:4px; }',\n '.divider { width:1px; height:20px; background:#334155; }',\n '.toast { position:fixed; bottom:72px; left:50%; transform:translateX(-50%); background:#0f172a; color:#e2e8f0; padding:10px 20px; border-radius:8px; font-size:13px; font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif; box-shadow:0 4px 16px rgba(0,0,0,0.4); pointer-events:none; animation:toastIn 0.2s ease; }',\n '@keyframes toastIn { from { opacity:0; transform:translateX(-50%) translateY(8px); } }',\n '.banner { position:fixed; bottom:20px; left:50%; transform:translateX(-50%); background:linear-gradient(135deg,#0f172a 0%,#1e293b 100%); border:1px solid #334155; border-radius:12px; padding:12px 20px; display:flex; gap:12px; align-items:center; font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif; box-shadow:0 8px 32px rgba(0,0,0,0.4); animation:bannerIn 0.4s ease; max-width:480px; pointer-events:auto; }',\n '@keyframes bannerIn { from { opacity:0; transform:translateX(-50%) translateY(20px); } to { opacity:1; transform:translateX(-50%) translateY(0); } }',\n '.banner-text { color:#e2e8f0; font-size:13px; line-height:1.4; }',\n '.banner-text strong { color:#60a5fa; }',\n '.kbd { display:inline-block; background:#334155; color:#e2e8f0; padding:1px 6px; border-radius:4px; font-size:12px; font-family:monospace; border:1px solid #475569; }',\n '.banner-close { background:none; border:none; color:#64748b; cursor:pointer; padding:4px; font-size:16px; flex-shrink:0; }',\n '.banner-close:hover { color:#94a3b8; }',\n '</style>',\n '<div class=\"highlight\"><div class=\"highlight-label\"></div></div>',\n '<div class=\"toolbar\" style=\"display:none\">',\n ' <span class=\"toolbar-label\">UI Context</span>',\n ' <div class=\"divider\"></div>',\n ' <button class=\"toolbar-btn primary\" id=\"capture-btn\">Capture</button>',\n ' <button class=\"toolbar-btn primary\" id=\"capture-all-btn\" style=\"display:none\">Capture All <span class=\"badge\" id=\"multi-badge\" style=\"display:none\">0</span></button>',\n ' <div class=\"divider\"></div>',\n ' <button class=\"toolbar-btn freeze\" id=\"freeze-btn\" title=\"Freeze DOM (Ctrl+Shift+F)\">Freeze</button>',\n ' <button class=\"toolbar-btn secondary\" id=\"close-btn\">\\\\u2715</button>',\n '</div>',\n ].join('\\\\n');\n\n highlightEl = shadow.querySelector('.highlight');\n toolbarEl = shadow.querySelector('.toolbar');\n\n shadow.getElementById('close-btn').addEventListener('click', deactivate);\n shadow.getElementById('capture-btn').addEventListener('click', function() {\n if (selectedEl) captureAndSend(selectedEl);\n });\n shadow.getElementById('capture-all-btn').addEventListener('click', captureAllSelected);\n shadow.getElementById('freeze-btn').addEventListener('click', toggleFreeze);\n\n return { host: host, shadow: shadow };\n }\n\n var overlayRef = null;\n\n function showHighlight(el) {\n if (!highlightEl || !el) { highlightEl && (highlightEl.style.display = 'none'); return; }\n var rect = el.getBoundingClientRect();\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\n var label = highlightEl.querySelector('.highlight-label');\n var src = el.getAttribute('data-source-file');\n var line = el.getAttribute('data-source-line');\n var comp = el.getAttribute('data-source-component');\n label.textContent = src\n ? (comp || el.tagName.toLowerCase()) + ' \\\\u00b7 ' + src + ':' + line\n : el.tagName.toLowerCase();\n }\n\n function showToast(msg, duration) {\n if (!overlayRef) return;\n duration = duration || 3000;\n var t = document.createElement('div');\n t.className = 'toast';\n t.textContent = msg;\n overlayRef.shadow.appendChild(t);\n setTimeout(function() { t.remove(); }, duration);\n }\n\n // ---- React Fiber Hierarchy ----\n function getComponentHierarchy(el) {\n var fiberKey = Object.keys(el).find(function(k) {\n return k.startsWith('__reactFiber$') || k.startsWith('__reactInternalInstance$');\n });\n if (!fiberKey) return [];\n var hierarchy = [];\n var fiber = el[fiberKey];\n while (fiber) {\n if (typeof fiber.type === 'function') {\n var name = fiber.type.displayName || fiber.type.name;\n if (name && !name.startsWith('_') && name !== 'Fragment') hierarchy.unshift(name);\n } else if (typeof fiber.type === 'object' && fiber.type) {\n var name = fiber.type.displayName || (fiber.type.render && (fiber.type.render.displayName || fiber.type.render.name));\n if (name && !name.startsWith('_') && name !== 'Fragment') hierarchy.unshift(name);\n }\n fiber = fiber.return;\n }\n return hierarchy;\n }\n\n // ---- Computed Styles ----\n var STYLE_PROPS = [\n 'padding','padding-top','padding-right','padding-bottom','padding-left',\n 'margin','margin-top','margin-right','margin-bottom','margin-left',\n 'background-color','color','font-size','font-weight','font-family',\n 'border-radius','display','flex-direction','justify-content','align-items',\n 'gap','width','height','overflow','position','z-index','opacity',\n 'border','box-shadow','line-height','letter-spacing','text-align'\n ];\n\n function extractContext(el) {\n var computed = getComputedStyle(el);\n var rect = el.getBoundingClientRect();\n var styles = {};\n for (var i = 0; i < STYLE_PROPS.length; i++) {\n var p = STYLE_PROPS[i];\n var v = computed.getPropertyValue(p);\n if (v && v !== 'none' && v !== 'normal' && v !== 'auto' && v !== '0px' && v !== 'rgba(0, 0, 0, 0)') {\n styles[p] = v;\n }\n }\n\n var file = el.getAttribute('data-source-file');\n var line = el.getAttribute('data-source-line');\n var col = el.getAttribute('data-source-col');\n var component = el.getAttribute('data-source-component');\n\n return {\n source: file ? { file: file, line: parseInt(line||'0'), col: parseInt(col||'0'), component: component || undefined } : null,\n tagName: el.tagName.toLowerCase(),\n classes: el.className || '',\n computedStyles: styles,\n dimensions: { width: rect.width, height: rect.height, x: rect.x, y: rect.y },\n componentHierarchy: getComponentHierarchy(el),\n url: location.href\n };\n }\n\n // ---- Screenshot ----\n function captureScreenshot(el) {\n return new Promise(function(resolve) {\n try {\n var rect = el.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) { resolve(undefined); return; }\n\n var canvas = document.createElement('canvas');\n var dpr = window.devicePixelRatio || 1;\n var pad = 8;\n var w = Math.ceil(rect.width + pad * 2);\n var h = Math.ceil(rect.height + pad * 2);\n canvas.width = w * dpr;\n canvas.height = h * dpr;\n\n var ctx = canvas.getContext('2d');\n if (!ctx) { resolve(undefined); return; }\n ctx.scale(dpr, dpr);\n\n // Try SVG foreignObject approach\n var clone = el.cloneNode(true);\n copyStyles(el, clone);\n\n var svgNs = 'http://www.w3.org/2000/svg';\n var svg = document.createElementNS(svgNs, 'svg');\n svg.setAttribute('width', String(w));\n svg.setAttribute('height', String(h));\n svg.setAttribute('xmlns', svgNs);\n\n var fo = document.createElementNS(svgNs, 'foreignObject');\n fo.setAttribute('width', '100%');\n fo.setAttribute('height', '100%');\n\n var container = document.createElement('div');\n container.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml');\n container.style.cssText = 'width:' + w + 'px;height:' + h + 'px;display:flex;align-items:center;justify-content:center;background:white;padding:' + pad + 'px;box-sizing:border-box;';\n container.appendChild(clone);\n fo.appendChild(container);\n svg.appendChild(fo);\n\n var svgStr = new XMLSerializer().serializeToString(svg);\n var blob = new Blob([svgStr], { type: 'image/svg+xml;charset=utf-8' });\n var url = URL.createObjectURL(blob);\n\n var img = new Image();\n img.onload = function() {\n ctx.drawImage(img, 0, 0);\n URL.revokeObjectURL(url);\n try { resolve(canvas.toDataURL('image/png')); } catch(e) { resolve(undefined); }\n };\n img.onerror = function() {\n URL.revokeObjectURL(url);\n // Fallback: placeholder\n ctx.fillStyle = '#f8fafc';\n ctx.fillRect(0, 0, w, h);\n ctx.strokeStyle = '#3b82f6';\n ctx.lineWidth = 2;\n ctx.strokeRect(pad, pad, rect.width, rect.height);\n ctx.fillStyle = '#64748b';\n ctx.font = '11px -apple-system, BlinkMacSystemFont, sans-serif';\n ctx.fillText(Math.round(rect.width) + ' x ' + Math.round(rect.height) + 'px', pad + 4, pad + rect.height / 2 + 4);\n try { resolve(canvas.toDataURL('image/png')); } catch(e) { resolve(undefined); }\n };\n img.src = url;\n } catch(e) {\n resolve(undefined);\n }\n });\n }\n\n function copyStyles(src, tgt) {\n var cs = getComputedStyle(src);\n var props = ['display','width','height','padding','margin','border','border-radius','background','background-color','color','font-size','font-weight','font-family','line-height','text-align','box-shadow','opacity','flex-direction','justify-content','align-items','gap','overflow'];\n for (var i = 0; i < props.length; i++) {\n tgt.style.setProperty(props[i], cs.getPropertyValue(props[i]));\n }\n var sc = src.children, tc = tgt.children;\n for (var j = 0; j < sc.length && j < tc.length; j++) {\n if (sc[j] instanceof HTMLElement && tc[j] instanceof HTMLElement) copyStyles(sc[j], tc[j]);\n }\n }\n\n // ---- Capture & Send ----\n function captureAndSend(el) {\n showToast('Capturing context...');\n var ctx = extractContext(el);\n\n captureScreenshot(el).then(function(screenshot) {\n if (screenshot) ctx.screenshotDataUrl = screenshot;\n\n if (import.meta.hot) {\n import.meta.hot.send('ui-context:capture', ctx);\n import.meta.hot.on('ui-context:capture-result', function(result) {\n if (result.success) {\n showToast('Context captured! Check .ui-context/latest.md');\n } else {\n showToast('Capture failed: ' + (result.error || 'unknown error'));\n }\n });\n }\n });\n }\n\n function captureAllSelected() {\n if (multiSelected.size === 0) {\n showToast('No elements selected. Use Shift+Click to select multiple.');\n return;\n }\n showToast('Capturing ' + multiSelected.size + ' elements...');\n\n var elements = Array.from(multiSelected);\n var contexts = [];\n var pending = elements.length;\n\n elements.forEach(function(el) {\n var ctx = extractContext(el);\n captureScreenshot(el).then(function(screenshot) {\n if (screenshot) ctx.screenshotDataUrl = screenshot;\n contexts.push(ctx);\n pending--;\n if (pending === 0) {\n if (import.meta.hot) {\n import.meta.hot.send('ui-context:capture', contexts);\n import.meta.hot.on('ui-context:capture-result', function(result) {\n if (result.success) {\n showToast(contexts.length + ' elements captured!');\n clearMultiSelection();\n } else {\n showToast('Capture failed: ' + (result.error || 'unknown error'));\n }\n });\n }\n }\n });\n });\n }\n\n function updateMultiBadge() {\n if (!overlayRef) return;\n var btn = overlayRef.shadow.getElementById('capture-all-btn');\n var badge = overlayRef.shadow.getElementById('multi-badge');\n if (multiSelected.size > 0) {\n btn.style.display = '';\n badge.style.display = '';\n badge.textContent = String(multiSelected.size);\n } else {\n btn.style.display = 'none';\n badge.style.display = 'none';\n }\n }\n\n function clearMultiSelection() {\n multiSelected.forEach(function(el) { el.style.outline = ''; });\n multiSelected.clear();\n updateMultiBadge();\n }\n\n // ---- Freeze Mode ----\n function toggleFreeze() {\n if (isFrozen) {\n unfreezeDOM();\n showToast('DOM unfrozen');\n } else {\n freezeDOM();\n showToast('DOM frozen — hover states preserved');\n }\n var btn = overlayRef && overlayRef.shadow.getElementById('freeze-btn');\n if (btn) {\n if (isFrozen) {\n btn.classList.add('active');\n btn.textContent = 'Frozen';\n } else {\n btn.classList.remove('active');\n btn.textContent = 'Freeze';\n }\n }\n }\n\n function freezeDOM() {\n isFrozen = true;\n var observer = new MutationObserver(function(mutations) {\n for (var i = 0; i < mutations.length; i++) {\n var m = mutations[i];\n for (var j = 0; j < m.addedNodes.length; j++) {\n var node = m.addedNodes[j];\n if (node instanceof HTMLElement && !(node.id && node.id.indexOf('ui-context') !== -1)) {\n node.remove();\n }\n }\n if (m.type === 'attributes' && m.target instanceof HTMLElement) {\n if (!(m.target.id && m.target.id.indexOf('ui-context') !== -1)) {\n var old = m.oldValue;\n if (old !== null && m.attributeName) {\n m.target.setAttribute(m.attributeName, old);\n }\n }\n }\n }\n });\n observer.observe(document.body, {\n childList: true, subtree: true, attributes: true, attributeOldValue: true\n });\n frozenObservers.push(observer);\n }\n\n function unfreezeDOM() {\n isFrozen = false;\n frozenObservers.forEach(function(obs) { obs.disconnect(); });\n frozenObservers = [];\n }\n\n // ---- Event Handlers ----\n function isOverlayEl(t) {\n return t.id === 'ui-context-host' || (t.closest && t.closest('#ui-context-host'));\n }\n\n function onMouseMove(e) {\n if (!isActive) return;\n var t = e.target;\n if (isOverlayEl(t)) return;\n showHighlight(t);\n }\n\n function onClick(e) {\n if (!isActive) return;\n var t = e.target;\n if (isOverlayEl(t)) return;\n e.preventDefault();\n e.stopPropagation();\n\n // Shift+Click: multi-select\n if (e.shiftKey) {\n if (multiSelected.has(t)) {\n multiSelected.delete(t);\n t.style.outline = '';\n } else {\n multiSelected.add(t);\n t.style.outline = '2px dashed #f59e0b';\n }\n updateMultiBadge();\n return;\n }\n\n selectedEl = t;\n captureAndSend(t);\n }\n\n // ---- Activate / Deactivate ----\n function activate() {\n if (isActive) return;\n isActive = true;\n overlayRef = createOverlay();\n toolbarEl.style.display = 'flex';\n document.addEventListener('mousemove', onMouseMove, true);\n document.addEventListener('click', onClick, true);\n document.body.style.cursor = 'crosshair';\n showToast('Click to capture, Shift+click for multi-select', 2000);\n }\n\n function deactivate() {\n if (!isActive) return;\n isActive = false;\n selectedEl = null;\n if (isFrozen) unfreezeDOM();\n clearMultiSelection();\n document.removeEventListener('mousemove', onMouseMove, true);\n document.removeEventListener('click', onClick, true);\n document.body.style.cursor = '';\n if (overlayRef) {\n overlayRef.host.remove();\n overlayRef = null;\n highlightEl = null;\n toolbarEl = null;\n }\n }\n\n // ---- Keyboard Shortcuts ----\n document.addEventListener('keydown', function(e) {\n var keys = SHORTCUT.split('+');\n var needsAlt = keys.indexOf('alt') !== -1;\n var needsCtrl = keys.indexOf('ctrl') !== -1;\n var needsShift = keys.indexOf('shift') !== -1;\n var mainKey = keys[keys.length - 1].toLowerCase();\n var mainCode = /^[a-z]$/.test(mainKey) ? 'Key' + mainKey.toUpperCase() : /^[0-9]$/.test(mainKey) ? 'Digit' + mainKey : '';\n\n if (e.altKey === needsAlt && e.ctrlKey === needsCtrl && e.shiftKey === needsShift && (mainCode ? e.code === mainCode : e.key.toLowerCase() === mainKey)) {\n e.preventDefault();\n isActive ? deactivate() : activate();\n return;\n }\n\n // Freeze: Ctrl+Shift+F (only when active)\n if (isActive && e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'f') {\n e.preventDefault();\n toggleFreeze();\n }\n });\n\n // ---- Onboarding Banner ----\n function showOnboarding() {\n try { if (localStorage.getItem(ONBOARDING_KEY)) return; } catch(e) { return; }\n\n // Wait for overlay ref to be set up\n var bannerHost = document.createElement('div');\n bannerHost.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;z-index:2147483646;pointer-events:none;';\n document.body.appendChild(bannerHost);\n var bannerShadow = bannerHost.attachShadow({ mode: 'open' });\n\n var shortcutDisplay = SHORTCUT.split('+').map(function(k) { return k.charAt(0).toUpperCase() + k.slice(1); }).join(' + ');\n\n bannerShadow.innerHTML = [\n '<style>',\n '.banner { position:fixed; bottom:20px; left:50%; transform:translateX(-50%); background:linear-gradient(135deg,#0f172a 0%,#1e293b 100%); border:1px solid #334155; border-radius:12px; padding:12px 20px; display:flex; gap:12px; align-items:center; font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif; box-shadow:0 8px 32px rgba(0,0,0,0.4); animation:bannerIn 0.4s ease; max-width:480px; pointer-events:auto; }',\n '@keyframes bannerIn { from { opacity:0; transform:translateX(-50%) translateY(20px); } to { opacity:1; transform:translateX(-50%) translateY(0); } }',\n '.text { color:#e2e8f0; font-size:13px; line-height:1.4; }',\n '.text strong { color:#60a5fa; }',\n '.kbd { display:inline-block; background:#334155; color:#e2e8f0; padding:1px 6px; border-radius:4px; font-size:12px; font-family:monospace; border:1px solid #475569; }',\n '.close { background:none; border:none; color:#64748b; cursor:pointer; padding:4px; font-size:16px; flex-shrink:0; }',\n '.close:hover { color:#94a3b8; }',\n '</style>',\n '<div class=\"banner\">',\n ' <span style=\"font-size:20px\">\\\\u{1F3AF}</span>',\n ' <span class=\"text\">',\n ' <strong>UI Context Kit</strong> is ready! Press <kbd class=\"kbd\">' + shortcutDisplay + '</kbd> to capture any UI element for AI.',\n ' <strong>Shift+Click</strong> for multi-select, <strong>Ctrl+Shift+F</strong> to freeze state.',\n ' </span>',\n ' <button class=\"close\" title=\"Dismiss\">\\\\u2715</button>',\n '</div>',\n ].join('\\\\n');\n\n bannerShadow.querySelector('.close').addEventListener('click', function() {\n bannerHost.remove();\n try { localStorage.setItem(ONBOARDING_KEY, '1'); } catch(e) {}\n });\n\n setTimeout(function() {\n if (bannerHost.parentNode) {\n var banner = bannerShadow.querySelector('.banner');\n if (banner) {\n banner.style.transition = 'opacity 0.3s ease';\n banner.style.opacity = '0';\n setTimeout(function() { bannerHost.remove(); }, 300);\n }\n }\n }, 8000);\n }\n\n showOnboarding();\n console.log('[ui-context-kit] Ready. Press ' + SHORTCUT + ' to activate.');\n})();\n `;\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { ElementContext } from './types';\n\nexport async function writeContext(\n context: ElementContext | ElementContext[],\n projectRoot: string,\n outputDir: string,\n): Promise<string> {\n const outPath = path.resolve(projectRoot, outputDir);\n const capturesDir = path.join(outPath, 'captures');\n\n // Ensure output directories exist\n fs.mkdirSync(outPath, { recursive: true });\n fs.mkdirSync(path.join(outPath, 'screenshots'), { recursive: true });\n fs.mkdirSync(capturesDir, { recursive: true });\n\n const contexts = Array.isArray(context) ? context : [context];\n\n // Save screenshots if available\n const screenshotPaths: (string | undefined)[] = [];\n for (const ctx of contexts) {\n if (ctx.screenshotDataUrl) {\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const filename = `capture-${timestamp}.png`;\n const relPath = `./screenshots/${filename}`;\n const base64 = ctx.screenshotDataUrl.replace(/^data:image\\/\\w+;base64,/, '');\n fs.writeFileSync(path.join(outPath, 'screenshots', filename), Buffer.from(base64, 'base64'));\n screenshotPaths.push(relPath);\n } else {\n screenshotPaths.push(undefined);\n }\n }\n\n // Read source code snippets\n const sourceSnippets: string[] = [];\n for (const ctx of contexts) {\n if (ctx.source) {\n sourceSnippets.push(readSourceSnippet(\n path.resolve(projectRoot, ctx.source.file),\n ctx.source.line,\n 10,\n ));\n } else {\n sourceSnippets.push('');\n }\n }\n\n // Build markdown\n const md = contexts.length === 1\n ? buildMarkdown(contexts[0], sourceSnippets[0], screenshotPaths[0])\n : buildMultiMarkdown(contexts, sourceSnippets, screenshotPaths);\n\n // Write latest.md\n const latestPath = path.join(outPath, 'latest.md');\n fs.writeFileSync(latestPath, md, 'utf-8');\n\n // Write timestamped capture file for history\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const capturePath = path.join(capturesDir, `${timestamp}.md`);\n fs.writeFileSync(capturePath, md, 'utf-8');\n\n // Update history.md (append summary, keep last 20 entries)\n updateHistory(outPath, contexts, timestamp);\n\n // Clean up old captures (keep last 50)\n cleanupOldCaptures(capturesDir, 50);\n\n console.log(`[ui-context-kit] Context written to ${path.relative(projectRoot, latestPath)}`);\n console.log(`[ui-context-kit] History saved to ${path.relative(projectRoot, capturePath)}`);\n\n return latestPath;\n}\n\nfunction updateHistory(outPath: string, contexts: ElementContext[], timestamp: string): void {\n const historyPath = path.join(outPath, 'history.md');\n\n // Build summary for this capture\n const lines: string[] = [];\n const time = timestamp.replace(/T/, ' ').replace(/-(\\d{2})-(\\d{2})-(\\d+)Z?$/, ':$1:$2');\n\n for (const ctx of contexts) {\n const component = ctx.source?.component || ctx.tagName;\n const file = ctx.source ? `${ctx.source.file}:${ctx.source.line}` : '';\n lines.push(`- **${component}** ${file ? `(\\`${file}\\`)` : ''} — ${ctx.url}`);\n }\n\n const entry = `### ${time}\\n${lines.join('\\n')}\\n\\n`;\n\n // Read existing history or create new\n let existing = '';\n try {\n existing = fs.readFileSync(historyPath, 'utf-8');\n } catch {\n existing = '# UI Context Capture History\\n\\n';\n }\n\n // Insert after the header line\n const headerEnd = existing.indexOf('\\n\\n');\n if (headerEnd !== -1) {\n const header = existing.slice(0, headerEnd + 2);\n const body = existing.slice(headerEnd + 2);\n existing = header + entry + body;\n } else {\n existing += entry;\n }\n\n // Keep only last 20 entries\n const entries = existing.split(/(?=### )/);\n const header = entries[0]; // everything before first ###\n const captureEntries = entries.slice(1);\n if (captureEntries.length > 20) {\n existing = header + captureEntries.slice(0, 20).join('');\n }\n\n fs.writeFileSync(historyPath, existing, 'utf-8');\n}\n\nfunction cleanupOldCaptures(capturesDir: string, maxFiles: number): void {\n try {\n const files = fs.readdirSync(capturesDir)\n .filter(f => f.endsWith('.md'))\n .sort()\n .reverse();\n\n for (let i = maxFiles; i < files.length; i++) {\n fs.unlinkSync(path.join(capturesDir, files[i]));\n }\n } catch {\n // ignore cleanup errors\n }\n}\n\nfunction readSourceSnippet(filePath: string, targetLine: number, contextLines: number): string {\n try {\n const content = fs.readFileSync(filePath, 'utf-8');\n const lines = content.split('\\n');\n const start = Math.max(0, targetLine - contextLines - 1);\n const end = Math.min(lines.length, targetLine + contextLines);\n\n return lines\n .slice(start, end)\n .map((line, i) => {\n const lineNum = start + i + 1;\n const marker = lineNum === targetLine ? ' // <-- target' : '';\n return `${line}${marker}`;\n })\n .join('\\n');\n } catch {\n return '// Source file not found';\n }\n}\n\nfunction buildMarkdown(\n context: ElementContext,\n sourceSnippet: string,\n screenshotPath?: string,\n): string {\n const { source, tagName, classes, computedStyles, dimensions, componentHierarchy, url } = context;\n\n const lines: string[] = ['# UI Context Capture', ''];\n\n // Target Element section\n lines.push('## Target Element');\n if (source) {\n if (source.component) {\n lines.push(`- **Component**: \\`${source.component}\\` in \\`${source.file}:${source.line}\\``);\n } else {\n lines.push(`- **File**: \\`${source.file}:${source.line}\\``);\n }\n }\n lines.push(`- **URL**: ${url}`);\n lines.push(`- **Tag**: \\`<${tagName}>\\``);\n lines.push('');\n\n // Source Code section\n if (source && sourceSnippet) {\n const startLine = Math.max(1, source.line - 10);\n const endLine = source.line + 10;\n lines.push('## Source Code');\n lines.push('```tsx');\n lines.push(`// ${source.file}:${startLine}-${endLine}`);\n lines.push(sourceSnippet);\n lines.push('```');\n lines.push('');\n }\n\n // Styling section\n lines.push('## Styling');\n if (classes) {\n lines.push(`- **Classes**: \\`${classes}\\``);\n }\n\n const styleEntries = Object.entries(computedStyles);\n if (styleEntries.length > 0) {\n lines.push(`- **Computed**: ${styleEntries.map(([k, v]) => `${camelToKebab(k)}: ${v}`).join(', ')}`);\n }\n\n lines.push(`- **Dimensions**: ${Math.round(dimensions.width)}x${Math.round(dimensions.height)}px at (${Math.round(dimensions.x)}, ${Math.round(dimensions.y)})`);\n lines.push('');\n\n // Component Hierarchy section\n if (componentHierarchy.length > 0) {\n lines.push('## Component Hierarchy');\n lines.push(componentHierarchy.join(' > '));\n lines.push('');\n }\n\n // Screenshot section\n if (screenshotPath) {\n lines.push('## Screenshot');\n lines.push(`![element](${screenshotPath})`);\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\nfunction buildMultiMarkdown(\n contexts: ElementContext[],\n sourceSnippets: string[],\n screenshotPaths: (string | undefined)[],\n): string {\n const lines: string[] = [\n `# UI Context Capture (${contexts.length} elements)`,\n '',\n ];\n\n for (let i = 0; i < contexts.length; i++) {\n const ctx = contexts[i];\n const snippet = sourceSnippets[i];\n const screenshot = screenshotPaths[i];\n\n lines.push(`---`);\n lines.push('');\n lines.push(`## Element ${i + 1}: \\`<${ctx.tagName}>\\`${ctx.source?.component ? ` (${ctx.source.component})` : ''}`);\n lines.push('');\n\n if (ctx.source) {\n if (ctx.source.component) {\n lines.push(`- **Component**: \\`${ctx.source.component}\\` in \\`${ctx.source.file}:${ctx.source.line}\\``);\n } else {\n lines.push(`- **File**: \\`${ctx.source.file}:${ctx.source.line}\\``);\n }\n }\n lines.push(`- **URL**: ${ctx.url}`);\n lines.push('');\n\n if (ctx.source && snippet) {\n const startLine = Math.max(1, ctx.source.line - 10);\n const endLine = ctx.source.line + 10;\n lines.push('### Source Code');\n lines.push('```tsx');\n lines.push(`// ${ctx.source.file}:${startLine}-${endLine}`);\n lines.push(snippet);\n lines.push('```');\n lines.push('');\n }\n\n lines.push('### Styling');\n if (ctx.classes) {\n lines.push(`- **Classes**: \\`${ctx.classes}\\``);\n }\n const styleEntries = Object.entries(ctx.computedStyles);\n if (styleEntries.length > 0) {\n lines.push(`- **Computed**: ${styleEntries.map(([k, v]) => `${camelToKebab(k)}: ${v}`).join(', ')}`);\n }\n lines.push(`- **Dimensions**: ${Math.round(ctx.dimensions.width)}x${Math.round(ctx.dimensions.height)}px at (${Math.round(ctx.dimensions.x)}, ${Math.round(ctx.dimensions.y)})`);\n lines.push('');\n\n if (ctx.componentHierarchy.length > 0) {\n lines.push('### Component Hierarchy');\n lines.push(ctx.componentHierarchy.join(' > '));\n lines.push('');\n }\n\n if (screenshot) {\n lines.push('### Screenshot');\n lines.push(`![element ${i + 1}](${screenshot})`);\n lines.push('');\n }\n }\n\n return lines.join('\\n');\n}\n\nfunction camelToKebab(str: string): string {\n return str.replace(/[A-Z]/g, m => '-' + m.toLowerCase());\n}\n","import { exec } from 'child_process';\nimport { platform } from 'os';\n\nexport function copyToClipboard(text: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const os = platform();\n let cmd: string;\n\n if (os === 'darwin') {\n cmd = 'pbcopy';\n } else if (os === 'linux') {\n cmd = 'xclip -selection clipboard';\n } else if (os === 'win32') {\n cmd = 'clip';\n } else {\n reject(new Error(`Unsupported platform: ${os}`));\n return;\n }\n\n const proc = exec(cmd, (err) => {\n if (err) reject(err);\n else resolve();\n });\n\n proc.stdin?.write(text);\n proc.stdin?.end();\n });\n}\n","import type { ViteDevServer } from 'vite';\nimport { writeContext } from './context-writer';\nimport { copyToClipboard } from './clipboard';\nimport type { ElementContext, UIContextKitOptions } from './types';\n\nexport function setupWebSocket(server: ViteDevServer, options: UIContextKitOptions): void {\n const root = server.config.root;\n const outputDir = options.outputDir || '.ui-context';\n const shouldCopy = options.clipboard !== false;\n\n server.ws.on('ui-context:capture', async (data: ElementContext | ElementContext[], client) => {\n try {\n const count = Array.isArray(data) ? data.length : 1;\n console.log(`[ui-context-kit] Received context capture (${count} element${count > 1 ? 's' : ''})`);\n\n const filePath = await writeContext(data, root, outputDir);\n\n if (shouldCopy) {\n try {\n const fs = await import('fs');\n const content = fs.readFileSync(filePath, 'utf-8');\n await copyToClipboard(content);\n console.log('[ui-context-kit] Context copied to clipboard');\n } catch (e) {\n console.warn('[ui-context-kit] Could not copy to clipboard:', e);\n }\n }\n\n client.send('ui-context:capture-result', { success: true });\n } catch (err: any) {\n console.error('[ui-context-kit] Error writing context:', err);\n client.send('ui-context:capture-result', { success: false, error: err.message });\n }\n });\n}\n","import path from 'path';\nimport { fileURLToPath } from 'url';\nimport { startContextServer } from './next-server';\nimport type { UIContextKitOptions } from './types';\n\n/**\n * Resolves the path to the next-loader.cjs file in the dist directory.\n */\nfunction resolveLoaderPath(): string {\n try {\n // ESM: import.meta.url is available\n const __dirname = path.dirname(fileURLToPath(import.meta.url));\n return path.resolve(__dirname, 'next-loader.cjs');\n } catch {\n // CJS fallback: __dirname is available\n return path.resolve(__dirname, 'next-loader.cjs');\n }\n}\n\n/**\n * Wraps a Next.js config to add ui-context-kit source attribute injection in development.\n * Supports both webpack and Turbopack.\n *\n * Also starts a standalone HTTP context server (port 19638) so the browser overlay\n * can send captured context without Vite's HMR WebSocket.\n *\n * Usage:\n * ```js\n * // next.config.mjs\n * import { withUIContext } from '@ui-context-kit/bridge';\n * export default withUIContext({ /* your config *\\/ });\n * ```\n */\nexport function withUIContext(nextConfig: any = {}, options?: UIContextKitOptions) {\n if (process.env.NODE_ENV !== 'development') return nextConfig;\n\n // Start the standalone context server for receiving captures\n startContextServer(options);\n\n const loaderPath = resolveLoaderPath();\n\n return {\n ...nextConfig,\n\n // Turbopack support\n experimental: {\n ...nextConfig.experimental,\n turbo: {\n ...nextConfig.experimental?.turbo,\n rules: {\n ...nextConfig.experimental?.turbo?.rules,\n '*.tsx': {\n loaders: [loaderPath],\n as: '*.tsx',\n },\n '*.jsx': {\n loaders: [loaderPath],\n as: '*.jsx',\n },\n },\n },\n },\n\n // Webpack support\n webpack(config: any, context: any) {\n config.module.rules.unshift({\n test: /\\.(jsx|tsx)$/,\n exclude: /node_modules/,\n enforce: 'pre' as const,\n use: [{ loader: loaderPath }],\n });\n\n if (typeof nextConfig.webpack === 'function') {\n config = nextConfig.webpack(config, context);\n }\n\n return config;\n },\n };\n}\n","import http from 'http';\nimport { writeContext } from './context-writer';\nimport { copyToClipboard } from './clipboard';\nimport type { UIContextKitOptions } from './types';\n\nconst DEFAULT_PORT = 19638;\nlet serverInstance: http.Server | null = null;\n\n/**\n * Starts a standalone HTTP server for receiving UI context captures.\n * Used by Next.js projects where Vite's HMR WebSocket is not available.\n *\n * The overlay's transport sends HTTP POST to /capture with the context data.\n */\nexport function startContextServer(options: UIContextKitOptions = {}): void {\n if (serverInstance) return;\n\n const port = DEFAULT_PORT;\n const outputDir = options.outputDir || '.ui-context';\n const shouldCopy = options.clipboard !== false;\n const projectRoot = process.cwd();\n\n serverInstance = http.createServer((req, res) => {\n // CORS headers for cross-port requests\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n if (req.method === 'POST' && req.url === '/capture') {\n let body = '';\n req.on('data', (chunk: string) => {\n body += chunk;\n });\n req.on('end', async () => {\n try {\n const data = JSON.parse(body);\n console.log(\n `[ui-context-kit] Received context capture (${Array.isArray(data) ? data.length : 1} element${Array.isArray(data) && data.length > 1 ? 's' : ''})`,\n );\n\n const filePath = await writeContext(data, projectRoot, outputDir);\n\n if (shouldCopy) {\n try {\n const fs = await import('fs');\n const content = fs.readFileSync(filePath, 'utf-8');\n await copyToClipboard(content);\n console.log('[ui-context-kit] Context copied to clipboard');\n } catch {\n // clipboard copy is best-effort\n }\n }\n\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ success: true }));\n } catch (err: any) {\n console.error('[ui-context-kit] Error writing context:', err);\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ success: false, error: err.message }));\n }\n });\n return;\n }\n\n res.writeHead(404);\n res.end();\n });\n\n serverInstance.listen(port, () => {\n console.log(`[ui-context-kit] Context server running on http://localhost:${port}`);\n });\n\n serverInstance.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n console.log(`[ui-context-kit] Context server already running on port ${port}`);\n serverInstance = null;\n } else {\n console.error('[ui-context-kit] Context server error:', err);\n serverInstance = null;\n }\n });\n}\n","import { createVitePlugin } from './vite-plugin';\nimport { writeContext } from './context-writer';\nimport { withUIContext } from './next-wrapper';\nimport type { UIContextKitOptions } from './types';\n\n/**\n * Vite plugin for UI Context Kit.\n * Enables browser-based element selection and context capture for AI coding assistants.\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { uiContextKit } from '@ui-context-kit/bridge'\n * export default defineConfig({\n * plugins: [react(), uiContextKit()]\n * })\n * ```\n */\nexport function uiContextKit(options?: UIContextKitOptions) {\n return createVitePlugin(options);\n}\n\nexport { writeContext, withUIContext };\nexport type { UIContextKitOptions, ElementContext, SourceLocation } from './types';\n"],"mappings":"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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;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;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;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","names":["path","fs","timestamp","header","fs","path","fs","path","fs","__dirname","path"]}
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (let key of __getOwnPropNames(from))
11
+ if (!__hasOwnProp.call(to, key) && key !== except)
12
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
13
+ }
14
+ return to;
15
+ };
16
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
17
+ // If the importer is in node compatibility mode or this is not an ESM
18
+ // file that has been converted to a CommonJS file using a Babel-
19
+ // compatible transform (i.e. "__esModule" has not been set), then set
20
+ // "default" to the CommonJS "module.exports" for node compatibility.
21
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
+ mod
23
+ ));
24
+
25
+ // src/next-loader.ts
26
+ var import_path = __toESM(require("path"), 1);
27
+ var import_babel_plugin = require("@ui-context-kit/babel-plugin");
28
+ function nextLoader(source) {
29
+ const callback = this.async();
30
+ const resourcePath = this.resourcePath;
31
+ if (resourcePath.includes("node_modules")) {
32
+ callback(null, source);
33
+ return;
34
+ }
35
+ const relativePath = import_path.default.relative(process.cwd(), resourcePath);
36
+ try {
37
+ const result = (0, import_babel_plugin.injectSourceAttributes)(source, relativePath);
38
+ if (!result) {
39
+ callback(null, source);
40
+ return;
41
+ }
42
+ callback(null, result.code, result.map);
43
+ } catch {
44
+ callback(null, source);
45
+ }
46
+ }
47
+ module.exports = nextLoader;
48
+ //# sourceMappingURL=next-loader.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/next-loader.ts"],"sourcesContent":["import path from 'path';\nimport { injectSourceAttributes } from '@ui-context-kit/babel-plugin';\n\n/**\n * Webpack loader that injects data-source-* attributes into JSX elements.\n * Used by withUIContext for both webpack and Turbopack in Next.js projects.\n *\n * Webpack requires module.exports to be the loader function directly.\n */\nfunction nextLoader(this: any, source: string) {\n const callback = this.async();\n const resourcePath: string = this.resourcePath;\n\n // Skip node_modules\n if (resourcePath.includes('node_modules')) {\n callback(null, source);\n return;\n }\n\n const relativePath = path.relative(process.cwd(), resourcePath);\n\n try {\n const result = injectSourceAttributes(source, relativePath);\n if (!result) {\n callback(null, source);\n return;\n }\n callback(null, result.code, result.map);\n } catch {\n // On error, pass through the original source unchanged\n callback(null, source);\n }\n}\n\nexport = nextLoader;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,kBAAiB;AACjB,0BAAuC;AAQvC,SAAS,WAAsB,QAAgB;AAC7C,QAAM,WAAW,KAAK,MAAM;AAC5B,QAAM,eAAuB,KAAK;AAGlC,MAAI,aAAa,SAAS,cAAc,GAAG;AACzC,aAAS,MAAM,MAAM;AACrB;AAAA,EACF;AAEA,QAAM,eAAe,YAAAA,QAAK,SAAS,QAAQ,IAAI,GAAG,YAAY;AAE9D,MAAI;AACF,UAAM,aAAS,4CAAuB,QAAQ,YAAY;AAC1D,QAAI,CAAC,QAAQ;AACX,eAAS,MAAM,MAAM;AACrB;AAAA,IACF;AACA,aAAS,MAAM,OAAO,MAAM,OAAO,GAAG;AAAA,EACxC,QAAQ;AAEN,aAAS,MAAM,MAAM;AAAA,EACvB;AACF;AAEA,iBAAS;","names":["path"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ui-context-kit/bridge",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Server bridge for ui-context-kit - writes context files for AI coding assistants",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -11,17 +11,25 @@
11
11
  "types": "./dist/index.d.ts",
12
12
  "import": "./dist/index.js",
13
13
  "require": "./dist/index.cjs"
14
+ },
15
+ "./next-loader": {
16
+ "require": "./dist/next-loader.cjs"
14
17
  }
15
18
  },
16
19
  "files": [
17
20
  "dist"
18
21
  ],
22
+ "scripts": {
23
+ "build": "tsup",
24
+ "dev": "tsup --watch"
25
+ },
19
26
  "dependencies": {
20
27
  "@babel/parser": "^7.24.0",
21
28
  "@babel/traverse": "^7.24.0",
22
29
  "@babel/types": "^7.24.0",
23
- "magic-string": "^0.30.8",
24
- "@ui-context-kit/babel-plugin": "0.1.0"
30
+ "@ui-context-kit/babel-plugin": "workspace:*",
31
+ "@ui-context-kit/overlay": "workspace:*",
32
+ "magic-string": "^0.30.8"
25
33
  },
26
34
  "peerDependencies": {
27
35
  "vite": ">=5.0.0"
@@ -36,9 +44,5 @@
36
44
  "tsup": "^8.0.0",
37
45
  "typescript": "^5.4.0",
38
46
  "vite": "^5.4.0"
39
- },
40
- "scripts": {
41
- "build": "tsup",
42
- "dev": "tsup --watch"
43
47
  }
44
- }
48
+ }