11import type { NuxtDevtoolsHostClient , TimelineEventRoute , TimelineMetrics } from '@nuxt/devtools/types'
2+ import type { NuxtDevToolsInspectorProps } from '@nuxt/devtools/webcomponents'
23import type { $Fetch } from 'ofetch'
34import type { Ref } from 'vue'
4- import type { Router } from 'vue-router'
55
6+ import type { Router } from 'vue-router'
67// eslint-disable-next-line ts/ban-ts-comment
78// @ts -ignore tsconfig
89import { useAppConfig , useRuntimeConfig } from '#imports'
10+ import { NuxtDevtoolsFrame , NuxtDevtoolsInspectPanel } from '@nuxt/devtools/webcomponents'
911import { setIframeServerContext } from '@vue/devtools-kit'
12+
1013import { createHooks } from 'hookable'
1114import { debounce } from 'perfect-debounce'
12-
1315import { events as inspectorEvents , hasData as inspectorHasData , state as inspectorState } from 'vite-plugin-vue-tracer/client/overlay'
14- import { computed , createApp , h , markRaw , ref , shallowReactive , shallowRef , toRef , watch } from 'vue'
15- import { initTimelineMetrics } from '../../function-metrics-helpers'
16- import Main from './Main.vue'
16+ import { computed , markRaw , reactive , ref , shallowReactive , shallowRef , toRef , watch } from 'vue'
1717
18+ import { initTimelineMetrics } from '../../function-metrics-helpers'
19+ import { settings } from '../../settings'
1820import { popupWindow , state } from './state'
1921
2022const clientRef = shallowRef < NuxtDevtoolsHostClient > ( )
@@ -34,6 +36,9 @@ export async function setupDevToolsClient({
3436 timeMetric : any
3537 router : Router
3638} ) {
39+ let iframe : HTMLIFrameElement | undefined
40+ let inspector : NuxtDevtoolsHostClient [ 'inspector' ] | undefined
41+
3742 const colorMode = useClientColorMode ( )
3843 const timeline = initTimelineMetrics ( )
3944
@@ -108,8 +113,6 @@ export async function setupDevToolsClient({
108113
109114 window . __NUXT_DEVTOOLS_HOST__ = client
110115
111- let iframe : HTMLIFrameElement | undefined
112-
113116 function syncClient ( ) {
114117 if ( ! client . inspector )
115118 client . inspector = getInspectorInstance ( )
@@ -183,33 +186,65 @@ export async function setupDevToolsClient({
183186 }
184187
185188 function getInspectorInstance ( ) : NuxtDevtoolsHostClient [ 'inspector' ] {
186- const isAvailable = ref ( inspectorHasData ( ) )
189+ if ( inspector )
190+ return inspector
187191
188- if ( ! inspectorEvents . events . disabled ?. length ) {
189- inspectorEvents . on ( 'disabled' , ( ) => {
190- inspectorState . isVisible = false
191- client ?. hooks . callHook ( 'host:inspector:close' )
192- } )
193- }
194- if ( ! inspectorEvents . events . enabled ?. length ) {
195- inspectorEvents . on ( 'enabled' , ( ) => {
196- inspectorState . isVisible = true
197- } )
198- }
199- if ( ! inspectorEvents . events . click ?. length ) {
200- inspectorEvents . on ( 'click' , async ( info ) => {
201- inspectorState . isEnabled = false
202- await client . hooks . callHook ( 'host:inspector:click' , info . fullpath )
203- } )
204- }
192+ const props = reactive < NuxtDevToolsInspectorProps > ( {
193+ mouse : { x : 0 , y : 0 } ,
194+ matched : undefined ,
195+ } )
205196
197+ const component = new NuxtDevtoolsInspectPanel ( reactive ( { props } ) )
198+ document . body . appendChild ( component )
199+ Object . assign ( component . style , {
200+ zIndex : 999999 ,
201+ position : 'fixed' ,
202+ } )
203+ component . addEventListener ( 'close' , ( ) => {
204+ props . matched = undefined
205+ inspectorState . isEnabled = false
206+ } )
207+ component . addEventListener ( 'selectParent' , ( ) => {
208+ const parent = inspectorState . main ?. getParent ( )
209+ if ( parent ) {
210+ inspectorState . main = parent
211+ props . matched = parent
212+ }
213+ } )
214+ // eslint-disable-next-line ts/ban-ts-comment
215+ // @ts -ignore WebComponent types
216+ component . addEventListener ( 'openInEditor' , ( e ) => {
217+ const url = ( e as any ) ?. detail ?. [ 0 ]
218+ if ( url )
219+ client . hooks . callHook ( 'host:inspector:click' , url )
220+ } )
221+
222+ inspectorEvents . on ( 'hover' , ( ) => {
223+ inspectorState . isFocused = false
224+ } )
225+ inspectorEvents . on ( 'disabled' , ( ) => {
226+ inspectorState . isVisible = false
227+ client ?. hooks . callHook ( 'host:inspector:close' )
228+ } )
229+ inspectorEvents . on ( 'enabled' , ( ) => {
230+ inspectorState . isVisible = true
231+ } )
232+ inspectorEvents . on ( 'click' , async ( info , e ) => {
233+ inspectorState . isFocused = true
234+ inspectorState . isVisible = true
235+
236+ props . matched = info
237+ props . mouse = { x : e . clientX , y : e . clientY }
238+ } )
239+
240+ const isAvailable = ref ( inspectorHasData ( ) )
206241 if ( ! isAvailable . value ) {
207242 inspectorEvents . on ( 'hover' , async ( ) => {
208243 isAvailable . value = inspectorHasData ( )
209244 } )
210245 }
211246
212- return markRaw ( {
247+ return inspector = markRaw ( {
213248 isAvailable,
214249 isEnabled : toRef ( inspectorState , 'isEnabled' ) ,
215250 enable : ( ) => {
@@ -284,13 +319,13 @@ export async function setupDevToolsClient({
284319 client . devtools . toggle ( )
285320 } )
286321
287- const app = createApp ( {
288- render : ( ) => h ( Main , { client } ) ,
289- devtools : {
290- hide : true ,
291- } ,
292- } )
293- app . mount ( holder )
322+ const frame = new NuxtDevtoolsFrame ( reactive ( {
323+ client,
324+ settings ,
325+ state ,
326+ popupWindow ,
327+ } ) )
328+ holder . appendChild ( frame )
294329}
295330
296331export function useClientColorMode ( ) : Ref < ColorScheme > {
0 commit comments