Skip to content
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
4 changes: 3 additions & 1 deletion packages/vite/src/app/components/chunks/BaseInfo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import { computed } from 'vue'
const props = withDefaults(defineProps<{
chunk: RolldownChunkInfo | RolldownChunkImport
link?: boolean
basic?: boolean
}>(), {
link: false,
basic: false,
})
const route = useRoute()
const normalizedImports = computed(() => Array.isArray(props.chunk.imports) ? props.chunk.imports.length : props.chunk.imports)
Expand All @@ -32,7 +34,7 @@ const normalizedModules = computed(() => Array.isArray(props.chunk.modules) ? pr

<div flex-auto />

<div flex="~ items-center gap-2">
<div v-if="!basic" flex="~ items-center gap-2">
<span op50 font-mono>#{{ chunk.chunk_id }}</span>
<div flex="~ gap-1 items-center" :title="`${normalizedImports} imports`">
<div i-ph-file-arrow-up-duotone />
Expand Down
17 changes: 13 additions & 4 deletions packages/vite/src/app/components/chunks/FlatList.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
<script setup lang="ts">
import type { RolldownChunkInfo, SessionContext } from '~~/shared/types'

defineProps<{
chunks: RolldownChunkInfo[]
withDefaults(defineProps<{
chunks: Array<RolldownChunkInfo & { id: string }>
session: SessionContext
link?: boolean
basic?: boolean
}>(), {
link: true,
basic: false,
})

const emit = defineEmits<{
(e: 'select', chunk: RolldownChunkInfo & { id: string }): void
}>()
</script>

Expand All @@ -13,8 +22,8 @@ defineProps<{
key-prop="chunk_id"
>
<template #default="{ item }">
<div flex pb2>
<ChunksBaseInfo :chunk="item" link w-full font-mono border="~ rounded base" px2 py1 text-sm hover="bg-active" flex="~ gap-4 items-center">
<div flex pb2 @click="emit('select', item)">
<ChunksBaseInfo :chunk="item" :basic="basic" :link="link" w-full font-mono border="~ rounded base" px2 py1 text-sm hover="bg-active" flex="~ gap-4 items-center">
<template #left-after>
<DisplayBadge v-if="item.is_initial" text="initial" />
</template>
Expand Down
9 changes: 6 additions & 3 deletions packages/vite/src/app/components/chunks/Graph.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ import { createModuleGraph } from '~/composables/moduleGraph'
type ChunkInfo = RolldownChunkInfo & {
id: string
}
const props = defineProps<{
const props = withDefaults(defineProps<{
session: SessionContext
chunks: ChunkInfo[]
}>()
entryId?: string
}>(), {
entryId: '',
})

const chunks = computed(() => props.chunks)
const route = useRoute()
Expand All @@ -32,7 +35,7 @@ createModuleGraph<ChunkInfo, ChunkImport>({
width.value = window.innerWidth
height.value = window.innerHeight

const entryChunks = chunks.value.filter(chunk => chunk.reason === 'entry')
const entryChunks = chunks.value.filter(chunk => props.entryId ? chunk.id === props.entryId : chunk.reason === 'entry')

const seen = new Set<ChunkInfo>()
const root = hierarchy<ModuleGraphNode<ChunkInfo, ChunkImport>>(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,52 +1,66 @@
<script setup lang="ts">
import type { ModuleListItem, SessionContext } from '~~/shared/types'
<script setup lang="ts" generic="T extends { id:string, imports: Record<string, unknown>[] }">
import type { SessionContext } from '~~/shared/types'
import type { GraphPathSelector } from '~/composables/graph-path-selector'
import { computed, watch } from 'vue'
import { useModulePathSelector } from '~/composables/moduleGraph'
import { useGraphPathSelector } from '~/composables/graph-path-selector'

const props = defineProps<{
session: SessionContext
modules: ModuleListItem[]
data: T[]
importIdKey: string
searchKeys?: string[]
}>()

const emit = defineEmits<{
(e: 'close'): void
(e: 'select', nodes: { start: string, end: string }): void
}>()

const modulesMap = computed(() => {
const map = new Map<string, ModuleListItem>()
props.modules.forEach((m) => {
defineSlots<{
list: (props: {
select: (module: T) => void
data: T[]
}) => void
item: (props: {
id: string
}) => void
}>()

const dataMap = computed(() => {
const map = new Map<string, T>()
props.data.forEach((m) => {
map.set(m.id, m)
})
return map
})

const startSelector = useModulePathSelector({
const startSelector: GraphPathSelector<T> = useGraphPathSelector<T>({
searchKeys: props.searchKeys,
getModules: () => {
if (!startSelector.state.value.search) {
return props.modules
return props.data
}
else {
return startSelector.fuse.value!.value?.search(startSelector.state.value.search).map(r => r.item) ?? []
}
},
})

startSelector.initSelector(computed(() => props.modules))
startSelector.initSelector(computed(() => props.data))

function getAllImports(moduleId: string, visited = new Set<string>()): ModuleListItem[] {
function getAllImports(moduleId: string, visited = new Set<string>()): T[] {
if (visited.has(moduleId))
return []
visited.add(moduleId)

const module = modulesMap.value.get(moduleId)
const module = dataMap.value.get(moduleId)
if (!module?.imports?.length)
return []

const res: ModuleListItem[] = []
const res: T[] = []

for (const importItem of module.imports) {
const importedModule = modulesMap.value.get(importItem.module_id)
const importedModule = dataMap.value.get(`${importItem[props.importIdKey]}`)
if (!importedModule)
continue

Expand All @@ -59,7 +73,8 @@ function getAllImports(moduleId: string, visited = new Set<string>()): ModuleLis
return res
}

const endSelector = useModulePathSelector({
const endSelector = useGraphPathSelector<T>({
searchKeys: props.searchKeys,
getModules: () => {
return startSelector.state.value.selected ? getAllImports(startSelector.state.value.selected) : []
},
Expand All @@ -82,39 +97,60 @@ watch([() => startSelector.state.value.selected, () => endSelector.state.value.s
end: endSelector.state.value.selected ?? '',
})
})

function close() {
emit('select', {
start: '',
end: '',
})
emit('close')
}
</script>

<template>
<div h12 px4 p2 relative flex="~ gap2 items-center">
<div flex="~ items-center gap2" class="flex-1" min-w-0>
<ModulesPathSelectorItem
<div h10 px4 p1 relative flex="~ gap2 items-center">
<div flex="~ items-center gap2" class="flex-1 h-full" min-w-0>
<DataPathSelectorItem
v-model:search="startSelector.state.value.search"
placeholder="Start"
:selector="startSelector"
:session="session"
:modules="startSelector.modules.value"
:data="startSelector.modules.value"
@clear="() => { startSelector.clear(); endSelector.clear() }"
/>
>
<template #list>
<slot name="list" :select="startSelector.select" :data="startSelector.modules.value" />
</template>
<template #item>
<slot :id="startSelector.state.value.selected!" name="item" />
</template>
</DataPathSelectorItem>
<div class="i-carbon-arrow-right op50" flex-shrink-0 />

<ModulesPathSelectorItem
<DataPathSelectorItem
v-model:search="endSelector.state.value.search"
placeholder="End"
:selector="endSelector"
:session="session"
:modules="filteredEndModules"
:data="filteredEndModules"
@clear="endSelector.clear"
>
<template #list>
<slot name="list" :select="endSelector.select" :data="filteredEndModules" />
</template>
<template #item>
<slot :id="endSelector.state.value.selected!" name="item" />
</template>
<template #empty>
<div flex="~ items-center justify-center" w-full h-20>
<span italic op50>
{{ startSelector.state.value.selected ? 'No modules' : 'Select a start module to get end modules' }}
</span>
</div>
</template>
</ModulesPathSelectorItem>
</DataPathSelectorItem>
</div>

<DisplayCloseButton class="mr--2" @click="emit('close')" />
<DisplayCloseButton class="mr--2" @click="close" />
</div>
</template>
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
<script setup lang="ts">
import type { ModuleListItem, SessionContext } from '~~/shared/types'
import type { ModulePathSelector } from '~/composables/moduleGraph'
<script setup lang="ts" generic="T extends { id:string, imports: any[] }">
import type { SessionContext } from '~~/shared/types'
import type { GraphPathSelector } from '~/composables/graph-path-selector'
import { hideAllPoppers, Menu as VMenu } from 'floating-vue'

withDefaults(
defineProps<{
selector: ModulePathSelector
selector: GraphPathSelector<T>
placeholder: string
session: SessionContext
modules?: ModuleListItem[]
data?: T[]
emptyStateText?: string
onClear?: () => void
}>(),
{
modules: undefined,
data: undefined,
emptyStateText: undefined,
onClear: undefined,
},
Expand All @@ -23,40 +23,32 @@ const emit = defineEmits<{
(e: 'clear'): void
}>()

defineSlots<{
list: () => void
item: () => void
empty: () => void
}>()

const search = defineModel<string>('search', { required: true })
</script>

<template>
<div flex-1 w-0>
<div flex-1 w-0 h-full>
<div v-if="selector.state.value.selected" w-full overflow-hidden flex="~ items-center" border="~ base rounded" p1 relative>
<div overflow-hidden text-ellipsis pr6 py0.5 w-0 flex-1>
<DisplayModuleId
:id="selector.state.value.selected"
:session="session"
block text-nowrap
:link="false"
:disable-tooltip="true"
/>
<div overflow-hidden text-ellipsis pr6 w-0 flex-1>
<slot name="item" />
</div>
<button i-carbon-clean text-4 hover="op100" op50 title="Clear" absolute right-2 @click="emit('clear')" />
</div>
<VMenu v-else :distance="15" :triggers="['click']" :auto-hide="false" :delay="{ show: 300, hide: 150 }">
<VMenu v-else :distance="15" :triggers="['click']" :auto-hide="false" :delay="{ show: 300, hide: 150 }" class="h-full">
<input
v-model="search"
p1
px4 w-full border="~ base rounded-1" style="outline: none" :placeholder="placeholder"
py1 px4 w-full h-full border="~ base rounded-1" style="outline: none" :placeholder="placeholder"
@blur="hideAllPoppers"
>
<template #popper>
<div class="p2 w100" flex="~ col gap2">
<ModulesFlatList
v-if="modules?.length"
:session="session"
:modules="modules"
disable-tooltip
:link="false"
@select="selector.select"
/>
<slot v-if="data?.length" name="list" />
<slot v-else name="empty" />
</div>
</template>
Expand Down
Loading
Loading