Skip to content

Commit 59996b9

Browse files
authored
feat(client): add vue SFC custom tab (#775)
1 parent ebec9f2 commit 59996b9

File tree

14 files changed

+405
-18
lines changed

14 files changed

+405
-18
lines changed

docs/plugins/api.md

+43
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,49 @@ addCustomTab({
5050
},
5151
category: 'advanced',
5252
})
53+
54+
55+
const SFC = /* vue */ `
56+
<script setup lang="ts">
57+
import { ref } from 'vue'
58+
59+
const count = ref(0)
60+
</script>
61+
62+
<template>
63+
<div class="h-full w-full flex flex-col items-center justify-center">
64+
<div>
65+
count is {{ count }}
66+
</div>
67+
<button class="btn" @click="count++">
68+
increment
69+
</button>
70+
</div>
71+
</template>
72+
73+
<style scoped>
74+
.btn {
75+
background-color: #4c51bf;
76+
color: #fff;
77+
padding: 0.5rem 1rem;
78+
border-radius: 0.25rem;
79+
border: none;
80+
cursor: pointer;
81+
}
82+
</style>
83+
`
84+
85+
addCustomTab({
86+
name: 'plugin-count',
87+
title: 'Plugin Count',
88+
icon: 'baseline-exposure-plus-1',
89+
// SFC view
90+
view: {
91+
type: 'sfc',
92+
sfc: SFC,
93+
},
94+
category: 'app',
95+
})
5396
```
5497

5598
## `addCustomCommand`

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
"play:multi-app": "turbo dev --filter=./packages/playground/multi-app",
6666
"play:webpack": "turbo dev --filter=./packages/playground/webpack",
6767
"play:options-api": "turbo dev --filter=./packages/playground/options-api",
68+
"play:plugin-sfc": "turbo dev --filter=./packages/playground/plugin-sfc",
6869
"docs": "pnpm -C docs run docs:dev",
6970
"docs:build": "pnpm -C docs run docs:build",
7071
"zip": "tsx ./scripts/extension-zip.ts",

packages/client/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@
4141
"vis-network": "^9.1.9",
4242
"vite-hot-client": "^0.2.4",
4343
"vue-router": "^4.5.0",
44-
"vue-virtual-scroller": "2.0.0-beta.8"
44+
"vue-virtual-scroller": "2.0.0-beta.8",
45+
"vue3-sfc-loader": "^0.9.5"
4546
},
4647
"devDependencies": {
4748
"@iconify/json": "^2.2.277",

packages/client/src/components/CustomTabComponent.vue

+3
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ watch(() => tabName.value, () => {
3939
<template v-else-if="tab?.view?.type === 'vnode'">
4040
<Component :is="tab.view.vnode" />
4141
</template>
42+
<template v-else-if="tab?.view?.type === 'sfc'">
43+
<SFCView :sfc="tab.view.sfc" :name="tab.name" />
44+
</template>
4245
<template v-else>
4346
<div>
4447
<NCard flex="~ col" h-full items-center justify-center>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<script setup lang="ts">
2+
import * as Vue from 'vue'
3+
import { loadModule } from 'vue3-sfc-loader'
4+
5+
const props = defineProps<{
6+
sfc: string
7+
name: string
8+
}>()
9+
10+
const options = {
11+
moduleCache: {
12+
vue: Vue,
13+
},
14+
getFile() {
15+
return props?.sfc ?? ''
16+
},
17+
addStyle(textContent: string) {
18+
const style = Object.assign(document.createElement('style'), { textContent })
19+
const ref = document.head.getElementsByTagName('style')[0] || null
20+
document.head.insertBefore(style, ref)
21+
},
22+
}
23+
24+
const RemoteSFC = defineAsyncComponent(() => loadModule(`${props.name}.vue`, options))
25+
</script>
26+
27+
<template>
28+
<RemoteSFC />
29+
</template>

packages/devtools-kit/src/types/tab.ts

+12-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ type TabCategory =
66
| 'modules'
77
| 'advanced'
88

9-
export type ModuleView = ModuleIframeView | ModuleVNodeView
9+
export type ModuleView = ModuleIframeView | ModuleVNodeView | ModuleSFCView
1010

1111
export interface ModuleIframeView {
1212
/**
@@ -36,6 +36,17 @@ export interface ModuleVNodeView {
3636
vnode: VNode
3737
}
3838

39+
export interface ModuleSFCView {
40+
/**
41+
* SFC view
42+
*/
43+
type: 'sfc'
44+
/**
45+
* SFC component
46+
*/
47+
sfc: string
48+
}
49+
3950
export interface CustomTab {
4051
/**
4152
* The name of the tab, must be unique
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>Vue DevTools Plugin-SFC Playground</title>
8+
</head>
9+
<body>
10+
<div id="app"></div>
11+
<script type="module" src="/src/main.ts"></script>
12+
</body>
13+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "playground-plugin-sfc",
3+
"type": "module",
4+
"version": "7.3.2",
5+
"private": true,
6+
"scripts": {
7+
"dev": "vite"
8+
},
9+
"dependencies": {
10+
"vue": "^3.5.13"
11+
},
12+
"devDependencies": {
13+
"@vitejs/plugin-vue": "^5.2.1",
14+
"@vue/devtools": "workspace:^",
15+
"typescript": "^5.7.2",
16+
"vite": "^6.0.1",
17+
"vite-plugin-inspect": "0.8.9",
18+
"vite-plugin-vue-devtools": "workspace:*"
19+
}
20+
}
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<script setup lang="ts">
2+
3+
</script>
4+
5+
<template>
6+
<div class="flex flex-col justify-center" />
7+
</template>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<script setup lang="ts">
2+
import { ref } from 'vue'
3+
4+
const count = ref(0)
5+
</script>
6+
7+
<template>
8+
<div class="h-full w-full flex flex-col items-center justify-center">
9+
<div>
10+
count is {{ count }}
11+
</div>
12+
<button class="btn" @click="count++">
13+
increment
14+
</button>
15+
</div>
16+
</template>
17+
18+
<style scoped>
19+
.btn {
20+
background-color: #4c51bf;
21+
color: #fff;
22+
padding: 0.5rem 1rem;
23+
border-radius: 0.25rem;
24+
border: none;
25+
cursor: pointer;
26+
}
27+
</style>
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { addCustomTab } from '@vue/devtools-kit'
2+
import { createApp } from 'vue'
3+
import App from './App.vue'
4+
import countSFC from './count.vue?raw'
5+
6+
const app = createApp(App)
7+
app.mount('#app')
8+
9+
setTimeout(() => {
10+
addCustomTab({
11+
name: 'plugin_count',
12+
title: 'Plugin Count',
13+
icon: 'baseline-exposure-plus-1',
14+
view: {
15+
type: 'sfc',
16+
sfc: countSFC,
17+
},
18+
category: 'app',
19+
})
20+
}, 2000)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import vue from '@vitejs/plugin-vue'
2+
import { defineConfig } from 'vite'
3+
import inspect from 'vite-plugin-inspect'
4+
import VueDevTools from 'vite-plugin-vue-devtools'
5+
// https://vitejs.dev/config/
6+
export default defineConfig({
7+
plugins: [
8+
vue(),
9+
VueDevTools(),
10+
inspect(),
11+
],
12+
server: {
13+
port: 3000,
14+
},
15+
})

0 commit comments

Comments
 (0)