Skip to content

Commit 4f5bb06

Browse files
authored
feat: vee validate panel (#390)
1 parent b82807c commit 4f5bb06

File tree

28 files changed

+465
-298
lines changed

28 files changed

+465
-298
lines changed

packages/applet/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ export * from './modules/components'
88
export * from './modules/router'
99
export * from './modules/vue-query'
1010
export * from './modules/vuex'
11+
export * from './modules/vee-validate'
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<template>
2+
<svg viewBox="0 0 566 154" fill="none" xmlns="http://www.w3.org/2000/svg">
3+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384.9216 333.356828" width="10em">
4+
<path fill="#06d77b" d="m320.544 0-32.1944 55.7536-95.8888 166.0904L96.572 55.7536h66.0912l29.7976 51.5984 29.7976-51.5984L254.4416 0H0l192.4608 333.3568L384.9216 0Z" />
5+
</svg>
6+
<path d="M152.571 118V46.1333H176.8C183.576 46.1333 189.77 47.468 195.383 50.1373C200.995 52.8067 205.478 56.8449 208.832 62.252C212.186 67.5907 213.863 74.1956 213.863 82.0667C213.863 89.8693 212.186 96.4742 208.832 101.881C205.478 107.288 200.995 111.327 195.383 113.996C189.77 116.665 183.576 118 176.8 118H152.571ZM175.157 104.653C181.796 104.653 187.306 102.874 191.687 99.3147C196.067 95.6871 198.257 89.9378 198.257 82.0667C198.257 74.1956 196.067 68.4462 191.687 64.8187C187.306 61.1911 181.796 59.3773 175.157 59.3773H167.971V104.653H175.157ZM270.18 100.444C269.153 105.988 266.381 110.437 261.864 113.791C257.347 117.144 251.905 118.821 245.54 118.821C239.928 118.821 235.102 117.555 231.064 115.023C227.094 112.422 224.083 109.068 222.029 104.961C219.976 100.855 218.949 96.5427 218.949 92.0253C218.949 87.4396 219.873 83.1276 221.721 79.0893C223.638 75.0511 226.513 71.7658 230.345 69.2333C234.247 66.7009 238.969 65.4347 244.513 65.4347C250.263 65.4347 255.054 66.6667 258.887 69.1307C262.72 71.5947 265.526 74.7431 267.305 78.576C269.153 82.4089 270.077 86.4471 270.077 90.6907C270.077 92.2649 270.009 93.8049 269.872 95.3107H232.707C233.254 99.0067 234.623 101.916 236.813 104.037C239.072 106.091 241.981 107.117 245.54 107.117C248.415 107.117 250.776 106.57 252.624 105.475C254.472 104.311 255.67 102.634 256.217 100.444H270.18ZM244.513 75.9067C241.228 75.9067 238.627 76.7622 236.711 78.4733C234.794 80.116 233.528 82.7169 232.912 86.276H255.807C255.601 83.2644 254.506 80.8004 252.521 78.884C250.537 76.8991 247.867 75.9067 244.513 75.9067ZM302.77 118H289.629L270.738 66.256H285.317L296.2 99.7253L306.98 66.256H321.661L302.77 118ZM359.731 118H344.331V59.3773H323.079V46.1333H380.983V59.3773H359.731V118ZM402.364 118.821C397.163 118.821 392.474 117.692 388.299 115.433C384.124 113.106 380.873 109.924 378.546 105.885C376.219 101.779 375.055 97.1929 375.055 92.128C375.055 87.0631 376.219 82.5116 378.546 78.4733C380.873 74.3667 384.124 71.184 388.299 68.9253C392.474 66.5982 397.163 65.4347 402.364 65.4347C407.566 65.4347 412.255 66.5982 416.43 68.9253C420.605 71.184 423.856 74.3667 426.183 78.4733C428.51 82.5116 429.674 87.0631 429.674 92.128C429.674 97.1929 428.51 101.779 426.183 105.885C423.856 109.924 420.605 113.106 416.43 115.433C412.255 117.692 407.566 118.821 402.364 118.821ZM402.364 106.501C406.197 106.501 409.311 105.167 411.707 102.497C414.103 99.828 415.3 96.3716 415.3 92.128C415.3 87.816 414.103 84.3253 411.707 81.656C409.311 78.9867 406.197 77.652 402.364 77.652C398.531 77.652 395.417 78.9867 393.022 81.656C390.626 84.3253 389.428 87.816 389.428 92.128C389.428 96.3716 390.626 99.828 393.022 102.497C395.417 105.167 398.531 106.501 402.364 106.501ZM462.12 118.821C456.918 118.821 452.229 117.692 448.054 115.433C443.879 113.106 440.628 109.924 438.301 105.885C435.974 101.779 434.81 97.1929 434.81 92.128C434.81 87.0631 435.974 82.5116 438.301 78.4733C440.628 74.3667 443.879 71.184 448.054 68.9253C452.229 66.5982 456.918 65.4347 462.12 65.4347C467.321 65.4347 472.01 66.5982 476.185 68.9253C480.36 71.184 483.611 74.3667 485.938 78.4733C488.265 82.5116 489.429 87.0631 489.429 92.128C489.429 97.1929 488.265 101.779 485.938 105.885C483.611 109.924 480.36 113.106 476.185 115.433C472.01 117.692 467.321 118.821 462.12 118.821ZM462.12 106.501C465.952 106.501 469.067 105.167 471.462 102.497C473.858 99.828 475.056 96.3716 475.056 92.128C475.056 87.816 473.858 84.3253 471.462 81.656C469.067 78.9867 465.952 77.652 462.12 77.652C458.287 77.652 455.172 78.9867 452.777 81.656C450.381 84.3253 449.184 87.816 449.184 92.128C449.184 96.3716 450.381 99.828 452.777 102.497C455.172 105.167 458.287 106.501 462.12 106.501ZM512.327 118H498.056V43.772H512.327V118ZM542.494 118.821C536.129 118.821 530.961 117.179 526.991 113.893C523.09 110.54 521.002 106.091 520.729 100.547H533.049C533.322 102.874 534.281 104.722 535.923 106.091C537.634 107.391 539.825 108.041 542.494 108.041C544.684 108.041 546.464 107.562 547.833 106.604C549.27 105.646 549.989 104.448 549.989 103.011C549.989 101.094 549.167 99.7596 547.525 99.0067C545.882 98.2538 543.281 97.5693 539.722 96.9533C536.026 96.2689 533.014 95.516 530.687 94.6947C528.36 93.8733 526.341 92.4018 524.63 90.28C522.987 88.0898 522.166 85.0098 522.166 81.04C522.166 78.0284 522.953 75.3591 524.527 73.032C526.17 70.6364 528.394 68.7884 531.201 67.488C534.007 66.1191 537.155 65.4347 540.646 65.4347C546.874 65.4347 551.905 66.9747 555.738 70.0547C559.639 73.1347 561.727 77.2071 562.001 82.272H549.578C549.304 80.1502 548.312 78.5076 546.601 77.344C544.958 76.112 543.11 75.496 541.057 75.496C539.003 75.496 537.361 75.9409 536.129 76.8307C534.897 77.7204 534.281 78.9524 534.281 80.5267C534.281 82.4431 535.068 83.7436 536.642 84.428C538.285 85.044 540.851 85.5916 544.342 86.0707C548.106 86.6182 551.186 87.3027 553.582 88.124C556.046 88.8769 558.168 90.3827 559.947 92.6413C561.727 94.9 562.617 98.1853 562.617 102.497C562.617 107.425 560.769 111.395 557.073 114.407C553.445 117.35 548.585 118.821 542.494 118.821Z" fill="currentColor" />
7+
</svg>
8+
</template>
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<script setup lang="ts">
2+
import DevToolsLogo from './DevToolsLogo.vue'
3+
import { useVirtualRouter } from '~/composables/virtual-router'
4+
5+
const virtualRouter = useVirtualRouter()
6+
</script>
7+
8+
<template>
9+
<div h-full w-full flex items-center>
10+
<div flex="~ col gap2" ma px-5>
11+
<div flex-auto />
12+
13+
<!-- Banner -->
14+
<div flex="~ col" mt-20 items-center>
15+
<div flex="~" mt--10 items-center justify-center>
16+
<DevToolsLogo h-18 />
17+
</div>
18+
<div mb6 mt--1 text-center text-sm flex="~ gap-1">
19+
<span op40>
20+
Vee Validate DevTools
21+
</span>
22+
</div>
23+
</div>
24+
25+
<div flex-auto />
26+
27+
<div flex="~ gap2 wrap">
28+
<div flex="~ col auto" min-w-40 p4 theme-card-lime @click="virtualRouter.push('/state')">
29+
<div i-carbon-tree-view-alt text-3xl />
30+
<code>State</code>
31+
</div>
32+
<!-- <div flex="~ col auto" min-w-40 p4 theme-card-lime @click="virtualRouter.push('/timeline')">
33+
<div i-mdi:timeline-clock-outline text-3xl />
34+
<div>Timeline</div>
35+
</div> -->
36+
</div>
37+
38+
<div flex="~ gap-6 wrap" mt-5 items-center justify-center>
39+
<a href="https://github.com/logaretm/vee-validate/" target="_blank" flex="~ gap1" items-center op50 hover="op100 text-blue" transition>
40+
<div i-carbon-star />
41+
Star on GitHub
42+
</a>
43+
<a href="https://vee-validate.logaretm.com/v4/" target="_blank" flex="~ gap1" items-center op50 hover="op100 text-yellow" transition>
44+
<div i-carbon-document />
45+
View Documentation
46+
</a>
47+
</div>
48+
49+
<div flex-auto />
50+
</div>
51+
</div>
52+
</template>
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
<script setup lang="ts">
2+
import { computed, ref, watch } from 'vue'
3+
import { Pane, Splitpanes } from 'splitpanes'
4+
import { callInspectorAction, callInspectorNodeAction, getInspectorActions, getInspectorNodeActions, getInspectorState, getInspectorTree, onInspectorStateUpdated, onInspectorTreeUpdated } from '@vue/devtools-core'
5+
import { parse } from '@vue/devtools-kit'
6+
import type { InspectorNodeTag, InspectorState } from '@vue/devtools-kit'
7+
import { vTooltip } from '@vue/devtools-ui'
8+
import Navbar from '~/components/basic/Navbar.vue'
9+
import SelectiveList from '~/components/basic/SelectiveList.vue'
10+
import DevToolsHeader from '~/components/basic/DevToolsHeader.vue'
11+
import Empty from '~/components/basic/Empty.vue'
12+
import RootStateViewer from '~/components/state/RootStateViewer.vue'
13+
import { createExpandedContext } from '~/composables/toggle-expanded'
14+
15+
const { expanded: expandedStateNodes } = createExpandedContext('vee-validate-state')
16+
17+
interface NodeAction {
18+
icon: string
19+
tooltip: string
20+
actions?: (payload: unknown) => void
21+
}
22+
const inspectorId = 'vee-validate-inspector'
23+
const nodeActions = ref<NodeAction[]>([])
24+
const actions = ref<NodeAction[]>([])
25+
26+
const selected = ref('')
27+
const tree = ref<{ id: string, label: string, tags: InspectorNodeTag[] }[]>([])
28+
const state = ref<Record<string, InspectorState[]>>({})
29+
const emptyState = computed(() => !Object.keys(state.value).length)
30+
31+
function getNodeActions() {
32+
getInspectorNodeActions(inspectorId).then((actions) => {
33+
nodeActions.value = actions as NodeAction[]
34+
})
35+
}
36+
37+
function getActions() {
38+
getInspectorActions(inspectorId).then((_actions) => {
39+
actions.value = _actions as NodeAction[]
40+
})
41+
}
42+
43+
getNodeActions()
44+
45+
getActions()
46+
47+
function callNodeAction(index: number) {
48+
callInspectorNodeAction(inspectorId, index, selected.value)
49+
}
50+
51+
function callAction(index: number) {
52+
callInspectorAction(inspectorId, index, selected.value)
53+
}
54+
55+
function filterEmptyState(data: Record<string, InspectorState[]>) {
56+
for (const key in data) {
57+
if (!data[key]?.length)
58+
delete data[key]
59+
}
60+
return data
61+
}
62+
63+
function getVeeValidateState(nodeId: string) {
64+
getInspectorState({ inspectorId, nodeId }).then((data) => {
65+
state.value = filterEmptyState(parse(data!))
66+
expandedStateNodes.value = Array.from({ length: Object.keys(state.value).length }, (_, i) => `${i}`)
67+
})
68+
}
69+
70+
function clearVeeValidateState() {
71+
state.value = {}
72+
}
73+
74+
watch(selected, () => {
75+
clearVeeValidateState()
76+
getVeeValidateState(selected.value)
77+
})
78+
79+
const getVeeValidateInspectorTree = () => {
80+
getInspectorTree({ inspectorId, filter: '' }).then((_data) => {
81+
const data = parse(_data!)
82+
tree.value = data
83+
if (!selected.value && data.length) {
84+
selected.value = data[0].id
85+
getVeeValidateState(data[0].id)
86+
}
87+
})
88+
}
89+
getVeeValidateInspectorTree()
90+
91+
onInspectorTreeUpdated((data) => {
92+
if (!data?.data.length || data.inspectorId !== inspectorId)
93+
return
94+
tree.value = data.data as unknown as { id: string, label: string, tags: InspectorNodeTag[] }[]
95+
if ((!selected.value && data.data.length) || (selected.value && !data.data.find(node => node.id === selected.value))) {
96+
selected.value = data.data[0].id
97+
getVeeValidateState(data.data[0].id)
98+
}
99+
})
100+
101+
onInspectorStateUpdated((data) => {
102+
if (!data || data.inspectorId !== inspectorId)
103+
return
104+
105+
const { inspectorId: _inspectorId, ...filtered } = data
106+
107+
state.value = filterEmptyState(filtered)
108+
expandedStateNodes.value = Array.from({ length: Object.keys(state.value).length }, (_, i) => `${i}`)
109+
})
110+
</script>
111+
112+
<template>
113+
<div class="h-full flex flex-col">
114+
<DevToolsHeader doc-link="https://vee-validate.logaretm.com/v4/" github-repo-link="https://github.com/logaretm/vee-validate/">
115+
<Navbar />
116+
</DevToolsHeader>
117+
<template v-if="tree.length">
118+
<Splitpanes class="flex-1 overflow-auto">
119+
<Pane border="r base" size="40" h-full>
120+
<div h-full select-none overflow-scroll class="no-scrollbar">
121+
<div v-if="actions.length" class="w-full px2 pt2">
122+
<div class="w-full flex justify-end pb1" border="b dashed base">
123+
<div class="flex items-center gap-2 px-1">
124+
<div v-for="(action, index) in actions" :key="index" v-tooltip.bottom-end="{ content: action.tooltip }" class="flex items-center gap1" @click="callAction(index)">
125+
<i :class="`i-ic-baseline-${action.icon.replace(/\_/g, '-')}`" cursor-pointer op70 text-base hover:op100 />
126+
</div>
127+
</div>
128+
</div>
129+
</div>
130+
<SelectiveList v-model="selected" :data="tree" />
131+
</div>
132+
</Pane>
133+
<Pane size="60">
134+
<div class="h-full flex flex-col p2">
135+
<div v-if="nodeActions.length" class="flex justify-end pb-1" border="b dashed base">
136+
<div class="flex items-center gap-2 px-1">
137+
<div v-for="(action, index) in nodeActions" :key="index" v-tooltip.bottom-end="{ content: action.tooltip }" class="flex items-center gap1" @click="callNodeAction(index)">
138+
<i :class="`i-ic-baseline-${action.icon.replace(/\_/g, '-')}`" cursor-pointer op70 text-base hover:op100 />
139+
</div>
140+
</div>
141+
</div>
142+
<RootStateViewer v-if="selected && !emptyState" :data="state" :node-id="selected" :inspector-id="inspectorId" expanded-state-id="vee-validate-state" class="no-scrollbar flex-1 select-none overflow-scroll" />
143+
<Empty v-else>
144+
No Data
145+
</Empty>
146+
</div>
147+
</Pane>
148+
</Splitpanes>
149+
</template>
150+
<Empty v-else>
151+
No Data
152+
</Empty>
153+
</div>
154+
</template>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<script setup lang="ts">
2+
import Timeline from '~/components/timeline/index.vue'
3+
4+
const LAYER_IDS = ['vee-validate-inspector']
5+
</script>
6+
7+
<template>
8+
<Timeline :layer-ids="LAYER_IDS" doc-link="https://vee-validate.logaretm.com/v4/" github-repo-link="https://github.com/logaretm/vee-validate/" />
9+
</template>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import VeeValidate from './index.vue'
2+
3+
export {
4+
VeeValidate,
5+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<script setup lang="ts">
2+
import Home from './components/Home.vue'
3+
import State from './components/state/Index.vue'
4+
import { registerVirtualRouter } from '~/composables/virtual-router'
5+
import { createDevToolsConnectStateContext } from '~/composables/connect-state'
6+
7+
createDevToolsConnectStateContext()
8+
9+
const { VirtualRouterView } = registerVirtualRouter([
10+
{
11+
path: '/',
12+
name: 'Home',
13+
component: Home,
14+
icon: 'https://vee-validate.logaretm.com/v4/logo.png',
15+
},
16+
{
17+
path: '/state',
18+
name: 'State',
19+
component: State,
20+
icon: 'i-carbon-tree-view-alt',
21+
},
22+
// {
23+
// path: '/timeline',
24+
// name: 'Timeline',
25+
// component: Timeline,
26+
// icon: 'i-mdi:timeline-clock-outline',
27+
// },
28+
])
29+
</script>
30+
31+
<template>
32+
<div h-full w-full>
33+
<VirtualRouterView />
34+
</div>
35+
</template>

packages/applet/src/modules/vue-query/components/state/Index.vue

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script setup lang="ts">
22
import { computed, ref, watch } from 'vue'
33
import { Pane, Splitpanes } from 'splitpanes'
4-
import { callInspectorNodeAction, getInspectorNodeActions, getInspectorState, getInspectorTree, onInspectorStateUpdated, onInspectorTreeUpdated } from '@vue/devtools-core'
4+
import { callInspectorAction, callInspectorNodeAction, getInspectorActions, getInspectorNodeActions, getInspectorState, getInspectorTree, onInspectorStateUpdated, onInspectorTreeUpdated } from '@vue/devtools-core'
55
import { parse } from '@vue/devtools-kit'
66
import type { InspectorNodeTag, InspectorState } from '@vue/devtools-kit'
77
import { vTooltip } from '@vue/devtools-ui'
@@ -21,6 +21,7 @@ interface NodeAction {
2121
}
2222
const inspectorId = 'vue-query'
2323
const nodeActions = ref<NodeAction[]>([])
24+
const actions = ref<NodeAction[]>([])
2425
2526
const selected = ref('')
2627
const tree = ref<{ id: string, label: string, tags: InspectorNodeTag[] }[]>([])
@@ -33,12 +34,24 @@ function getNodeActions() {
3334
})
3435
}
3536
37+
function getActions() {
38+
getInspectorActions(inspectorId).then((_actions) => {
39+
actions.value = _actions as NodeAction[]
40+
})
41+
}
42+
3643
getNodeActions()
3744
45+
getActions()
46+
3847
function callNodeAction(index: number) {
3948
callInspectorNodeAction(inspectorId, index, selected.value)
4049
}
4150
51+
function callAction(index: number) {
52+
callInspectorAction(inspectorId, index, selected.value)
53+
}
54+
4255
function filterEmptyState(data: Record<string, InspectorState[]>) {
4356
for (const key in data) {
4457
if (!data[key]?.length)
@@ -88,8 +101,9 @@ onInspectorTreeUpdated((data) => {
88101
onInspectorStateUpdated((data) => {
89102
if (!data || data.inspectorId !== inspectorId)
90103
return
104+
const { inspectorId: _inspectorId, ...filtered } = data
91105
92-
state.value = filterEmptyState(data as any)
106+
state.value = filterEmptyState(filtered)
93107
expandedStateNodes.value = Array.from({ length: Object.keys(state.value).length }, (_, i) => `${i}`)
94108
})
95109
</script>
@@ -103,12 +117,19 @@ onInspectorStateUpdated((data) => {
103117
<Splitpanes class="flex-1 overflow-auto">
104118
<Pane border="r base" size="40" h-full>
105119
<div h-full select-none overflow-scroll class="no-scrollbar">
120+
<div v-if="actions.length" class="flex justify-end pb-1" border="b dashed base">
121+
<div class="flex items-center gap-2 px-1">
122+
<div v-for="(action, index) in actions" :key="index" v-tooltip.bottom-end="{ content: action.tooltip }" class="flex items-center gap1" @click="callAction(index)">
123+
<i :class="`i-ic-baseline-${action.icon.replace(/\_/g, '-')}`" cursor-pointer op70 text-base hover:op100 />
124+
</div>
125+
</div>
126+
</div>
106127
<SelectiveList v-model="selected" :data="tree" />
107128
</div>
108129
</Pane>
109130
<Pane size="60">
110131
<div class="h-full flex flex-col p2">
111-
<div class="flex justify-end pb-1" border="b dashed base">
132+
<div v-if="nodeActions.length" class="flex justify-end pb-1" border="b dashed base">
112133
<div class="flex items-center gap-2 px-1">
113134
<div v-for="(action, index) in nodeActions" :key="index" v-tooltip.bottom-end="{ content: action.tooltip }" class="flex items-center gap1" @click="callNodeAction(index)">
114135
<i :class="`i-ic-baseline-${action.icon.replace(/\_/g, '-')}`" cursor-pointer op70 text-base hover:op100 />

packages/applet/uno.config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,5 +67,7 @@ export default defineConfig(mergeConfigs([unoConfig, {
6767
'i-ic-baseline-settings-backup-restore',
6868
'i-ic-baseline-hourglass-empty',
6969
'i-ic-baseline-error-outline',
70+
'i-ic-baseline-done-outline',
71+
'i-ic-baseline-delete-sweep',
7072
],
7173
}])) as any

packages/client/src/components/pages/RoutePathItem.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const emit = defineEmits<{
1111
}>()
1212
1313
function parseExpressRoute(route: string) {
14-
return route.split(/(:\w+[\?\*]?)/).filter(Boolean)
14+
return route.split(/(:\w+[?*]?)/).filter(Boolean)
1515
}
1616
1717
const partsInput = ref<string[]>([])

0 commit comments

Comments
 (0)