@@ -110,5 +110,5 @@ watchDebounced(routeInput, () => {
/>
-
+
diff --git a/packages/client/src/pages/pinia.vue b/packages/client/src/pages/pinia.vue
index 04e145b0..11d7d1c9 100644
--- a/packages/client/src/pages/pinia.vue
+++ b/packages/client/src/pages/pinia.vue
@@ -1,87 +1,8 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/packages/client/src/pages/router.vue b/packages/client/src/pages/router.vue
index f37e89c6..f6ef79de 100644
--- a/packages/client/src/pages/router.vue
+++ b/packages/client/src/pages/router.vue
@@ -1,86 +1,8 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/packages/client/src/pages/timeline.vue b/packages/client/src/pages/timeline.vue
deleted file mode 100644
index fa10a1a0..00000000
--- a/packages/client/src/pages/timeline.vue
+++ /dev/null
@@ -1,137 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- No events
-
-
-
-
-
-
-
-
-
-
- Select an event to display details
-
-
-
-
-
-
-
- No layers
-
-
diff --git a/packages/client/uno.config.ts b/packages/client/uno.config.ts
index 8f50211c..d9e62e6d 100644
--- a/packages/client/uno.config.ts
+++ b/packages/client/uno.config.ts
@@ -1,5 +1,5 @@
import { defineConfig, mergeConfigs, presetAttributify, presetWebFonts } from 'unocss'
-import { themeDef, unoConfig } from '@vue/devtools-ui/theme'
+import { unoConfig } from '@vue/devtools-ui/theme'
export default defineConfig(mergeConfigs([unoConfig, {
rules: [
@@ -15,7 +15,7 @@ export default defineConfig(mergeConfigs([unoConfig, {
'background-size': '40px 40px',
}],
['panel-grids-dark', {
- 'background-image': `url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' transform='scale(3)'%3E%3Crect x='0' y='0' width='100%25' height='100%25' fill='${encodeURIComponent(themeDef.colors.black)}'/%3E%3Cpath d='M 10,-2.55e-7 V 20 Z M -1.1677362e-8,10 H 20 Z' stroke-width='0.2' stroke='${encodeURIComponent('#141b24')}' fill='none'/%3E%3C/svg%3E");`,
+ 'background-image': `url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' transform='scale(3)'%3E%3Crect x='0' y='0' width='100%25' height='100%25' fill='${encodeURIComponent('#121212')}'/%3E%3Cpath d='M 10,-2.55e-7 V 20 Z M -1.1677362e-8,10 H 20 Z' stroke-width='0.2' stroke='${encodeURIComponent('#121212')}' fill='none'/%3E%3C/svg%3E");`,
'background-size': '40px 40px',
}],
],
@@ -51,7 +51,7 @@ export default defineConfig(mergeConfigs([unoConfig, {
],
shortcuts: [{
// general
- 'bg-base': 'bg-white dark:bg-black',
+ 'bg-base': 'bg-white dark:bg-[#121212]',
'text-base': 'text-black dark:text-white',
'bg-active': 'bg-gray:5',
'border-base': 'border-gray/20',
@@ -61,7 +61,7 @@ export default defineConfig(mergeConfigs([unoConfig, {
'x-divider': 'h-1px w-full bg-gray/15',
// glass
- 'glass-effect': 'backdrop-blur-6 bg-white/80 dark:bg-black/90',
+ 'glass-effect': 'backdrop-blur-6 bg-white/80 dark:bg-[#121212]/90',
'navbar-glass': 'sticky z-10 top-0 glass-effect',
// code
diff --git a/packages/core/src/bridge-events/devtools-actions.ts b/packages/core/src/bridge-events/devtools-actions.ts
index c7df3dc4..b900ab51 100644
--- a/packages/core/src/bridge-events/devtools-actions.ts
+++ b/packages/core/src/bridge-events/devtools-actions.ts
@@ -37,6 +37,10 @@ export const inspectComponentInspector = defineDevToolsAction('devtools:inspect-
return devtools.api.inspectComponentInspector()
})
+export const cancelInspectComponentInspector = defineDevToolsAction('devtools:cancel-inspect-component-inspector', (devtools) => {
+ return devtools.api.cancelInspectComponentInspector()
+})
+
export const toggleComponentInspector = defineDevToolsAction('devtools:toggle-component-inspector', (devtools, payload) => {
return devtools.api.toggleComponentInspector(payload)
})
@@ -45,6 +49,10 @@ export const scrollToComponent = defineDevToolsAction('devtools:scroll-to-compon
return devtools.api.scrollToComponent(payload)
})
+export const getComponentRenderCode = defineDevToolsAction('devtools:get-component-render-code', (devtools, payload) => {
+ return devtools.api.getComponentRenderCode(payload)
+})
+
export const getInspectorState = defineDevToolsAction('devtools:inspector-state', async (devtools, payload) => {
const res = await devtools.api.getInspectorState(payload)
return stringify(res) as string
diff --git a/packages/devtools-kit/src/api/api.ts b/packages/devtools-kit/src/api/api.ts
index 35ea0d5f..d3c5f478 100644
--- a/packages/devtools-kit/src/api/api.ts
+++ b/packages/devtools-kit/src/api/api.ts
@@ -2,7 +2,7 @@ import { TimelineLayerItem, addTimelineLayer } from '../core/timeline'
import { InspectorApiPayload, addInspector, getInspector, updateInspector } from '../core/inspector'
import { toggleActiveAppRecord } from '../core/app-record'
import type { VueAppInstance } from '../types'
-import { highlight as highlightElement, inspectComponentHighLighter, scrollToComponent, toggleComponentHighLighter, unhighlight as unhighlightElement } from '../core/component-highlighter'
+import { cancelInspectComponentHighLighter, highlight as highlightElement, inspectComponentHighLighter, scrollToComponent, toggleComponentHighLighter, unhighlight as unhighlightElement } from '../core/component-highlighter'
import { devtoolsContext } from '../state'
import { now as nowFn, stringify } from '../shared'
import { StateEditor } from '../core/component/state/editor'
@@ -14,6 +14,7 @@ import type { CustomCommand } from '../core/custom-command'
import { getComponentInspector } from '../core/component-inspector'
import type { OpenInEditorOptions } from '../core/open-in-editor'
import { openInEditor } from '../core/open-in-editor'
+import { getComponentInstance } from '../core/component/utils'
import { DevToolsEventParams, DevToolsEvents, apiHooks } from './hook'
import { on } from './on'
@@ -182,10 +183,21 @@ export class DevToolsPluginApi {
return inspectComponentHighLighter()
}
+ cancelInspectComponentInspector() {
+ return cancelInspectComponentHighLighter()
+ }
+
scrollToComponent(...params: DevToolsEventParams
) {
return scrollToComponent(...params)
}
+ getComponentRenderCode(id: string) {
+ const instance = getComponentInstance(devtoolsContext.appRecord!, id)
+ if (instance)
+ // @ts-expect-error skip type check
+ return !(instance?.type instanceof Function) ? instance.render.toString() : instance.type.toString()
+ }
+
getComponentBoundingRect(...params: DevToolsEventParams) {
const { inspectorId, instanceId = '' } = params[0]
const _payload = {
diff --git a/packages/devtools-kit/src/api/hook.ts b/packages/devtools-kit/src/api/hook.ts
index 3410ba50..cd40a90b 100644
--- a/packages/devtools-kit/src/api/hook.ts
+++ b/packages/devtools-kit/src/api/hook.ts
@@ -17,6 +17,7 @@ export enum DevToolsEvents {
TOGGLE_COMPONENT_HIGHLIGHTER = 'component-highlighter:toggle',
GET_COMPONENT_BOUNDING_RECT = 'component-bounding-rect:get',
SCROLL_TO_COMPONENT = 'scroll-to-component',
+ GET_COMPONENT_RENDER_CODE = 'component-render-code:get',
GET_INSPECTOR_TREE = 'inspector-tree:get',
SEND_INSPECTOR_TREE = 'inspector-tree:send',
GET_INSPECTOR_STATE = 'inspector-state:get',
@@ -36,6 +37,7 @@ export interface DevToolsEvent {
// highlighter
[DevToolsEvents.TOGGLE_COMPONENT_HIGHLIGHTER]: (payload: ComponentHighLighterOptions) => void
[DevToolsEvents.SCROLL_TO_COMPONENT]: (payload: ScrollToComponentOptions) => void
+ [DevToolsEvents.GET_COMPONENT_RENDER_CODE]: (id: string) => void
[DevToolsEvents.GET_COMPONENT_BOUNDING_RECT]: (payload: ComponentBoundingRectApiPayload) => void
// state
[DevToolsEvents.DEVTOOLS_STATE_UPDATED]: (state: DevToolsState, oldState: DevToolsState) => void
diff --git a/packages/devtools-kit/src/core/component-highlighter/index.ts b/packages/devtools-kit/src/core/component-highlighter/index.ts
index 679906e3..7d348414 100644
--- a/packages/devtools-kit/src/core/component-highlighter/index.ts
+++ b/packages/devtools-kit/src/core/component-highlighter/index.ts
@@ -189,6 +189,14 @@ function selectComponentFn(e: MouseEvent, cb) {
}
}
+let inspectComponentHighLighterSelectFn: (e: MouseEvent) => void = null!
+
+export function cancelInspectComponentHighLighter() {
+ window.removeEventListener('mouseover', inspectFn)
+ window.removeEventListener('click', inspectComponentHighLighterSelectFn, true)
+ inspectComponentHighLighterSelectFn = null!
+}
+
export function inspectComponentHighLighter() {
window.addEventListener('mouseover', inspectFn)
return new Promise((resolve) => {
@@ -197,6 +205,7 @@ export function inspectComponentHighLighter() {
e.stopPropagation()
selectComponentFn(e, (id: string) => {
window.removeEventListener('click', onSelect, true)
+ inspectComponentHighLighterSelectFn = null!
window.removeEventListener('mouseover', inspectFn)
const el = getContainerElement()
if (el)
@@ -204,6 +213,7 @@ export function inspectComponentHighLighter() {
resolve(JSON.stringify({ id }))
})
}
+ inspectComponentHighLighterSelectFn = onSelect
window.addEventListener('click', onSelect, true)
})
}
diff --git a/packages/devtools-kit/src/core/component/state/custom.ts b/packages/devtools-kit/src/core/component/state/custom.ts
index 73152ef7..d869435d 100644
--- a/packages/devtools-kit/src/core/component/state/custom.ts
+++ b/packages/devtools-kit/src/core/component/state/custom.ts
@@ -22,7 +22,7 @@ export function getFunctionDetails(func: Function) {
return {
_custom: {
type: 'function' satisfies customTypeEnums,
- displayText: `function ${escape(name)}${args}`,
+ displayText: `function ${escape(name)}${args}`,
tooltipText: string.trim() ? `${string}
` : null,
},
}
diff --git a/packages/devtools-kit/src/core/component/state/process.ts b/packages/devtools-kit/src/core/component/state/process.ts
index e11bacbe..8e6205a7 100644
--- a/packages/devtools-kit/src/core/component/state/process.ts
+++ b/packages/devtools-kit/src/core/component/state/process.ts
@@ -148,10 +148,11 @@ function processSetupState(instance: VueAppInstance) {
let result: Partial
- // @TODO: need to re-design this?
let isOtherType = typeof value === 'function'
- || typeof value?.render === 'function'
- || typeof value?.__asyncLoader === 'function'
+ || typeof value?.render === 'function' // Components
+ || typeof value?.__asyncLoader === 'function' // Components
+ || (typeof value === 'object' && value && ('setup' in value || 'props' in value)) // Components
+ || /^v[A-Z]/.test(key) // Directives
if (rawData) {
const info = getSetupStateType(rawData)
diff --git a/packages/devtools-kit/src/core/component/utils/index.ts b/packages/devtools-kit/src/core/component/utils/index.ts
index ab3c5679..d7344116 100644
--- a/packages/devtools-kit/src/core/component/utils/index.ts
+++ b/packages/devtools-kit/src/core/component/utils/index.ts
@@ -101,7 +101,7 @@ export function getInstanceName(instance: VueAppInstance) {
*/
export function getUniqueComponentId(instance: VueAppInstance) {
const appId = instance?.appContext?.app?.__VUE_DEVTOOLS_NEXT_APP_RECORD_ID__ ?? 0
- const instanceId = instance === instance.root ? 'root' : instance.uid
+ const instanceId = instance === instance?.root ? 'root' : instance.uid
return `${appId}:${instanceId}`
}
diff --git a/packages/devtools-kit/src/index.ts b/packages/devtools-kit/src/index.ts
index 0b83c0af..e63f2b92 100644
--- a/packages/devtools-kit/src/index.ts
+++ b/packages/devtools-kit/src/index.ts
@@ -29,7 +29,8 @@ export interface DevToolsType {
export { parse, stringify } from './shared'
export { formatInspectorStateValue, getInspectorStateValueType, getRaw, toEdit, toSubmit } from './core/component/state/format'
-export { UNDEFINED } from './core/component/state/constants'
+export { UNDEFINED, INFINITY, NAN, NEGATIVE_INFINITY } from './core/component/state/constants'
+export { isPlainObject } from './core/component/state/is'
export const devtools = {
state: devtoolsState,
diff --git a/packages/playground/applet/package.json b/packages/playground/applet/package.json
index 0e7604e9..0c7b25ec 100644
--- a/packages/playground/applet/package.json
+++ b/packages/playground/applet/package.json
@@ -19,6 +19,7 @@
"@vue/devtools-applet": "workspace:*",
"@vue/devtools-core": "workspace:*",
"@vue/devtools-kit": "workspace:*",
+ "@vue/devtools-shared": "workspace:*",
"sass": "^1.75.0",
"serve": "^14.2.2",
"typescript": "^5.4.5",
diff --git a/packages/playground/applet/src/App.vue b/packages/playground/applet/src/App.vue
index d104efc0..7daf105e 100644
--- a/packages/playground/applet/src/App.vue
+++ b/packages/playground/applet/src/App.vue
@@ -1,11 +1,13 @@
+
+
+
+ Foo Component {{ msg }}
+
+
diff --git a/packages/playground/applet/src/components/Hello.vue b/packages/playground/applet/src/components/Hello.vue
new file mode 100644
index 00000000..71a04409
--- /dev/null
+++ b/packages/playground/applet/src/components/Hello.vue
@@ -0,0 +1,10 @@
+
+
+
+
+ Hello Component
+
+
+
diff --git a/packages/playground/basic/vite.config.ts b/packages/playground/basic/vite.config.ts
index d06e4aeb..f08406a9 100644
--- a/packages/playground/basic/vite.config.ts
+++ b/packages/playground/basic/vite.config.ts
@@ -1,7 +1,7 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
+import VueDevTools from 'vite-plugin-vue-devtools'
-import VueDevtools from 'vite-plugin-vue-devtools'
import Unocss from 'unocss/vite'
import AutoImport from 'unplugin-auto-import/vite'
@@ -9,7 +9,7 @@ import AutoImport from 'unplugin-auto-import/vite'
export default defineConfig({
plugins: [
vue(),
- VueDevtools(),
+ VueDevTools(),
Unocss(),
AutoImport({
imports: [
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index cd3cbb04..9e51c3ff 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -161,9 +161,15 @@ importers:
'@vue/devtools-ui':
specifier: workspace:^
version: link:../ui
+ lodash-es:
+ specifier: ^4.17.21
+ version: 4.17.21
perfect-debounce:
specifier: ^1.0.0
version: 1.0.0
+ shiki:
+ specifier: 1.3.0
+ version: 1.3.0
splitpanes:
specifier: ^3.1.5
version: 3.1.5
@@ -171,6 +177,9 @@ importers:
specifier: 2.0.0-beta.8
version: 2.0.0-beta.8(vue@3.4.23)
devDependencies:
+ '@types/lodash-es':
+ specifier: ^4.17.12
+ version: 4.17.12
unplugin-vue:
specifier: ^5.0.5
version: 5.0.5(@types/node@20.12.7)(vue@3.4.23)
@@ -208,6 +217,9 @@ importers:
'@unocss/runtime':
specifier: ^0.59.4
version: 0.59.4
+ '@vue/devtools-applet':
+ specifier: workspace:^
+ version: link:../applet
'@vue/devtools-core':
specifier: workspace:^
version: link:../core
@@ -493,6 +505,9 @@ importers:
'@vue/devtools-kit':
specifier: workspace:*
version: link:../../devtools-kit
+ '@vue/devtools-shared':
+ specifier: workspace:*
+ version: link:../../shared
sass:
specifier: ^1.75.0
version: 1.75.0
@@ -2588,6 +2603,12 @@ packages:
'@types/linkify-it@3.0.5':
resolution: {integrity: sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw==}
+ '@types/lodash-es@4.17.12':
+ resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==}
+
+ '@types/lodash@4.17.0':
+ resolution: {integrity: sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==}
+
'@types/markdown-it@12.2.3':
resolution: {integrity: sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==}
@@ -5820,6 +5841,9 @@ packages:
resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ lodash-es@4.17.21:
+ resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
+
lodash.debounce@4.0.8:
resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==}
@@ -10339,6 +10363,12 @@ snapshots:
'@types/linkify-it@3.0.5': {}
+ '@types/lodash-es@4.17.12':
+ dependencies:
+ '@types/lodash': 4.17.0
+
+ '@types/lodash@4.17.0': {}
+
'@types/markdown-it@12.2.3':
dependencies:
'@types/linkify-it': 3.0.5
@@ -14211,6 +14241,8 @@ snapshots:
dependencies:
p-locate: 6.0.0
+ lodash-es@4.17.21: {}
+
lodash.debounce@4.0.8: {}
lodash.defaultsdeep@4.6.1: {}
diff --git a/turbo.json b/turbo.json
index 49b2816a..e64bed8e 100644
--- a/turbo.json
+++ b/turbo.json
@@ -10,13 +10,6 @@
"@vue/devtools-electron#stub"
]
},
- "@vue/devtools-applet#stub": {
- "cache": false,
- "dependsOn": [
- "@vue/devtools-kit#stub",
- "^stub"
- ]
- },
"@vue/devtools-browser-extension#build": {
"dependsOn": [
"@vue/devtools-client#build",