@@ -29,11 +29,36 @@ class ClaudeDevTools {
2929 ( document . head || document . documentElement ) . appendChild ( script ) ;
3030 }
3131
32+ injectPickerStyles ( ) {
33+ this . pickerStyle = document . createElement ( "style" ) ;
34+ this . pickerStyle . id = "claude-devtools-picker-style" ;
35+ this . pickerStyle . textContent = `
36+ *[disabled] {
37+ pointer-events: all !important;
38+ }
39+ button[disabled],
40+ input[disabled],
41+ select[disabled],
42+ textarea[disabled] {
43+ pointer-events: all !important;
44+ }
45+ ` ;
46+ document . head . appendChild ( this . pickerStyle ) ;
47+ }
48+
49+ removePickerStyles ( ) {
50+ if ( this . pickerStyle ) {
51+ this . pickerStyle . remove ( ) ;
52+ this . pickerStyle = null ;
53+ }
54+ }
55+
3256 startPicking ( ) {
3357 if ( this . isPicking ) return ;
3458
3559 this . isPicking = true ;
3660 this . createOverlay ( ) ;
61+ this . injectPickerStyles ( ) ;
3762 this . bindEvents ( ) ;
3863 }
3964
@@ -42,6 +67,7 @@ class ClaudeDevTools {
4267
4368 this . isPicking = false ;
4469 this . removeOverlay ( ) ;
70+ this . removePickerStyles ( ) ;
4571 this . unbindEvents ( ) ;
4672 this . clearHighlight ( ) ;
4773 }
@@ -90,11 +116,7 @@ class ClaudeDevTools {
90116 }
91117
92118 bindEvents ( ) {
93- document . addEventListener ( "mouseover" , this . handleMouseOver , {
94- capture : true ,
95- passive : false ,
96- } ) ;
97- document . addEventListener ( "mouseout" , this . handleMouseOut , {
119+ document . addEventListener ( "mousemove" , this . handleMouseMove , {
98120 capture : true ,
99121 passive : false ,
100122 } ) ;
@@ -106,8 +128,6 @@ class ClaudeDevTools {
106128 capture : true ,
107129 passive : false ,
108130 } ) ;
109-
110- // Only block interactions that interfere with element selection
111131 document . addEventListener ( "mousedown" , this . blockEvent , {
112132 capture : true ,
113133 passive : false ,
@@ -124,16 +144,10 @@ class ClaudeDevTools {
124144 capture : true ,
125145 passive : false ,
126146 } ) ;
127- // Don't block wheel - allow scrolling
128- // Don't block touch events - allow mobile interaction
129147 }
130148
131149 unbindEvents ( ) {
132- document . removeEventListener ( "mouseover" , this . handleMouseOver , {
133- capture : true ,
134- passive : false ,
135- } ) ;
136- document . removeEventListener ( "mouseout" , this . handleMouseOut , {
150+ document . removeEventListener ( "mousemove" , this . handleMouseMove , {
137151 capture : true ,
138152 passive : false ,
139153 } ) ;
@@ -145,8 +159,6 @@ class ClaudeDevTools {
145159 capture : true ,
146160 passive : false ,
147161 } ) ;
148-
149- // Remove blocked event listeners
150162 document . removeEventListener ( "mousedown" , this . blockEvent , {
151163 capture : true ,
152164 passive : false ,
@@ -165,39 +177,42 @@ class ClaudeDevTools {
165177 } ) ;
166178 }
167179
168- handleMouseOver = async ( e ) => {
180+ handleMouseMove = async ( e ) => {
169181 if ( ! this . isPicking ) return ;
170182
171- // Skip our own elements
172- if ( this . isOurElement ( e . target ) ) return ;
173-
174183 e . stopPropagation ( ) ;
175184 e . preventDefault ( ) ;
176185
177- await this . highlightElement ( e . target ) ;
178- } ;
179-
180- handleMouseOut = ( e ) => {
181- if ( ! this . isPicking ) return ;
186+ const instructionsRect = this . instructions . getBoundingClientRect ( ) ;
187+ const isNearInstructions =
188+ e . clientY >= instructionsRect . top - 50 &&
189+ e . clientY <= instructionsRect . bottom + 20 &&
190+ e . clientX >= instructionsRect . left - 50 &&
191+ e . clientX <= instructionsRect . right + 50 ;
192+
193+ if ( isNearInstructions ) {
194+ this . instructions . style . opacity = "0.2" ;
195+ } else {
196+ this . instructions . style . opacity = "1" ;
197+ }
182198
183- // Skip our own elements
184- if ( this . isOurElement ( e . target ) ) return ;
199+ const element = this . getElementFromPoint ( e . clientX , e . clientY ) ;
200+ if ( ! element ) return ;
185201
186- e . stopPropagation ( ) ;
187- e . preventDefault ( ) ;
188- this . clearHighlight ( ) ;
202+ if ( element !== this . currentElement ) {
203+ await this . highlightElement ( element ) ;
204+ }
189205 } ;
190206
191207 handleClick = async ( e ) => {
192208 if ( ! this . isPicking ) return ;
193209
194- // Skip our own elements
195- if ( this . isOurElement ( e . target ) ) return ;
196-
197210 e . stopPropagation ( ) ;
198211 e . preventDefault ( ) ;
199212
200- const element = e . target ;
213+ const element = this . getElementFromPoint ( e . clientX , e . clientY ) ;
214+ if ( ! element ) return ;
215+
201216 await this . selectElement ( element ) ;
202217 } ;
203218
@@ -214,22 +229,23 @@ class ClaudeDevTools {
214229
215230 blockEvent = ( e ) => {
216231 if ( ! this . isPicking ) return ;
217- if ( this . isOurElement ( e . target ) ) return ;
218232 e . stopPropagation ( ) ;
219233 e . preventDefault ( ) ;
220234 } ;
221235
222- isOurElement ( element ) {
223- return (
224- element === this . overlay ||
225- element === this . instructions ||
226- element === this . highlighter ||
227- element === this . label ||
228- element . closest ( ".claude-devtools-overlay" ) ||
229- element . closest ( ".claude-devtools-instructions" ) ||
230- element . closest ( ".claude-devtools-highlighter" ) ||
231- element . closest ( ".claude-devtools-label" )
232- ) ;
236+ getElementFromPoint ( x , y ) {
237+ const elements = document . elementsFromPoint ( x , y ) ;
238+ for ( const element of elements ) {
239+ if (
240+ element !== this . overlay &&
241+ element !== this . instructions &&
242+ element !== this . highlighter &&
243+ element !== this . label
244+ ) {
245+ return element ;
246+ }
247+ }
248+ return null ;
233249 }
234250
235251 async highlightElement ( element ) {
@@ -324,8 +340,7 @@ class ClaudeDevTools {
324340
325341 setTimeout ( ( ) => {
326342 window . removeEventListener ( "message" , handleMessage ) ;
327- // element.removeAttribute('data-claude-devtools-id');
328- resolve ( this . getFallbackComponentInfo ( element ) ) ;
343+ resolve ( null ) ;
329344 } , 500 ) ;
330345 } ) ;
331346 }
@@ -336,10 +351,6 @@ class ClaudeDevTools {
336351 ) ;
337352 }
338353
339- getFallbackComponentInfo ( ) {
340- return null ;
341- }
342-
343354 getElementHTML ( element ) {
344355 const clone = element . cloneNode ( true ) ;
345356 this . removeUnwantedAttributes ( clone ) ;
@@ -475,58 +486,6 @@ class ClaudeDevTools {
475486 }
476487 }
477488
478- async createPlaceholderImage ( rect , tagName ) {
479- return new Promise ( ( resolve ) => {
480- // Create a simple canvas-based placeholder that won't cause taint issues
481- const canvas = document . createElement ( "canvas" ) ;
482- const ctx = canvas . getContext ( "2d" ) ;
483-
484- // Limit canvas size to reasonable dimensions
485- const maxWidth = Math . min ( rect . width , 400 ) ;
486- const maxHeight = Math . min ( rect . height , 300 ) ;
487-
488- canvas . width = maxWidth ;
489- canvas . height = maxHeight ;
490-
491- // Create a gradient background
492- const gradient = ctx . createLinearGradient ( 0 , 0 , maxWidth , maxHeight ) ;
493- gradient . addColorStop ( 0 , "#f8f9fa" ) ;
494- gradient . addColorStop ( 1 , "#e9ecef" ) ;
495-
496- ctx . fillStyle = gradient ;
497- ctx . fillRect ( 0 , 0 , maxWidth , maxHeight ) ;
498-
499- // Add border
500- ctx . strokeStyle = "#dee2e6" ;
501- ctx . lineWidth = 2 ;
502- ctx . strokeRect ( 1 , 1 , maxWidth - 2 , maxHeight - 2 ) ;
503-
504- // Add element info text
505- ctx . fillStyle = "#495057" ;
506- ctx . font =
507- "16px -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif" ;
508- ctx . textAlign = "center" ;
509- ctx . textBaseline = "middle" ;
510-
511- const text = `<${ tagName . toLowerCase ( ) } >` ;
512- ctx . fillText ( text , maxWidth / 2 , maxHeight / 2 - 10 ) ;
513-
514- // Add dimensions text
515- ctx . font = "12px monospace" ;
516- ctx . fillStyle = "#6c757d" ;
517- const dimText = `${ Math . round ( rect . width ) } ×${ Math . round ( rect . height ) } px` ;
518- ctx . fillText ( dimText , maxWidth / 2 , maxHeight / 2 + 15 ) ;
519-
520- try {
521- const dataURL = canvas . toDataURL ( "image/png" ) ;
522- resolve ( dataURL ) ;
523- } catch ( error ) {
524- // If even this fails, return null
525- console . warn ( "Failed to create placeholder image:" , error ) ;
526- resolve ( null ) ;
527- }
528- } ) ;
529- }
530489}
531490
532491// Initialize
0 commit comments