Skip to content

Commit 30b54dc

Browse files
committed
refactor: path selector
1 parent a905136 commit 30b54dc

File tree

4 files changed

+219
-221
lines changed

4 files changed

+219
-221
lines changed

packages/vite/src/app/components/modules/GraphNavigator.vue

Lines changed: 0 additions & 219 deletions
This file was deleted.
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
<script setup lang="ts">
2+
import type { ModuleListItem, SessionContext } from '~~/shared/types'
3+
import { hideAllPoppers, Menu as VMenu } from 'floating-vue'
4+
import { computed, watch } from 'vue'
5+
import { useModulePathSelector } from '~/composables/moduleGraph'
6+
7+
const props = defineProps<{
8+
session: SessionContext
9+
modules: ModuleListItem[]
10+
}>()
11+
12+
const emit = defineEmits<{
13+
(e: 'close'): void
14+
(e: 'select', nodes: { start: string, end: string }): void
15+
}>()
16+
17+
const modulesMap = computed(() => {
18+
const map = new Map<string, ModuleListItem>()
19+
props.modules.forEach((m) => {
20+
map.set(m.id, m)
21+
})
22+
return map
23+
})
24+
25+
const startSelector = useModulePathSelector({
26+
getModules: () => {
27+
if (!startSelector.state.value.search) {
28+
return props.modules
29+
}
30+
else {
31+
return startSelector.fuse.value!.value?.search(startSelector.state.value.search).map(r => r.item) ?? []
32+
}
33+
},
34+
})
35+
36+
startSelector.initSelector(computed(() => props.modules))
37+
38+
function getAllImports(moduleId: string, visited = new Set<string>()): ModuleListItem[] {
39+
if (visited.has(moduleId))
40+
return []
41+
visited.add(moduleId)
42+
43+
const module = modulesMap.value.get(moduleId)
44+
if (!module?.imports?.length)
45+
return []
46+
47+
const res: ModuleListItem[] = []
48+
49+
for (const importItem of module.imports) {
50+
const importedModule = modulesMap.value.get(importItem.module_id)
51+
if (!importedModule)
52+
continue
53+
54+
if (!visited.has(importedModule.id)) {
55+
res.push(importedModule)
56+
res.push(...getAllImports(importedModule.id, visited))
57+
}
58+
}
59+
60+
return res
61+
}
62+
63+
const endSelector = useModulePathSelector({
64+
getModules: () => {
65+
return startSelector.state.value.selected ? getAllImports(startSelector.state.value.selected) : []
66+
},
67+
})
68+
69+
endSelector.initSelector(endSelector.modules)
70+
71+
const filteredEndModules = computed(() => {
72+
if (!endSelector.state.value.search) {
73+
return endSelector.modules.value
74+
}
75+
else {
76+
return endSelector.fuse.value!.value?.search(endSelector.state.value.search).map(r => r.item) ?? []
77+
}
78+
})
79+
80+
watch([() => startSelector.state.value.selected, () => endSelector.state.value.selected], () => {
81+
emit('select', {
82+
start: startSelector.state.value.selected ?? '',
83+
end: endSelector.state.value.selected ?? '',
84+
})
85+
})
86+
</script>
87+
88+
<template>
89+
<div h12 px4 p2 relative flex="~ gap2 items-center">
90+
<div flex="~ items-center gap2" class="flex-1" min-w-0>
91+
<div flex-1 w-0>
92+
<div v-if="startSelector.state.value.selected" w-full overflow-hidden flex="~ items-center" border="~ base rounded" p1 relative>
93+
<div overflow-hidden text-ellipsis pr6 py0.5 w-0 flex-1>
94+
<DisplayModuleId
95+
:id="startSelector.state.value.selected"
96+
:session="session"
97+
block text-nowrap
98+
:link="false"
99+
:disable-tooltip="true"
100+
/>
101+
</div>
102+
<button i-carbon-clean text-4 hover="op100" op50 title="Clear" absolute right-2 @click="startSelector.clear" />
103+
</div>
104+
<VMenu v-else :distance="15" :triggers="['click']" :auto-hide="false" :delay="{ show: 300, hide: 150 }">
105+
<input
106+
v-model="startSelector.state.value.search"
107+
p1 px4 w-full border="~ base rounded-1" style="outline: none"
108+
placeholder="Start"
109+
@blur="hideAllPoppers"
110+
>
111+
<template #popper>
112+
<div class="p2 w100" flex="~ col gap2">
113+
<ModulesFlatList
114+
:session="session"
115+
:modules="startSelector.modules.value"
116+
disable-tooltip
117+
:link="false"
118+
@select="startSelector.select"
119+
/>
120+
</div>
121+
</template>
122+
</VMenu>
123+
</div>
124+
<div class="i-carbon-arrow-right op50" flex-shrink-0 />
125+
126+
<div flex-1 w-0>
127+
<div v-if="endSelector.state.value.selected" w-full overflow-hidden flex="~ items-center" border="~ base rounded" p1 relative>
128+
<div overflow-hidden text-ellipsis pr6 py0.5 w-0 flex-1>
129+
<DisplayModuleId
130+
:id="endSelector.state.value.selected"
131+
:session="session"
132+
block text-nowrap
133+
:link="false"
134+
:disable-tooltip="true"
135+
/>
136+
</div>
137+
<button i-carbon-clean text-4 hover="op100" op50 title="Clear" absolute right-2 @click="() => { startSelector.clear() ; endSelector.clear() }" />
138+
</div>
139+
<VMenu v-else :distance="15" :triggers="['click']" :auto-hide="false" :delay="{ show: 300, hide: 150 }">
140+
<input
141+
v-model="endSelector.state.value.search"
142+
p1 px4 w-full border="~ base rounded-1" style="outline: none"
143+
placeholder="End"
144+
@blur="hideAllPoppers"
145+
>
146+
<template #popper>
147+
<div class="p2 w100" flex="~ col gap2">
148+
<ModulesFlatList
149+
v-if="filteredEndModules.length"
150+
:session="session"
151+
:modules="filteredEndModules"
152+
disable-tooltip
153+
:link="false"
154+
@select="endSelector.select"
155+
/>
156+
<div v-else flex="~ items-center justify-center" w-full h-20>
157+
<span italic op50>
158+
{{ startSelector.state.value.selected ? 'No modules' : 'Select a start module to get end modules' }}
159+
</span>
160+
</div>
161+
</div>
162+
</template>
163+
</VMenu>
164+
</div>
165+
</div>
166+
167+
<DisplayCloseButton class="mr--2" @click="emit('close')" />
168+
</div>
169+
</template>

0 commit comments

Comments
 (0)