@winstonfassett/webdev-gateway 0.1.0-alpha.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.
Files changed (112) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/LICENSE +21 -0
  3. package/README.md +78 -0
  4. package/dist/adapter-helpers.d.ts +64 -0
  5. package/dist/adapter-helpers.d.ts.map +1 -0
  6. package/dist/adapter-helpers.js +297 -0
  7. package/dist/adapter-helpers.js.map +1 -0
  8. package/dist/admin/assets/index-DEDI8OIx.css +2 -0
  9. package/dist/admin/assets/index-DaI40ww1.js +70 -0
  10. package/dist/admin/assets/tinykeys.module-CjuTRcEz.js +1 -0
  11. package/dist/admin/index.html +13 -0
  12. package/dist/admin-rpc.d.ts +27 -0
  13. package/dist/admin-rpc.d.ts.map +1 -0
  14. package/dist/admin-rpc.js +147 -0
  15. package/dist/admin-rpc.js.map +1 -0
  16. package/dist/admin.d.ts +10 -0
  17. package/dist/admin.d.ts.map +1 -0
  18. package/dist/admin.js +202 -0
  19. package/dist/admin.js.map +1 -0
  20. package/dist/auto-register.d.ts +10 -0
  21. package/dist/auto-register.d.ts.map +1 -0
  22. package/dist/auto-register.js +145 -0
  23. package/dist/auto-register.js.map +1 -0
  24. package/dist/cdp-relay.d.ts +110 -0
  25. package/dist/cdp-relay.d.ts.map +1 -0
  26. package/dist/cdp-relay.js +616 -0
  27. package/dist/cdp-relay.js.map +1 -0
  28. package/dist/cli.d.ts +3 -0
  29. package/dist/cli.d.ts.map +1 -0
  30. package/dist/cli.js +95 -0
  31. package/dist/cli.js.map +1 -0
  32. package/dist/doctor.d.ts +6 -0
  33. package/dist/doctor.d.ts.map +1 -0
  34. package/dist/doctor.js +149 -0
  35. package/dist/doctor.js.map +1 -0
  36. package/dist/element-grab-client.js +305 -0
  37. package/dist/element-grab.d.ts +15 -0
  38. package/dist/element-grab.d.ts.map +1 -0
  39. package/dist/element-grab.js +102 -0
  40. package/dist/element-grab.js.map +1 -0
  41. package/dist/gateway.d.ts +5 -0
  42. package/dist/gateway.d.ts.map +1 -0
  43. package/dist/gateway.js +534 -0
  44. package/dist/gateway.js.map +1 -0
  45. package/dist/installer.d.ts +48 -0
  46. package/dist/installer.d.ts.map +1 -0
  47. package/dist/installer.js +637 -0
  48. package/dist/installer.js.map +1 -0
  49. package/dist/libs/element-source.js +35 -0
  50. package/dist/libs/modern-screenshot.js +14 -0
  51. package/dist/log-reader.d.ts +30 -0
  52. package/dist/log-reader.d.ts.map +1 -0
  53. package/dist/log-reader.js +174 -0
  54. package/dist/log-reader.js.map +1 -0
  55. package/dist/mcp-server.d.ts +22 -0
  56. package/dist/mcp-server.d.ts.map +1 -0
  57. package/dist/mcp-server.js +115 -0
  58. package/dist/mcp-server.js.map +1 -0
  59. package/dist/mcp-tools-core.d.ts +30 -0
  60. package/dist/mcp-tools-core.d.ts.map +1 -0
  61. package/dist/mcp-tools-core.js +375 -0
  62. package/dist/mcp-tools-core.js.map +1 -0
  63. package/dist/mcp-tools-full.d.ts +4 -0
  64. package/dist/mcp-tools-full.d.ts.map +1 -0
  65. package/dist/mcp-tools-full.js +141 -0
  66. package/dist/mcp-tools-full.js.map +1 -0
  67. package/dist/playwright-commands.d.ts +33 -0
  68. package/dist/playwright-commands.d.ts.map +1 -0
  69. package/dist/playwright-commands.js +356 -0
  70. package/dist/playwright-commands.js.map +1 -0
  71. package/dist/registry.d.ts +83 -0
  72. package/dist/registry.d.ts.map +1 -0
  73. package/dist/registry.js +205 -0
  74. package/dist/registry.js.map +1 -0
  75. package/dist/rpc-server.d.ts +54 -0
  76. package/dist/rpc-server.d.ts.map +1 -0
  77. package/dist/rpc-server.js +207 -0
  78. package/dist/rpc-server.js.map +1 -0
  79. package/dist/session.d.ts +13 -0
  80. package/dist/session.d.ts.map +1 -0
  81. package/dist/session.js +61 -0
  82. package/dist/session.js.map +1 -0
  83. package/dist/types.d.ts +76 -0
  84. package/dist/types.d.ts.map +1 -0
  85. package/dist/types.js +2 -0
  86. package/dist/types.js.map +1 -0
  87. package/dist/webdev-client.js +20 -0
  88. package/dist/writers/base.d.ts +24 -0
  89. package/dist/writers/base.d.ts.map +1 -0
  90. package/dist/writers/base.js +98 -0
  91. package/dist/writers/base.js.map +1 -0
  92. package/dist/writers/console.d.ts +8 -0
  93. package/dist/writers/console.d.ts.map +1 -0
  94. package/dist/writers/console.js +14 -0
  95. package/dist/writers/console.js.map +1 -0
  96. package/dist/writers/dev-events.d.ts +28 -0
  97. package/dist/writers/dev-events.d.ts.map +1 -0
  98. package/dist/writers/dev-events.js +53 -0
  99. package/dist/writers/dev-events.js.map +1 -0
  100. package/dist/writers/errors.d.ts +8 -0
  101. package/dist/writers/errors.d.ts.map +1 -0
  102. package/dist/writers/errors.js +14 -0
  103. package/dist/writers/errors.js.map +1 -0
  104. package/dist/writers/network.d.ts +9 -0
  105. package/dist/writers/network.d.ts.map +1 -0
  106. package/dist/writers/network.js +17 -0
  107. package/dist/writers/network.js.map +1 -0
  108. package/dist/writers/server-console.d.ts +8 -0
  109. package/dist/writers/server-console.d.ts.map +1 -0
  110. package/dist/writers/server-console.js +14 -0
  111. package/dist/writers/server-console.js.map +1 -0
  112. package/package.json +79 -0
