@@ -40,10 +40,12 @@ export class LivematePanel extends ReactDevToolsViewBase {
4040
4141 this . contentElement . classList . add ( 'livemate-panel' ) ;
4242
43- const promptSection = this . contentElement . createChild (
44- 'div' ,
45- 'livemate-prompt-section'
46- ) ;
43+ const model = this . model ;
44+ if ( model === null ) {
45+ throw new Error ( 'Attempted to render React DevTools panel, but the model was null' ) ;
46+ }
47+
48+ const bridge = model . getBridgeOrThrow ( ) ;
4749
4850 // Create outer wrapper for centering
4951 const outerWrapper = document . createElement ( 'div' ) ;
@@ -53,26 +55,10 @@ export class LivematePanel extends ReactDevToolsViewBase {
5355 const toolbarContainer = document . createElement ( 'div' ) ;
5456 toolbarContainer . setAttribute ( 'style' , 'display: flex; flex-direction: column; padding: 20px; gap: 12px; max-width: 800px; width: 100%; margin: 0 20px; border: 1px solid var(--sys-color-divider); border-radius: 8px; background: var(--sys-color-surface);' ) ;
5557
56- // First row: Inspect button and breadcrumb
58+ // First row: breadcrumb
5759 const topRow = document . createElement ( 'div' ) ;
5860 topRow . setAttribute ( 'style' , 'display: flex; align-items: center; gap: 8px;' ) ;
5961
60- // Inspect button
61- const inspectButton = document . createElement ( 'button' ) ;
62- inspectButton . textContent = 'Inspect' ;
63- inspectButton . setAttribute ( 'style' , 'padding: 4px 12px; cursor: pointer;' ) ;
64- let isInspecting = false ;
65- inspectButton . addEventListener ( 'click' , ( ) => {
66- isInspecting = ! isInspecting ;
67- if ( isInspecting ) {
68- ( bridge as any ) . send ( 'startInspectingNative' ) ;
69- inspectButton . textContent = 'Stop Inspecting' ;
70- } else {
71- ( bridge as any ) . send ( 'stopInspectingNative' ) ;
72- inspectButton . textContent = 'Inspect' ;
73- }
74- } ) ;
75-
7662 // Breadcrumb view
7763 const breadcrumb = document . createElement ( 'div' ) ;
7864 breadcrumb . setAttribute ( 'style' , 'flex: 1; font-family: monospace; font-size: 12px; color: var(--sys-color-on-surface); display: flex; align-items: center; gap: 4px; flex-wrap: wrap;' ) ;
@@ -82,6 +68,9 @@ export class LivematePanel extends ReactDevToolsViewBase {
8268 selectedComponentBox . setAttribute ( 'style' , 'padding: 4px 8px; border: 1px solid var(--sys-color-divider); border-radius: 4px; background: var(--sys-color-surface-variant); font-family: monospace; font-size: 12px; color: var(--sys-color-on-surface);' ) ;
8369 selectedComponentBox . textContent = '' ;
8470
71+ // Track the current hierarchy for prompt context
72+ let currentHierarchy : Array < { name : string } > = [ ] ;
73+
8574 // Function to update breadcrumb with component data
8675 const updateBreadcrumb = ( components : Array < { name : string } > ) : void => {
8776 breadcrumb . innerHTML = '' ;
@@ -123,10 +112,10 @@ export class LivematePanel extends ReactDevToolsViewBase {
123112
124113 // Listen for component data from React DevTools
125114 bridge . addListener ( 'viewDataAtPoint' , ( data : unknown ) => {
126- updateBreadcrumb ( data as Array < { name : string } > ) ;
115+ currentHierarchy = data as Array < { name : string } > ;
116+ updateBreadcrumb ( currentHierarchy ) ;
127117 } ) ;
128118
129- topRow . appendChild ( inspectButton ) ;
130119 topRow . appendChild ( breadcrumb ) ;
131120 topRow . appendChild ( selectedComponentBox ) ;
132121
@@ -139,24 +128,41 @@ export class LivematePanel extends ReactDevToolsViewBase {
139128 queryInput . setAttribute ( 'placeholder' , 'Query to modify component...' ) ;
140129 queryInput . setAttribute ( 'style' , 'flex: 1; padding: 12px 16px; border: 1px solid var(--sys-color-divider); border-radius: 4px; background: var(--sys-color-cdt-base-container); color: var(--sys-color-on-surface); font-size: 14px; min-height: 100px; resize: vertical; font-family: inherit;' ) ;
141130
142- // Send to devmate button
143- const sendButton = document . createElement ( 'button' ) ;
144- sendButton . textContent = 'Send to Devmate' ;
145- sendButton . setAttribute ( 'style' , 'padding: 4px 12px; cursor: pointer; align-self: flex-end;' ) ;
146- sendButton . addEventListener ( 'click' , ( ) => {
131+ // Function to send query to Devmate
132+ const sendQueryToDevmate = ( ) : void => {
147133 const query = queryInput . value ;
148134 if ( query . trim ( ) ) {
149- console . log ( 'Sending to Devmate:' , query ) ;
150- // statusArea.textContent = 'Sending to Devmate...';
151- // statusArea.className = 'livemate-status pending';
135+ // Build the prompt with focused component and hierarchy information
136+ let prompt = query ;
137+ if ( currentHierarchy . length > 0 ) {
138+ // The focused component is the last item in the hierarchy (leaf node)
139+ const focusedComponent = currentHierarchy [ currentHierarchy . length - 1 ] . name ;
140+ const hierarchyStr = currentHierarchy . map ( c => c . name ) . join ( ' > ' ) ;
141+ prompt = `Focused component: ${ focusedComponent } \nComponent hierarchy: ${ hierarchyStr } \n\nQuery: ${ query } ` ;
142+ }
152143 (
153144 Host . InspectorFrontendHost . InspectorFrontendHostInstance as unknown as {
154145 sendToDevmate : ( prompt : string ) => void ,
155146 }
156- ) . sendToDevmate ( query ) ;
147+ ) . sendToDevmate ( prompt ) ;
148+ queryInput . value = '' ;
149+ }
150+ } ;
151+
152+ // Handle Enter key to send prompt (Shift+Enter for newline)
153+ queryInput . addEventListener ( 'keydown' , ( event : KeyboardEvent ) => {
154+ if ( event . key === 'Enter' && ! event . shiftKey ) {
155+ event . preventDefault ( ) ;
156+ sendQueryToDevmate ( ) ;
157157 }
158158 } ) ;
159159
160+ // Send to devmate button
161+ const sendButton = document . createElement ( 'button' ) ;
162+ sendButton . textContent = 'Send to Devmate' ;
163+ sendButton . setAttribute ( 'style' , 'padding: 4px 12px; cursor: pointer; align-self: flex-end;' ) ;
164+ sendButton . addEventListener ( 'click' , sendQueryToDevmate ) ;
165+
160166 bottomRow . appendChild ( queryInput ) ;
161167 bottomRow . appendChild ( sendButton ) ;
162168
0 commit comments