Skip to content
This repository was archived by the owner on Jan 6, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/client/auto-imports.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// Generated by unplugin-auto-import
export {}
declare global {
Expand Down Expand Up @@ -98,8 +99,12 @@ declare global {
const resolveComponent: typeof import('vue')['resolveComponent']
const resolveRef: typeof import('@vueuse/core')['resolveRef']
const resolveUnref: typeof import('@vueuse/core')['resolveUnref']
const scrollToComponent: typeof import('./composables/component')['scrollToComponent']
const selected: typeof import('./composables/component')['selected']
const selectedComponent: typeof import('./composables/component')['selectedComponent']
const selectedComponentName: typeof import('./composables/component')['selectedComponentName']
const selectedComponentNode: typeof import('./composables/component')['selectedComponentNode']
const selectedComponentNodeFilePath: typeof import('./composables/component')['selectedComponentNodeFilePath']
const selectedComponentState: typeof import('./composables/component')['selectedComponentState']
const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly']
Expand Down
2 changes: 1 addition & 1 deletion src/client/components/ComponentTreeNode.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const { highlight, unhighlight } = useHighlightComponent(props.data)
}"
vue-block
:class="[isSelected ? 'vue-block-active' : 'vue-block-hover']"
@click="select(data.id)"
@click="select(data)"
@mouseover="highlight"
@mouseleave="unhighlight"
>
Expand Down
44 changes: 40 additions & 4 deletions src/client/composables/component.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
import type { ComponentInternalInstance } from 'vue'

import { InstanceMap, getInstanceName, getInstanceOrVnodeRect } from '../logic/components'
import { InstanceMap, getInstanceDetails, getInstanceName, getInstanceOrVnodeRect, getRootElementsFromComponentInstance } from '../logic/components'
import { useDevtoolsClient } from '../logic/client'

export const selected = ref('vue-devtools:root')
export const selectedComponentName = ref('')
export const selectedComponentNode = ref<ComponentTreeNode>()
export const selectedComponentNodeFilePath = computed(() => getInstanceDetails(selectedComponentNode.value?.instance)?.file)
const expandedMap = ref<Record<ComponentTreeNode['id'], boolean>>({
'vue-devtools:root': true,
})

export const selectedComponent = ref<ComponentInternalInstance>()
export const selectedComponentState = shallowRef<Record<string, any>[]>([])
export function useComponent(instance: ComponentTreeNode & { instance?: ComponentInternalInstance }) {
function select(id: string) {
selected.value = id
function select(data: ComponentTreeNode) {
selected.value = data.id
selectedComponentName.value = data.name
// TODO (Refactor): get instance state way
selectedComponentState.value = InstanceMap.get(id)
selectedComponentState.value = InstanceMap.get(data.id)
selectedComponentNode.value = data
// selectedComponent.value = instance.instance
// selectedComponentState.value = getInstanceState(instance.instance!)
}
Expand Down Expand Up @@ -48,3 +54,33 @@ export function useHighlightComponent(node: ComponentTreeNode): {
unhighlight,
}
}

scrollToComponent.timer = null
export function scrollToComponent() {
if (scrollToComponent.timer)
clearTimeout(scrollToComponent.timer)

const client = useDevtoolsClient()
const { highlight, unhighlight } = useHighlightComponent(selectedComponentNode.value!)

const instance = selectedComponentNode.value!.instance

const [el] = getRootElementsFromComponentInstance(instance)
if (typeof el.scrollIntoView === 'function') {
el.scrollIntoView({
behavior: 'smooth',
})
}
else {
const _bounds = getInstanceOrVnodeRect(instance)
client.value.componentInspector.scrollToComponent(_bounds)
}

scrollToComponent.timer = setTimeout(() => {
highlight()
scrollToComponent.timer = setTimeout(() => {
unhighlight()
scrollToComponent.timer = null
}, 1500)
}, 1200)
}
1 change: 1 addition & 0 deletions src/client/logic/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const client = ref<VueDevtoolsHostClient>({
componentInspector: {
highlight: () => {},
unHighlight: () => {},
scrollToComponent: () => {},
},
})

Expand Down
2 changes: 1 addition & 1 deletion src/client/logic/components/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export function getInstanceDetails(instance: any): any {
return {
id: getUniqueComponentId(instance),
name: getInstanceName(instance),
file: instance.type?.__file,
file: instance?.type?.__file,
state: getInstanceState(instance),
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/client/logic/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { ComponentWalker, InstanceMap } from './tree'
export { getInstanceState } from './data'
export { getInstanceOrVnodeRect } from './el'
export { getInstanceState, getInstanceDetails } from './data'
export { getInstanceOrVnodeRect, getRootElementsFromComponentInstance } from './el'
export { getInstanceName } from './util'
36 changes: 35 additions & 1 deletion src/client/pages/components.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
import { Pane, Splitpanes } from 'splitpanes'

import { ComponentWalker, getInstanceState } from '../logic/components'
import { useDevtoolsClient } from '../logic/client'
import { instance, onVueInstanceUpdate } from '../logic/app'
import { selected } from '../composables/component'
import { scrollToComponent, selected, selectedComponentName, selectedComponentNode, selectedComponentNodeFilePath } from '../composables/component'

const componentTree = ref<ComponentTreeNode[]>([])

Expand Down Expand Up @@ -49,6 +50,8 @@ function init() {
selectedComponentState.value = getInstanceState(instance.value!)
walker.getComponentTree(instance.value!).then((res) => {
componentTree.value = res
selectedComponentName.value = res?.[0]?.name ?? ''
selectedComponentNode.value = res?.[0]
})
}

Expand All @@ -60,6 +63,11 @@ onMounted(() => {
}
})
})

function openInEditor() {
const client = useDevtoolsClient()
client.value.openInEditor(selectedComponentNodeFilePath.value)
}
</script>

<template>
Expand All @@ -71,6 +79,32 @@ onMounted(() => {
</div>
</Pane>
<Pane>
<div v-if="normalizedComponentState.length" border="b base" flex justify-between px-4 py-2>
<span v-if="selectedComponentName" text-sm text-primary op90>&lt;{{ selectedComponentName }}&gt;</span>
<p flex>
<span>
<VTooltip placement="bottom">
<i gg:scroll-h cursor-pointer text-xl op70 hover="op100" @click="scrollToComponent" />
<template #popper>
<p text-xs op-50>
Scroll to component
</p>
</template>
</VTooltip>

</span>
<span v-if="selectedComponentNodeFilePath" pl-2>
<VTooltip placement="bottom">
<i carbon-launch cursor-pointer text-sm op70 hover="op100" @click="openInEditor" />
<template #popper>
<p text-xs op-50>
Open component in editor
</p>
</template>
</VTooltip>
</span>
</p>
</div>
<div v-if="normalizedComponentState.length" h-screen select-none overflow-scroll p-2 class="no-scrollbar">
<StateFields v-for="(item, index) in normalizedComponentState" :id="index" :key="item.key" :data="item" />
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/node/views/ComponentInspector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const inspectorCardStyle = computed(() => ({ top: props.bounds.top < 35 ? 0 : '-

<style scoped>
.vue-devtools-component-inspector {
z-index: 2147483646;
z-index: 2147483640;
position: fixed;
background-color:#42b88325;
border: 1px solid #42b88350;
Expand Down
15 changes: 15 additions & 0 deletions src/node/views/Main.vue
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,21 @@ async function setupClient(iframe: HTMLIFrameElement) {
componentInspector: {
highlight,
unHighlight,
scrollToComponent(bounds) {
const scrollTarget = document.createElement('div')
scrollTarget.style.position = 'absolute'
scrollTarget.style.width = `${Math.round(bounds.width * 100) / 100}px`
scrollTarget.style.height = `${Math.round(bounds.height * 100) / 100}px`
scrollTarget.style.top = `${Math.round(bounds.top * 100) / 100}px`
scrollTarget.style.left = `${Math.round(bounds.left * 100) / 100}px`
document.body.appendChild(scrollTarget)
scrollTarget.scrollIntoView({
behavior: 'smooth',
})
setTimeout(() => {
document.body.removeChild(scrollTarget)
}, 2000)
},
},
})
}
Expand Down
14 changes: 8 additions & 6 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ import type { Router } from 'vue-router'

type WithOptional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>

export interface ComponentInspectorBounds {
width: number
height: number
top: number
left: number
}
export interface ComponentRelationship {
id: string
deps: string[]
Expand Down Expand Up @@ -80,13 +86,9 @@ export interface VueDevtoolsHostClient {
categorizedHookBuffer: Record<string, [string, Record<string, any>][]>
openInEditor: OpenInEditorFn
componentInspector: {
highlight: (_name: string, _bounds: {
top: number
left: number
width: number
height: number
}) => void
highlight: (_name: string, _bounds: ComponentInspectorBounds) => void
unHighlight: () => void
scrollToComponent: (_bounds: ComponentInspectorBounds) => void
}
}

Expand Down