package/dist/cli.js ADDED
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { startGateway } from './gateway.js';
4
+ import { runInit } from './installer.js';
5
+ import { runDoctor } from './doctor.js';
6
+ const program = new Command();
7
+ program
8
+ .name('npx webdev')
9
+ .description('MCP gateway for web development — proxy any dev server with live browser observability for AI agents');
10
+ program
11
+ .command('start', { isDefault: true })
12
+ .description('Start the gateway (default command)')
13
+ .option('-p, --port <port>', 'Gateway port', (v) => parseInt(v, 10))
14
+ .option('--network', 'Capture fetch/XHR requests')
15
+ .option('--https', 'Enable HTTPS with self-signed cert')
16
+ .option('--cert <path>', 'Custom TLS certificate (use with --key)')
17
+ .option('--key <path>', 'Custom TLS private key (use with --cert)')
18
+ .option('--auto-register', 'Register MCP URL in .mcp.json, .cursor/, .windsurf/ then exit')
19
+ .option('--global', 'With --auto-register: write to user-level configs (~/.claude/, ~/.cursor/)')
20
+ .action(async (opts) => {
21
+ if (opts.autoRegister) {
22
+ const { autoRegister, autoRegisterGlobal } = await import('./auto-register.js');
23
+ const port = opts.port ?? 3333;
24
+ const mcpUrl = `http://localhost:${port}/__mcp/sse`;
25
+ if (opts.global) {
26
+ const registered = autoRegisterGlobal(mcpUrl);
27
+ for (const path of registered) {
28
+ console.log(` Auto-registered (global): ${path}`);
29
+ }
30
+ }
31
+ else {
32
+ const registered = autoRegister(process.cwd(), mcpUrl);
33
+ for (const path of registered) {
34
+ console.log(` Auto-registered: ${path}`);
35
+ }
36
+ }
37
+ process.exit(0);
38
+ }
39
+ await startGateway({
40
+ port: opts.port,
41
+ network: opts.network,
42
+ https: opts.https,
43
+ cert: opts.cert,
44
+ key: opts.key,
45
+ });
46
+ });
47
+ program
48
+ .command('init')
49
+ .description('Install webdev into the current project (detect framework, wire config, install deps, register MCP)')
50
+ .option('--cwd <dir>', 'Project directory (default: current)', process.cwd())
51
+ .option('-p, --port <port>', 'Gateway port to register with MCP clients (default: 3333)', (v) => parseInt(v, 10), 3333)
52
+ .option('--skip-install', 'Skip npm install of adapter + gateway packages')
53
+ .option('--skip-mcp', 'Skip writing MCP client config files')
54
+ .option('-y, --yes', 'Auto-accept all prompts (non-interactive / CI)')
55
+ .action(async (opts) => {
56
+ await runInit({
57
+ cwd: opts.cwd,
58
+ port: opts.port,
59
+ skipInstall: opts.skipInstall,
60
+ skipMcp: opts.skipMcp,
61
+ yes: opts.yes,
62
+ });
63
+ });
64
+ program
65
+ .command('doctor')
66
+ .description('Verify setup: gateway reachable, framework wired, adapter installed, MCP registered')
67
+ .option('--cwd <dir>', 'Project directory (default: current)', process.cwd())
68
+ .option('-p, --port <port>', 'Gateway port (default: 3333)', (v) => parseInt(v, 10), 3333)
69
+ .action(async (opts) => {
70
+ await runDoctor({ cwd: opts.cwd, port: opts.port });
71
+ });
72
+ program
73
+ .command('register')
74
+ .description('Register MCP URL with agent clients (.mcp.json, .cursor/, .windsurf/, .vscode/)')
75
+ .option('-p, --port <port>', 'Gateway port', (v) => parseInt(v, 10), 3333)
76
+ .option('--global', 'Write to user-level configs (~/.claude/, ~/.cursor/) instead of project-level')
77
+ .action(async (opts) => {
78
+ const { autoRegister, autoRegisterGlobal } = await import('./auto-register.js');
79
+ const mcpUrl = `http://localhost:${opts.port}/__mcp/sse`;
80
+ if (opts.global) {
81
+ const registered = autoRegisterGlobal(mcpUrl);
82
+ for (const path of registered)
83
+ console.log(` Registered (global): ${path}`);
84
+ }
85
+ else {
86
+ const registered = autoRegister(process.cwd(), mcpUrl);
87
+ for (const path of registered)
88
+ console.log(` Registered: ${path}`);
89
+ }
90
+ });
91
+ program.parseAsync().catch((err) => {
92
+ console.error('Failed:', err);
93
+ process.exit(1);
94
+ });
95
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export type DoctorOptions = {
2
+ cwd: string;
3
+ port: number;
4
+ };
5
+ export declare function runDoctor(opts: DoctorOptions): Promise<void>;
6
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AAcA,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA8GlE"}
package/dist/doctor.js ADDED
@@ -0,0 +1,149 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { join, dirname } from 'node:path';
3
+ import http from 'node:http';
4
+ import { intro, outro, log, note } from '@clack/prompts';
5
+ import pc from 'picocolors';
6
+ import { detectFrameworksIn, isWired, relPath, ADAPTER_PACKAGES, GATEWAY_PKG, } from './installer.js';
7
+ export async function runDoctor(opts) {
8
+ intro(pc.cyan('webdev doctor'));
9
+ let pass = 0;
10
+ let fail = 0;
11
+ let warn = 0;
12
+ // 1. Gateway reachable
13
+ const gatewayOk = await checkGatewayReachable(opts.port);
14
+ if (gatewayOk) {
15
+ log.success(`Gateway responding at ${pc.dim(`http://localhost:${opts.port}`)}`);
16
+ pass++;
17
+ }
18
+ else {
19
+ log.error(`Gateway not responding at ${pc.dim(`http://localhost:${opts.port}`)} — start it with ${pc.cyan('npm run dev')} (adapter auto-spawns) or ${pc.cyan('npx webdev')}`);
20
+ fail++;
21
+ }
22
+ // 2. Detect framework + check wiring + check adapter installed
23
+ const frameworks = await detectFrameworksIn(opts.cwd);
24
+ if (frameworks.length === 0) {
25
+ log.warn(`No supported framework config in ${pc.dim(opts.cwd)}. Skipping wiring + adapter checks. (Run ${pc.cyan('init')} from the directory containing your framework config.)`);
26
+ warn++;
27
+ }
28
+ else {
29
+ for (const fw of frameworks) {
30
+ const rel = relPath(opts.cwd, fw.configPath);
31
+ if (isWired(fw)) {
32
+ log.success(`${fw.name}: config wired ${pc.dim(`(${rel})`)}`);
33
+ pass++;
34
+ }
35
+ else {
36
+ log.error(`${fw.name}: config NOT wired ${pc.dim(`(${rel})`)} — run ${pc.cyan('npx webdev init')}`);
37
+ fail++;
38
+ }
39
+ const adapterPkg = ADAPTER_PACKAGES[fw.name];
40
+ if (adapterPkg) {
41
+ if (isPackageInstalled(fw.projectDir, adapterPkg)) {
42
+ log.success(`${adapterPkg} installed ${pc.dim(`(${relPath(opts.cwd, fw.projectDir) || '.'})`)}`);
43
+ pass++;
44
+ }
45
+ else {
46
+ log.error(`${adapterPkg} NOT installed in ${pc.dim(relPath(opts.cwd, fw.projectDir) || '.')} — run ${pc.cyan(`npm i -D ${adapterPkg}`)}`);
47
+ fail++;
48
+ }
49
+ }
50
+ if (!isPackageInstalled(fw.projectDir, GATEWAY_PKG)) {
51
+ log.warn(`${GATEWAY_PKG} not in ${relPath(opts.cwd, fw.projectDir) || '.'} package.json (OK if you use ${pc.cyan('npx webdev')} — won't auto-spawn from the adapter)`);
52
+ warn++;
53
+ }
54
+ }
55
+ }
56
+ // 3. MCP client configs — check for ANY entry pointing at our gateway URL
57
+ // (user may have registered under a custom key like 'my-mcp' instead of 'webdev')
58
+ const gatewayUrl = `http://localhost:${opts.port}/__mcp/sse`;
59
+ const mcpRels = [
60
+ { path: '.mcp.json', serversKey: 'mcpServers' },
61
+ { path: '.cursor/mcp.json', serversKey: 'mcpServers' },
62
+ { path: '.windsurf/mcp.json', serversKey: 'mcpServers' },
63
+ { path: '.vscode/mcp.json', serversKey: 'servers' },
64
+ ];
65
+ let anyMcpFound = false;
66
+ let anyMcpPointsHere = false;
67
+ for (const { path, serversKey } of mcpRels) {
68
+ const full = join(opts.cwd, path);
69
+ if (!existsSync(full))
70
+ continue;
71
+ anyMcpFound = true;
72
+ try {
73
+ const config = JSON.parse(readFileSync(full, 'utf-8'));
74
+ const servers = (config[serversKey] ?? {});
75
+ const matchingEntry = Object.entries(servers).find(([_k, v]) => v?.url === gatewayUrl);
76
+ if (matchingEntry) {
77
+ const [key] = matchingEntry;
78
+ const keyHint = key === 'webdev' ? '' : pc.dim(` (key: ${key})`);
79
+ log.success(`MCP registered in ${pc.dim(path)}${keyHint}`);
80
+ pass++;
81
+ anyMcpPointsHere = true;
82
+ }
83
+ else {
84
+ log.warn(`${path} exists but no entry points to ${pc.dim(gatewayUrl)}`);
85
+ warn++;
86
+ }
87
+ }
88
+ catch (err) {
89
+ log.warn(`Could not parse ${pc.dim(path)} — ${err.message}`);
90
+ warn++;
91
+ }
92
+ }
93
+ if (!anyMcpFound) {
94
+ log.warn(`No MCP client config files found. Run ${pc.cyan('npx webdev register')} to create them.`);
95
+ warn++;
96
+ }
97
+ else if (!anyMcpPointsHere) {
98
+ log.error(`MCP files exist but none point to ${pc.dim(gatewayUrl)}. Run ${pc.cyan('npx webdev register')}.`);
99
+ fail++;
100
+ }
101
+ // Summary
102
+ const summary = [
103
+ `${pc.green(`✓ ${pass} passed`)}`,
104
+ warn > 0 ? `${pc.yellow(`▲ ${warn} warning${warn !== 1 ? 's' : ''}`)}` : null,
105
+ fail > 0 ? `${pc.red(`✗ ${fail} failed`)}` : null,
106
+ ]
107
+ .filter(Boolean)
108
+ .join(' · ');
109
+ note(summary, 'doctor');
110
+ if (fail > 0) {
111
+ outro(pc.red('Some checks failed.'));
112
+ process.exitCode = 1;
113
+ }
114
+ else if (warn > 0) {
115
+ outro(pc.yellow('All required checks passed (warnings noted).'));
116
+ }
117
+ else {
118
+ outro(pc.green('All checks passed.'));
119
+ }
120
+ }
121
+ async function checkGatewayReachable(port) {
122
+ return new Promise((resolve) => {
123
+ const req = http.request({ host: 'localhost', port, path: '/', method: 'HEAD', timeout: 1500 }, (res) => {
124
+ // Any HTTP response means the gateway is up.
125
+ res.resume();
126
+ resolve(true);
127
+ });
128
+ req.on('error', () => resolve(false));
129
+ req.on('timeout', () => {
130
+ req.destroy();
131
+ resolve(false);
132
+ });
133
+ req.end();
134
+ });
135
+ }
136
+ function isPackageInstalled(projectDir, pkg) {
137
+ // Cheap check: package dir in node_modules. Workspace-hoisted deps may live
138
+ // in a parent node_modules — walk up until found or filesystem root.
139
+ let dir = projectDir;
140
+ while (true) {
141
+ if (existsSync(join(dir, 'node_modules', pkg, 'package.json')))
142
+ return true;
143
+ const parent = dirname(dir);
144
+ if (parent === dir)
145
+ return false;
146
+ dir = parent;
147
+ }
148
+ }
149
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,305 @@
1
+ "use strict";(()=>{var K="data-element-grab";var ve=e=>{let t=document.querySelector(`[${K}]`);if(t){let s=t.shadowRoot?.querySelector(`[${K}]`);if(s instanceof HTMLDivElement&&t.shadowRoot)return s}let n=document.createElement("div");n.setAttribute(K,"true"),n.style.zIndex=String(2147483647),n.style.position="fixed",n.style.inset="0",n.style.pointerEvents="none";let o=n.attachShadow({mode:"open"});if(e){let s=document.createElement("style");s.textContent=e,o.appendChild(s)}let i=document.createElement("div");i.setAttribute(K,"true"),o.appendChild(i);let r=document.body??document.documentElement;return r.appendChild(n),setTimeout(()=>r.appendChild(n),1e3),i};var k=(e,t,n)=>e+(t-e)*n;var G=null,ht=()=>{if(G!==null)return G;try{G=window.matchMedia("(color-gamut: p3)").matches}catch{G=!1}return G},ft="210, 57, 192",gt="0.84 0.19 0.78",R=e=>ht()?`color(display-p3 ${gt} / ${e})`:`rgba(${ft}, ${e})`;var Ae="c",Le=!0;var Ce=32;var Z=.95,Re=.7,Y=.5,Oe=.01,Te=2,Ne=R(.4),Se=R(.05),se=R(.5),ae=R(.08),Ie=R(.3),Me=R(.04),De=R(.15),Pe=50,H=1500,le=100,ce=100,de=8,ke=4,He=.2,Be=50,pe=16,O=4,T=8,Xe=100,$e=15;var Fe=95;var ue=2147483647,q=2147483645;var me=16;var W={selection:{borderColor:se,fillColor:ae,lerpFactor:Z},drag:{borderColor:Ne,fillColor:Se,lerpFactor:Re},grabbed:{borderColor:se,fillColor:ae,lerpFactor:Z},inspect:{borderColor:Ie,fillColor:Me,lerpFactor:Z}},Ve=e=>{let t=e.match(/^(\d+(?:\.\d+)?)/);return t?parseFloat(t[1]):0},z=(e,t,n)=>({id:e,current:{x:t.x,y:t.y,width:t.width,height:t.height},target:{x:t.x,y:t.y,width:t.width,height:t.height},borderRadius:Ve(t.borderRadius),opacity:n?.opacity??1,targetOpacity:n?.targetOpacity??n?.opacity??1,createdAt:n?.createdAt,initialized:!0}),J=(e,t,n)=>{e.target={x:t.x,y:t.y,width:t.width,height:t.height},e.borderRadius=Ve(t.borderRadius),n!==void 0&&(e.targetOpacity=n)},Q=(e,t,n=!1)=>{let o=k(e.current.x,e.target.x,t),i=k(e.current.y,e.target.y,t),r=k(e.current.width,e.target.width,t),s=k(e.current.height,e.target.height,t),a=Math.abs(o-e.target.x)<Y&&Math.abs(i-e.target.y)<Y&&Math.abs(r-e.target.width)<Y&&Math.abs(s-e.target.height)<Y;e.current.x=a?e.target.x:o,e.current.y=a?e.target.y:i,e.current.width=a?e.target.width:r,e.current.height=a?e.target.height:s;let p=!0;if(n){let d=k(e.opacity,e.targetOpacity,t);p=Math.abs(d-e.targetOpacity)<Oe,e.opacity=p?e.targetOpacity:d}return!a||!p},yt=(e,t,n,o,i,r,s,a,p=1)=>{if(o<=0||i<=0)return;let d=Math.min(r,o/2,i/2);e.globalAlpha=p,e.beginPath(),d>0?e.roundRect(t,n,o,i,d):e.rect(t,n,o,i),e.fillStyle=s,e.fill(),e.strokeStyle=a,e.lineWidth=1,e.stroke(),e.globalAlpha=1},ee=class{canvas;mainCtx=null;w=0;h=0;dpr=1;frameId=null;layers={selection:{canvas:null,ctx:null},drag:{canvas:null,ctx:null},grabbed:{canvas:null,ctx:null},inspect:{canvas:null,ctx:null}};selectionAnims=[];dragAnim=null;grabbedAnims=[];inspectAnims=[];selectionVisible=!1;selectionFading=!1;dragVisible=!1;constructor(t){this.canvas=document.createElement("canvas"),this.canvas.setAttribute("data-element-grab-canvas",""),this.canvas.style.position="fixed",this.canvas.style.top="0",this.canvas.style.left="0",this.canvas.style.pointerEvents="none",this.canvas.style.zIndex=String(q),t.appendChild(this.canvas),this.init(),window.addEventListener("resize",()=>this.init())}init(){let t=typeof window<"u"&&window.matchMedia?.("(color-gamut: p3)")?.matches?"display-p3":"srgb";this.dpr=Math.max(window.devicePixelRatio||1,Te),this.w=window.innerWidth,this.h=window.innerHeight,this.canvas.width=this.w*this.dpr,this.canvas.height=this.h*this.dpr,this.canvas.style.width=`${this.w}px`,this.canvas.style.height=`${this.h}px`,this.mainCtx=this.canvas.getContext("2d",{colorSpace:t}),this.mainCtx&&this.mainCtx.scale(this.dpr,this.dpr);for(let n of Object.keys(this.layers)){let o=new OffscreenCanvas(this.w*this.dpr,this.h*this.dpr),i=o.getContext("2d",{colorSpace:t});i&&i.scale(this.dpr,this.dpr),this.layers[n]={canvas:o,ctx:i}}}setSelection(t,n=!1){if(!t){this.selectionAnims=[],this.schedule();return}this.selectionAnims.length>0?(J(this.selectionAnims[0],t),n&&(this.selectionAnims[0].current={...this.selectionAnims[0].target})):this.selectionAnims=[z("sel-0",t)],this.schedule()}setSelectionMultiple(t,n=!1){this.selectionAnims=t.map((o,i)=>{let r=`sel-${i}`,s=this.selectionAnims.find(a=>a.id===r);return s?(J(s,o),n&&(s.current={...s.target}),s):z(r,o)}),this.schedule()}setDrag(t){if(!t){this.dragAnim=null,this.schedule();return}this.dragAnim?J(this.dragAnim,t):this.dragAnim=z("drag",t),this.schedule()}addGrabbed(t,n){this.grabbedAnims.find(o=>o.id===t)||this.grabbedAnims.push(z(t,n,{createdAt:Date.now()})),this.schedule()}setInspect(t){this.inspectAnims=t.map((n,o)=>{let i=`inspect-${o}`,r=this.inspectAnims.find(s=>s.id===i);return r?(J(r,n),r):z(i,n)}),this.schedule()}clearInspect(){this.inspectAnims=[],this.schedule()}destroy(){this.frameId!==null&&cancelAnimationFrame(this.frameId),this.canvas.remove(),window.removeEventListener("resize",()=>this.init())}schedule(){this.frameId===null&&(this.frameId=requestAnimationFrame(()=>this.tick()))}tick(){this.frameId=null;let t=!1;for(let o of this.selectionAnims)o.initialized&&Q(o,W.selection.lerpFactor)&&(t=!0);this.dragAnim?.initialized&&Q(this.dragAnim,W.drag.lerpFactor)&&(t=!0);let n=Date.now();this.grabbedAnims=this.grabbedAnims.filter(o=>{if(o.initialized&&Q(o,W.grabbed.lerpFactor)&&(t=!0),o.createdAt){let i=n-o.createdAt;return i>=H+ce?!1:(i>H&&(o.opacity=1-(i-H)/ce,t=!0),!0)}return o.opacity>0});for(let o of this.inspectAnims)o.initialized&&Q(o,W.inspect.lerpFactor)&&(t=!0);this.composite(),t&&(this.frameId=requestAnimationFrame(()=>this.tick()))}renderLayer(t,n,o){let i=this.layers[t];if(!i.ctx)return;i.ctx.clearRect(0,0,this.w,this.h);let r=W[t];for(let s of n){let a=o?.fading?0:s.opacity;yt(i.ctx,s.current.x,s.current.y,s.current.width,s.current.height,s.borderRadius,r.fillColor,r.borderColor,a)}}composite(){if(!this.mainCtx)return;this.mainCtx.setTransform(1,0,0,1,0,0),this.mainCtx.clearRect(0,0,this.canvas.width,this.canvas.height),this.mainCtx.setTransform(this.dpr,0,0,this.dpr,0,0),this.renderLayer("inspect",this.inspectAnims),this.renderLayer("drag",this.dragAnim?[this.dragAnim]:[]),this.renderLayer("selection",this.selectionAnims,{fading:this.selectionFading}),this.renderLayer("grabbed",this.grabbedAnims);let t=["inspect","drag","selection","grabbed"];for(let n of t){let o=this.layers[n].canvas;o&&this.mainCtx.drawImage(o,0,0,this.w,this.h)}}};var bt=["data-testid","data-test-id","data-test","data-cy","data-qa","aria-label","role","name","title","alt"];var Ge=e=>typeof CSS<"u"&&CSS.escape?CSS.escape(e):e.replace(/[^a-zA-Z0-9_-]/g,t=>`\\${t}`),he=(e,t)=>{try{let n=e.ownerDocument.querySelectorAll(t);return n.length===1&&n[0]===e}catch{return!1}},Ye=e=>{if(e instanceof HTMLElement&&e.id){let i=`#${Ge(e.id)}`;if(he(e,i))return i}for(let i of bt){let r=e.getAttribute(i);if(!r||r.length>120)continue;let s=JSON.stringify(r),a=`[${i}=${s}]`;if(he(e,a))return a;let p=`${e.tagName.toLowerCase()}${a}`;if(he(e,p))return p}let t=e.ownerDocument.body??e.ownerDocument.documentElement,n=[],o=e;for(;o;){if(o instanceof HTMLElement&&o.id){n.unshift(`#${Ge(o.id)}`);break}let i=o.parentElement;if(!i){n.unshift(o.tagName.toLowerCase());break}let s=Array.from(i.children).indexOf(o)+1;if(n.unshift(`${o.tagName.toLowerCase()}:nth-child(${s})`),i===t){n.unshift(t.tagName.toLowerCase());break}o=i}return n.join(" > ")};function Et(e){try{let t=Object.keys(e).find(i=>i.startsWith("__reactFiber$")||i.startsWith("__reactInternalInstance$"));if(!t)return null;let o=e[t];for(;o;){if(o.type&&typeof o.type=="function"){let i=o.type.displayName||o.type.name;if(i&&i.length>1&&i[0]===i[0].toUpperCase()&&i!=="Fragment"&&i!=="Suspense"){let r=o._debugSource;return{component:i,file:r?.fileName??null,line:r?.lineNumber??null,column:r?.columnNumber??null}}}o=o.return}}catch{}return null}function _t(e){try{let t=e.getAttribute("data-v-inspector");if(t){let o=t.split(":");if(o.length>=2){let i=o.slice(0,-2).join(":")||o[0],r=parseInt(o[o.length-2],10),s=parseInt(o[o.length-1],10);return{component:We(e),file:i,line:isNaN(r)?null:r,column:isNaN(s)?null:s}}}let n=We(e);if(n)return{component:n,file:null,line:null,column:null}}catch{}return null}function We(e){let t=e;for(;t;){let n=t.__vueParentComponent;if(n){let o=n.type;if(o){let i=o.name||o.__name;if(i&&i!=="Fragment")return i}}t=t.parentElement}return null}function xt(e){try{let t=e;for(;t;){let n=t.__svelte_meta;if(n?.loc){let o=n.loc,i=typeof o.file=="string"?o.file:null,r=typeof o.line=="number"?o.line:null,s=typeof o.column=="number"?o.column+1:null,a=null,p=n.parent;for(;p;){if(typeof p.componentTag=="string"){a=p.componentTag;break}p=p.parent}return{component:a,file:i,line:r,column:s}}t=t.parentElement}}catch{}return null}function wt(e){try{let t=e.__c||e._component;if(t){let n=t.constructor?.displayName||t.constructor?.name,o=t.__v?.__source||t.props?.__source;return{component:n&&n!=="Fragment"?n:null,file:o?.fileName??null,line:o?.lineNumber??null,column:o?.columnNumber??null}}}catch{}return null}var U;async function ze(){if(U!==void 0)return U;try{let t=await import((window.__WEBDEV_ORIGIN__||window.location.origin)+"/__libs/element-source.js");return U=t,t}catch{return U=null,null}}ze();async function vt(e){let t=U;if(!t)return null;try{let n=await t.resolveElementInfo(e);return n?{component:n.componentName??null,file:n.source?.filePath??null,line:n.source?.lineNumber??null,column:n.source?.columnNumber??null}:null}catch{return null}}var At=[Et,_t,xt,wt];function fe(e){for(let t of At){let n=t(e);if(n)return n}return null}async function Ue(e){if(await ze()){let n=await vt(e);if(n)return n}return fe(e)}function je(e){if(!e.file)return null;let t=e.file;return e.line!=null&&(t+=":"+e.line),e.column!=null&&(t+=":"+e.column),t}var Ke=(e,t)=>e.length>t?e.slice(0,t)+"\u2026":e,ge=e=>fe(e)?.component??null,Lt=e=>{let t=e.tagName.toLowerCase(),n=e instanceof HTMLElement?e.innerText?.trim()??e.textContent?.trim()??"":e.textContent?.trim()??"",o="";for(let{name:r,value:s}of e.attributes)o+=` ${r}="${Ke(s,$e)}"`;let i=Ke(n,Xe);return i.length>0?`<${t}${o}>
2
+ ${i}
3
+ </${t}>`:`<${t}${o} />`},te=async e=>{let t=Lt(e),n=Ye(e),o=await Ue(e),i=o?.component??null,r=o?je(o):null,s=o?.file?{file:o.file,line:o.line??void 0,column:o.column??void 0}:void 0,a=r?`src: ${r}`:"";return{html:t,stack:a,component:i,selector:n,source:s}},ne=e=>{let t=[];if(e.component?t.push(`<${e.component}> (${e.html.match(/^<(\w+)/)?.[1]??"?"})`):t.push(e.html.split(`
4
+ `)[0]),e.source?.file){let n=e.source.file;e.source.line&&(n+=`:${e.source.line}`),e.source.column&&(n+=`:${e.source.column}`),t.push(`src: ${n}`)}return t.push(`sel: ${e.selector}`),t.push("Live ref: window.__LAST_GRABBED__.element"),t.join(`
5
+ `)};var Ze=async(e,t)=>{let n=new URLSearchParams({file:e});t&&n.set("line",String(t)),n.set("column","1");try{if((await fetch(`/__open-in-editor?${n}`)).ok)return}catch{}try{let i=new URLSearchParams({file:e});if(t&&i.set("line1",String(t)),i.set("column1","1"),(await fetch(`/__nextjs_launch-editor?${i}`)).ok)return}catch{}let o=t?`:${t}`:"";window.open(`vscode://file/${e}${o}`,"_blank","noopener,noreferrer")};function qe(e,t){let n=document.createElement("div");n.className="eg-label",n.style.display="none",e.appendChild(n);let o=document.createElement("div");o.className="eg-arrow";let i=document.createElement("div");i.className="eg-panel",i.style.padding="6px 8px";let r=document.createElement("div");r.className="eg-tag";let s=document.createElement("span");s.className="eg-tag-name";let a=document.createElement("span");a.className="eg-tag-component";let p=document.createElement("span");p.className="eg-tag-suffix",s.appendChild(a),s.appendChild(p),r.appendChild(s),i.appendChild(r),n.appendChild(o),n.appendChild(i);let d={visible:!1,tagName:"",bounds:null,mouseX:0,status:"hovering"},f="none",m=()=>{let c=d.bounds;if(!c)return;let x=n.offsetWidth||100,v=n.offsetHeight||30,b=Math.max(ke,Math.min(de,x*He)),y=window.visualViewport?.width??window.innerWidth,I=window.visualViewport?.height??window.innerHeight,E=window.visualViewport?.offsetLeft??0,re=window.visualViewport?.offsetTop??0,$=d.mouseX||c.x+c.width/2,F=0,C=x/2;$+C>E+y-T&&(F=E+y-T-($+C)),$-C+F<E+T&&(F=E+T-($-C));let V=c.y+c.height+b+O,ct=V+v<=re+I-T,we="bottom";ct||(V=c.y-v-b-O,we="top"),V<re+T&&(V=re+T);let dt=C-F,pt=Math.min(pe,C),ut=Math.max(x-pe,C),mt=Math.max(pt,Math.min(ut,dt))-C;n.style.top=`${V}px`,n.style.left=`${$}px`,n.style.transform=`translateX(calc(-50% + ${F}px))`,n.style.zIndex=String(ue),n.style.opacity=d.status==="fading"?"0":"1",n.style.pointerEvents=d.status==="frozen"||d.status==="copying"?"auto":"none",o.style.left=`calc(${Be}% + ${mt}px)`,we==="bottom"?(o.style.top="0",o.style.bottom="",o.style.transform="translateX(-50%) translateY(-100%)",o.style.borderBottom=`${b}px solid white`,o.style.borderTop=""):(o.style.top="",o.style.bottom="0",o.style.transform="translateX(-50%) translateY(100%)",o.style.borderTop=`${b}px solid white`,o.style.borderBottom=""),o.style.borderLeft=`${b}px solid transparent`,o.style.borderRight=`${b}px solid transparent`},w=()=>{d.componentName?(a.textContent=d.componentName,p.textContent=`.${d.tagName}`):(a.textContent=d.tagName,p.textContent="")},S=()=>{f!=="hover"&&(f="hover",n.innerHTML="",i.innerHTML="",i.style.padding="6px 8px",i.className="eg-panel animate-pop-in",i.appendChild(r),n.appendChild(o),n.appendChild(i))},l=()=>{f="frozen",n.innerHTML="",i.innerHTML="",i.style.padding="0",i.className="eg-panel";let c=document.createElement("div");Object.assign(c.style,{display:"flex",flexDirection:"column",alignItems:"flex-start",minWidth:"150px",maxWidth:"280px"});let x=document.createElement("div");Object.assign(x.style,{display:"flex",alignItems:"center",gap:"4px",padding:"6px 8px 4px 8px"}),x.appendChild(r),c.appendChild(x);let v=document.createElement("div");v.className="eg-bottom-section";let b=document.createElement("div");Object.assign(b.style,{display:"flex",justifyContent:"space-between",alignItems:"flex-end",width:"100%",minHeight:"16px"});let y=document.createElement("textarea");y.className="eg-input",y.placeholder="Add context",y.rows=1,y.style.maxHeight=`${Fe}px`,queueMicrotask(()=>y.focus({preventScroll:!0})),y.addEventListener("keydown",E=>{E.stopImmediatePropagation(),E.code==="Enter"&&!E.shiftKey?(E.preventDefault(),t.onsubmit(y.value)):E.code==="Escape"&&(E.preventDefault(),t.ondismiss())});let I=document.createElement("button");I.className="eg-circle-btn eg-interactive-scale",I.setAttribute("aria-label","Submit"),I.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="white" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>',I.addEventListener("click",E=>{E.stopImmediatePropagation(),t.onsubmit(y.value)}),b.appendChild(y),b.appendChild(I),v.appendChild(b),c.appendChild(v),i.appendChild(c),n.appendChild(o),n.appendChild(i)},A=()=>{f="copying",n.innerHTML="",i.innerHTML="",i.style.padding="6px 8px",i.className="eg-panel";let c=document.createElement("span");c.className="eg-status shimmer-text",c.textContent="Grabbing\u2026",i.appendChild(c),n.appendChild(o),n.appendChild(i)},u=()=>{f="copied",n.innerHTML="",i.innerHTML="",i.style.padding="6px 8px",i.className="eg-panel animate-success-pop";let c=document.createElement("span");c.className="eg-status",c.style.color="black",c.textContent="Copied",i.appendChild(c),n.appendChild(o),n.appendChild(i)},g=()=>{if(!d.visible||!d.bounds){n.style.display="none";return}switch(n.style.display="",d.status){case"hovering":S(),w();break;case"frozen":f!=="frozen"&&(l(),w());break;case"copying":f!=="copying"&&A();break;case"copied":f!=="copied"&&u();break}m()};return{update(c){let x=c.tagName!==void 0&&c.tagName!==d.tagName,v=c.componentName!==void 0&&c.componentName!==d.componentName;if(Object.assign(d,c),d.status==="hovering"&&f==="hover"&&d.visible&&d.bounds){(x||v)&&w(),m();return}g()},hide(){d.visible=!1,d.status="hovering",f="none",n.style.display="none"},getPromptValue(){return n.querySelector("textarea")?.value?.trim()||""}}}function Je(e,t){let n="element-grab-toolbar",r="right",s=.5,a=!1,p=0,d=0,f=!1;try{let l=JSON.parse(localStorage.getItem(n)||"{}");l.edge&&(r=l.edge),typeof l.ratio=="number"&&(s=l.ratio)}catch{}let m=document.createElement("div");m.className="eg-toolbar-pill",m.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3l7.07 16.97 2.51-7.39 7.39-2.51L3 3z"/><path d="M13 13l6 6"/></svg><div class="eg-toolbar-dot" style="display:none"></div>',e.appendChild(m);let w=m.querySelector(".eg-toolbar-dot"),S=()=>{let l=window.innerWidth,A=window.innerHeight,u=me,g,c;switch(r){case"right":g=l-40-u,c=u+s*(A-32-2*u);break;case"left":g=u,c=u+s*(A-32-2*u);break;case"top":g=u+s*(l-40-2*u),c=u;break;case"bottom":g=u+s*(l-40-2*u),c=A-32-u;break}m.style.left=`${g}px`,m.style.top=`${c}px`};return m.addEventListener("pointerdown",l=>{a=!0,f=!1,p=l.clientX,d=l.clientY;try{m.setPointerCapture(l.pointerId)}catch{}l.preventDefault()}),m.addEventListener("pointermove",l=>{if(!a)return;(Math.abs(l.clientX-p)>5||Math.abs(l.clientY-d)>5)&&(f=!0);let A=window.innerWidth,u=window.innerHeight,g=me,c=A-l.clientX,x=l.clientX,v=l.clientY,b=u-l.clientY,y=Math.min(c,x,v,b);r=y===c?"right":y===x?"left":y===v?"top":"bottom",s=r==="left"||r==="right"?Math.max(0,Math.min(1,(l.clientY-g)/(u-2*g))):Math.max(0,Math.min(1,(l.clientX-g)/(A-2*g))),S()}),m.addEventListener("pointerup",l=>{if(a){a=!1;try{m.releasePointerCapture(l.pointerId)}catch{}try{localStorage.setItem(n,JSON.stringify({edge:r,ratio:s}))}catch{}f||t.ontoggle()}}),S(),{setActive(l){m.classList.toggle("active",l),w.style.display=l?"":"none"},destroy(){m.remove()}}}function Qe(e){let t=document.createElement("div");t.className="eg-label",t.style.display="none",t.style.pointerEvents="auto",e.appendChild(t);let n=null,o=a=>{a.key==="Escape"&&(a.preventDefault(),s())},i=a=>{t.contains(a.target)||s()},r=a=>{n=a.ondismiss;let p=a.componentName?`<span class="eg-tag-component">${B(a.componentName)}</span><span class="eg-tag-suffix">.${B(a.tagName)}</span>`:`<span class="eg-tag-component">${B(a.tagName)}</span>`,d=a.actions.map(l=>`<button class="eg-menu-item" data-action="${B(l.label)}">${B(l.label)}${l.shortcut?`<span class="eg-menu-item-shortcut">${B(l.shortcut)}</span>`:""}</button>`).join("");t.innerHTML=`<div class="eg-panel" style="flex-direction:column;align-items:flex-start;min-width:100px;padding:0"><div style="display:flex;align-items:center;gap:4px;padding:6px 8px 4px 8px"><span class="eg-tag-name">${p}</span></div><div class="eg-bottom-section" style="padding:4px 0">${d}</div></div>`;let f=de,m=Math.max(O,Math.min(a.position.x-60,window.innerWidth-140)),w=a.bounds.y+a.bounds.height+f+O;t.style.display="";let S=t.offsetHeight;w+S>window.innerHeight&&(w=a.bounds.y-S-f-O),w<O&&(w=O),t.style.left=`${m}px`,t.style.top=`${w}px`,t.style.zIndex=String(ue),t.querySelectorAll(".eg-menu-item").forEach(l=>{let A=l.getAttribute("data-action"),u=a.actions.find(g=>g.label===A);l.addEventListener("click",g=>{g.stopImmediatePropagation(),u?.action(),s()})}),window.addEventListener("keydown",o,!0),window.addEventListener("pointerdown",i,!0)},s=()=>{t.style.display="none",t.innerHTML="",window.removeEventListener("keydown",o,!0),window.removeEventListener("pointerdown",i,!0),n?.(),n=null};return{show:r,hide:s}}var B=e=>e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;");var et=`:host {
6
+ all: initial;
7
+ direction: ltr;
8
+ }
9
+
10
+ @keyframes shake {
11
+ 0%, 100% { transform: translateX(0); }
12
+ 15% { transform: translateX(-3px); }
13
+ 30% { transform: translateX(3px); }
14
+ 45% { transform: translateX(-3px); }
15
+ 60% { transform: translateX(3px); }
16
+ 75% { transform: translateX(-2px); }
17
+ 90% { transform: translateX(2px); }
18
+ }
19
+
20
+ @keyframes pop-in {
21
+ 0% { opacity: 0; transform: scale(0.9); }
22
+ 70% { opacity: 1; transform: scale(1.02); }
23
+ 100% { opacity: 1; transform: scale(1); }
24
+ }
25
+
26
+ @keyframes pop-out {
27
+ from { opacity: 1; transform: scale(1); }
28
+ to { opacity: 0; transform: scale(0.95); }
29
+ }
30
+
31
+ @keyframes slide-in-bottom {
32
+ from { opacity: 0; transform: translateY(8px); }
33
+ to { opacity: 1; transform: translateY(0); }
34
+ }
35
+
36
+ @keyframes slide-in-top {
37
+ from { opacity: 0; transform: translateY(-8px); }
38
+ to { opacity: 1; transform: translateY(0); }
39
+ }
40
+
41
+ @keyframes success-pop {
42
+ 0% { transform: scale(0.9); opacity: 0; }
43
+ 60% { transform: scale(1.1); opacity: 1; }
44
+ 80% { transform: scale(0.95); }
45
+ 100% { transform: scale(1); opacity: 1; }
46
+ }
47
+
48
+ @keyframes icon-loader-spin {
49
+ 0% { opacity: 1; }
50
+ 50% { opacity: 0.5; }
51
+ 100% { opacity: 0.2; }
52
+ }
53
+
54
+ @keyframes shimmer {
55
+ 0% { background-position: 200% 0; }
56
+ 100% { background-position: -200% 0; }
57
+ }
58
+
59
+ @keyframes tooltip-fade-in {
60
+ from { opacity: 0; transform: scale(0.97); }
61
+ to { opacity: 1; transform: scale(1); }
62
+ }
63
+
64
+ .icon-loader-bar {
65
+ animation: icon-loader-spin 0.5s linear infinite;
66
+ }
67
+
68
+ .shimmer-text {
69
+ background: linear-gradient(90deg, #71717a 0%, #a1a1aa 25%, #71717a 50%, #a1a1aa 75%, #71717a 100%);
70
+ background-size: 200% 100%;
71
+ -webkit-background-clip: text;
72
+ background-clip: text;
73
+ color: transparent;
74
+ animation: shimmer 2.5s linear infinite;
75
+ }
76
+
77
+ .animate-shake { animation: shake 0.3s ease-out; will-change: transform; }
78
+ .animate-pop-in { animation: pop-in 150ms ease-out; will-change: transform, opacity; }
79
+ .animate-pop-out { animation: pop-out 150ms ease-out forwards; will-change: transform, opacity; }
80
+ .animate-slide-in-bottom { animation: slide-in-bottom 200ms ease-out; will-change: transform, opacity; }
81
+ .animate-slide-in-top { animation: slide-in-top 200ms ease-out; will-change: transform, opacity; }
82
+ .animate-success-pop { animation: success-pop 250ms ease-out; will-change: transform, opacity; }
83
+ .animate-tooltip-fade-in { animation: tooltip-fade-in 100ms ease-out; will-change: transform, opacity; }
84
+
85
+ /* --- Base styles for element-grab UI --- */
86
+
87
+ .eg-label {
88
+ position: fixed;
89
+ font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
90
+ font-size: 13px;
91
+ font-weight: 500;
92
+ -webkit-font-smoothing: antialiased;
93
+ -moz-osx-font-smoothing: grayscale;
94
+ filter: drop-shadow(0px 1px 2px #51515140);
95
+ user-select: none;
96
+ z-index: 2147483647;
97
+ transition: opacity 100ms ease-out;
98
+ }
99
+
100
+ .eg-panel {
101
+ display: flex;
102
+ align-items: center;
103
+ gap: 5px;
104
+ background: white;
105
+ border-radius: 10px;
106
+ padding: 0;
107
+ width: fit-content;
108
+ height: fit-content;
109
+ font-synthesis: none;
110
+ /* superellipse corners \u2014 degrades gracefully */
111
+ corner-shape: superellipse(1.25);
112
+ }
113
+
114
+ .eg-tag {
115
+ display: flex;
116
+ align-items: center;
117
+ gap: 4px;
118
+ max-width: 280px;
119
+ overflow: hidden;
120
+ flex-shrink: 0;
121
+ }
122
+
123
+ .eg-tag-name {
124
+ font-size: 13px;
125
+ line-height: 16px;
126
+ font-weight: 500;
127
+ overflow: hidden;
128
+ text-overflow: ellipsis;
129
+ white-space: nowrap;
130
+ min-width: 0;
131
+ }
132
+
133
+ .eg-tag-component { color: black; }
134
+ .eg-tag-suffix { color: rgba(0,0,0,0.5); }
135
+
136
+ .eg-tag-open-icon {
137
+ color: black;
138
+ transition: all 100ms;
139
+ flex-shrink: 0;
140
+ }
141
+
142
+ .eg-tag-open-icon.visible { opacity: 1; transform: scale(1); }
143
+ .eg-tag-open-icon.hidden { opacity: 0; transform: scale(0.75); margin-left: -2px; width: 0; }
144
+
145
+ .eg-bottom-section {
146
+ font-synthesis: none;
147
+ flex-shrink: 0;
148
+ display: flex;
149
+ flex-direction: column;
150
+ align-items: flex-start;
151
+ padding: 6px 8px;
152
+ width: auto;
153
+ height: fit-content;
154
+ align-self: stretch;
155
+ border-top: 0.5px solid #D9D9D9;
156
+ -webkit-font-smoothing: antialiased;
157
+ border-radius: 0 0 6px 6px;
158
+ }
159
+
160
+ .eg-arrow {
161
+ position: absolute;
162
+ width: 0;
163
+ height: 0;
164
+ z-index: 10;
165
+ }
166
+
167
+ /* Interactive utilities */
168
+ .eg-interactive-scale {
169
+ transition: transform 150ms cubic-bezier(0.34, 1.56, 0.64, 1);
170
+ }
171
+ .eg-interactive-scale:hover { transform: scale(1.05); }
172
+ .eg-interactive-scale:active { transform: scale(0.97); }
173
+
174
+ .eg-press-scale {
175
+ transition: transform 100ms ease-out;
176
+ }
177
+ .eg-press-scale:active { transform: scale(0.97); }
178
+
179
+ /* Prompt input */
180
+ .eg-input {
181
+ color: black;
182
+ font-size: 13px;
183
+ line-height: 16px;
184
+ font-weight: 500;
185
+ background: transparent;
186
+ border: none;
187
+ outline: none;
188
+ resize: none;
189
+ flex: 1;
190
+ padding: 0;
191
+ margin: 0;
192
+ overflow-wrap: break-word;
193
+ overflow-y: auto;
194
+ field-sizing: content;
195
+ min-height: 16px;
196
+ scrollbar-width: none;
197
+ }
198
+
199
+ .eg-input::placeholder { color: rgba(0,0,0,0.4); }
200
+
201
+ /* Submit/abort buttons */
202
+ .eg-circle-btn {
203
+ flex-shrink: 0;
204
+ display: flex;
205
+ align-items: center;
206
+ justify-content: center;
207
+ width: 16px;
208
+ height: 16px;
209
+ border-radius: 50%;
210
+ background: black;
211
+ cursor: pointer;
212
+ margin-left: 4px;
213
+ border: none;
214
+ padding: 0;
215
+ }
216
+
217
+ /* Status text with shimmer */
218
+ .eg-status {
219
+ font-size: 13px;
220
+ line-height: 16px;
221
+ font-weight: 500;
222
+ height: fit-content;
223
+ font-variant-numeric: tabular-nums;
224
+ overflow: hidden;
225
+ text-overflow: ellipsis;
226
+ white-space: nowrap;
227
+ }
228
+
229
+ /* Context menu */
230
+ .eg-menu-item {
231
+ position: relative;
232
+ z-index: 1;
233
+ display: flex;
234
+ align-items: center;
235
+ justify-content: space-between;
236
+ width: 100%;
237
+ padding: 4px 8px;
238
+ cursor: pointer;
239
+ text-align: left;
240
+ border: none;
241
+ background: transparent;
242
+ font-size: 13px;
243
+ line-height: 16px;
244
+ font-weight: 500;
245
+ color: black;
246
+ }
247
+
248
+ .eg-menu-item:disabled { opacity: 0.4; cursor: default; }
249
+ .eg-menu-item-shortcut { font-size: 11px; color: rgba(0,0,0,0.5); margin-left: 16px; }
250
+
251
+ /* Toolbar pill */
252
+ .eg-toolbar-pill {
253
+ position: fixed;
254
+ pointer-events: auto;
255
+ cursor: grab;
256
+ display: flex;
257
+ align-items: center;
258
+ justify-content: center;
259
+ gap: 4px;
260
+ width: 40px;
261
+ height: 32px;
262
+ background: white;
263
+ border-radius: 10px;
264
+ box-shadow: 0 1px 4px rgba(0,0,0,0.15), 0 0 0 0.5px rgba(0,0,0,0.06);
265
+ transition: background 150ms ease, box-shadow 150ms ease, transform 150ms ease;
266
+ user-select: none;
267
+ -webkit-user-select: none;
268
+ touch-action: none;
269
+ color: rgba(0,0,0,0.5);
270
+ }
271
+ .eg-toolbar-pill:hover {
272
+ box-shadow: 0 2px 8px rgba(0,0,0,0.18), 0 0 0 0.5px rgba(0,0,0,0.08);
273
+ color: rgba(0,0,0,0.8);
274
+ transform: scale(1.05);
275
+ }
276
+ .eg-toolbar-pill:active { transform: scale(0.97); }
277
+ .eg-toolbar-pill.active {
278
+ background: #6366f1;
279
+ color: white;
280
+ box-shadow: 0 2px 8px rgba(99,102,241,0.4), 0 0 0 0.5px rgba(99,102,241,0.3);
281
+ }
282
+ .eg-toolbar-pill.active:hover {
283
+ background: #5558e6;
284
+ box-shadow: 0 2px 12px rgba(99,102,241,0.5), 0 0 0 0.5px rgba(99,102,241,0.4);
285
+ }
286
+ .eg-toolbar-dot {
287
+ width: 6px;
288
+ height: 6px;
289
+ border-radius: 50%;
290
+ background: white;
291
+ opacity: 0.8;
292
+ flex-shrink: 0;
293
+ }
294
+
295
+ .eg-menu-highlight {
296
+ pointer-events: none;
297
+ position: absolute;
298
+ background: rgba(0,0,0,0.05);
299
+ opacity: 0;
300
+ transition: top 75ms ease-out, left 75ms ease-out, width 75ms ease-out, height 75ms ease-out, opacity 75ms ease-out;
301
+ }
302
+ `;var L=!1,_=null,j=null,h=null,M=null,be="",N=null,X=null,oe=null,D=null,Rt=e=>{let t=e.getRootNode();return!!(t instanceof ShadowRoot&&t.host.hasAttribute("data-element-grab")||e.hasAttribute?.("data-element-grab"))},tt=e=>{if(Rt(e)||e===document.body||e===document.documentElement)return!1;let t=e.getBoundingClientRect();if(t.width/window.innerWidth>.9&&t.height/window.innerHeight>.9){let n=getComputedStyle(e);if(n.pointerEvents==="none"||n.backgroundColor==="transparent"||n.backgroundColor==="rgba(0, 0, 0, 0)")return!1}return!0},Ot=(e,t)=>{let n=document.elementFromPoint(e,t);if(n&&tt(n))return n;let o=document.elementsFromPoint(e,t);for(let i of o)if(tt(i))return i;return null},ie=null,nt=0,ot=0,it=2,Ee=()=>{if(M)return;be=window.__WEBDEV_ORIGIN__||window.location.origin,M=ve(et),_=new ee(M),N=qe(M,{onsubmit:Tt,onopen:st,ondismiss:P});let e=()=>!!document.querySelector("vite-devtools-dock-embedded, vite-devtools-dock-standalone");if(!e()){X=Je(M,{ontoggle:()=>{L?P():xe()}});let t=new MutationObserver(()=>{X&&e()&&(X.destroy(),X=null,t.disconnect())});t.observe(document.documentElement,{childList:!0,subtree:!0})}oe=Qe(M),D=document.createElement("div"),Object.assign(D.style,{position:"fixed",top:"0",right:"0",bottom:"0",left:"0",pointerEvents:"none",zIndex:String(q),opacity:"0",transition:`opacity ${le}ms ease-out`,willChange:"opacity",contain:"strict",transform:"translateZ(0)",boxShadow:`inset 0 0 ${Pe}px ${De}`}),M.appendChild(D),document.addEventListener("contextmenu",t=>{if(!h||!oe)return;t.preventDefault();let n=h.getBoundingClientRect();oe.show({position:{x:t.clientX,y:t.clientY},bounds:{x:n.x,y:n.y,width:n.width,height:n.height},tagName:h.tagName.toLowerCase(),componentName:ge(h)||void 0,actions:[{label:"Copy",shortcut:"\u2318C",action:()=>{let o=window.__LAST_GRABBED__?.card;o&&navigator.clipboard.writeText(o).catch(()=>{})}},{label:"Copy HTML",action:()=>{h&&navigator.clipboard.writeText(h.outerHTML).catch(()=>{})}},{label:"Copy Styles",action:()=>{if(!h)return;let o=getComputedStyle(h),i=Array.from(o).filter(r=>o.getPropertyValue(r)!=="").map(r=>`${r}: ${o.getPropertyValue(r)};`).join(`
303
+ `);navigator.clipboard.writeText(i).catch(()=>{})}},{label:"Open in editor",shortcut:"\u2318O",action:st}],ondismiss:()=>{}})},!0),console.log("[element-grab] Ready \u2014 hold Cmd+Shift+C to activate")},_e=e=>{let t=e.getBoundingClientRect(),n=getComputedStyle(e);return{x:t.x,y:t.y,width:t.width,height:t.height,borderRadius:n.borderRadius||"0"}},rt=0,at=e=>{if(!L||h)return;let t=Date.now();if(t-rt<Ce||(rt=t,ie&&Math.abs(e.clientX-nt)<it&&Math.abs(e.clientY-ot)<it))return;nt=e.clientX,ot=e.clientY;let n=Ot(e.clientX,e.clientY);if(!n)return;ie=n,j=n;let o=_e(n);_&&(_.selectionVisible=!0,_.selectionFading=!1,_.setSelection(o)),N?.update({visible:!0,tagName:n.tagName.toLowerCase(),componentName:ge(n)||void 0,bounds:{x:o.x,y:o.y,width:o.width,height:o.height},mouseX:e.clientX,status:"hovering"})},lt=async e=>{if(!L||!j)return;e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation();let t=j;h=t,D&&(D.style.opacity="1");let n=_e(t);N?.update({status:"frozen",bounds:{x:n.x,y:n.y,width:n.width,height:n.height}});let o=await te(t),i=ne(o);window.__LAST_GRABBED__={element:t,selector:o.selector,component:o.component,source:o.source,card:i}},Tt=async e=>{if(!h)return;let t=e?.trim()||N?.getPromptValue()||"";N?.update({status:"copying"});let n=await te(h),o=ne(n);t&&(o+=`
304
+ prompt: ${t}`),window.__LAST_GRABBED__={element:h,selector:n.selector,component:n.component,source:n.source,card:o};try{await fetch(`${be}/__element-grab/selection`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({payload:{card:o,timestamp:Date.now(),url:window.location.href},browserId:sessionStorage.getItem("__webdev_browser_id__")})})}catch{}try{await navigator.clipboard.writeText(o)}catch{}_&&_.addGrabbed(`grab-${Date.now()}`,_e(h)),N?.update({status:"copied"}),console.log(`[element-grab] Grabbed:
305
+ `+o),setTimeout(()=>{N?.update({status:"fading"}),setTimeout(()=>P(),le)},H)},st=()=>{let e=window.__LAST_GRABBED__;e?.source?.file&&Ze(e.source.file,e.source.line)},xe=()=>{L||(Ee(),L=!0,h=null,ie=null,document.addEventListener("mousemove",at,!0),document.addEventListener("click",lt,!0),document.body.style.cursor="crosshair",_&&(_.selectionVisible=!0,_.selectionFading=!1),X?.setActive(!0))},P=()=>{L=!1,j=null,h=null,ie=null,document.removeEventListener("mousemove",at,!0),document.removeEventListener("click",lt,!0),document.body.style.cursor="",_&&(_.selectionVisible=!1,_.setSelection(null)),N?.hide(),oe?.hide(),X?.setActive(!1),D&&(D.style.opacity="0")},ye=!1,Nt=e=>{if(e.key==="Meta"||e.key==="Control"){ye=!0;return}ye&&e.key.toLowerCase()===Ae&&(!Le||e.shiftKey)&&(e.preventDefault(),L||xe()),e.key==="Escape"&&L&&(e.preventDefault(),P())},St=e=>{(e.key==="Meta"||e.key==="Control")&&(ye=!1,L&&!h&&P())};document.addEventListener("keydown",Nt,!0);document.addEventListener("keyup",St,!0);Ee();window.__elementGrab={activate:xe,deactivate:P,isActive:()=>L,async grabBySelector(e){Ee();let t=document.querySelector(e);if(!t)return null;j=t,h=t;let n=await te(t),o=ne(n);window.__LAST_GRABBED__={element:t,selector:n.selector,component:n.component,source:n.source,card:o};try{await fetch(`${be}/__element-grab/selection`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({payload:{card:o,timestamp:Date.now(),url:window.location.href},browserId:sessionStorage.getItem("__webdev_browser_id__")})})}catch{}return P(),o}};})();
@@ -0,0 +1,15 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { IncomingMessage, ServerResponse } from 'node:http';
3
+ interface ElementSelection {
4
+ card: string;
5
+ timestamp: number;
6
+ url: string;
7
+ browserId?: string;
8
+ }
9
+ export declare function pushSelection(sel: ElementSelection): void;
10
+ export declare function getLatestSelection(): ElementSelection | null;
11
+ export declare function getAllSelections(): ElementSelection[];
12
+ export declare function registerElementGrabTool(mcp: McpServer): void;
13
+ export declare function handleElementGrabRequest(req: IncomingMessage, res: ServerResponse, url: string): boolean;
14
+ export {};
15
+ //# sourceMappingURL=element-grab.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"element-grab.d.ts","sourceRoot":"","sources":["../src/element-grab.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACxE,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAIhE,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAaD,wBAAgB,aAAa,CAAC,GAAG,EAAE,gBAAgB,QAIlD;AAED,wBAAgB,kBAAkB,IAAI,gBAAgB,GAAG,IAAI,CAG5D;AAED,wBAAgB,gBAAgB,IAAI,gBAAgB,EAAE,CAGrD;AAGD,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,SAAS,QAiCrD;AAGD,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CA+CxG"}