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
201 changes: 106 additions & 95 deletions packages/rolldown/src/app/components/data/PluginDetailsTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -82,108 +82,119 @@ function toggleDurationSortType() {
</script>

<template>
<div role="table" min-w-max>
<div role="row" class="sticky top-0 z10 border-b border-base" flex="~ row">
<div v-if="selectedFields.includes('hookName')" role="columnheader" bg-base flex-none w32 ws-nowrap p1 text-center font-600>
Hook name
</div>
<div v-if="selectedFields.includes('module')" role="columnheader" bg-base flex-1 min-w100 ws-nowrap p1 text-left font-600>
<button flex="~ row gap1 items-center" w-full>
Module
<VMenu>
<DataVirtualList
v-if="filtered.length && selectedFields.length"
class="plugin-details-table"
role="table"
min-w-max h-full min-h-0
:items="filtered"
key-prop="id"
:page-mode="false"
>
<template #before>
<div role="row" class="border-b border-base bg-base" flex="~ row">
<div v-if="selectedFields.includes('hookName')" role="columnheader" bg-base flex-none w32 ws-nowrap p1 text-center font-600>
Hook name
</div>
<div v-if="selectedFields.includes('module')" role="columnheader" bg-base flex-1 min-w100 ws-nowrap p1 text-left font-600>
<button flex="~ row gap1 items-center" w-full>
Module
<VMenu>
<span w-6 h-6 rounded-full cursor-pointer hover="bg-active" flex="~ items-center justify-center">
<i text-xs class="i-ph-funnel-duotone" :class="filterModuleTypes.length !== searchFilterTypes.length ? 'text-primary op100' : 'op50'" />
</span>
<template #popper>
<div class="p2" flex="~ col gap2">
<label
v-for="rule of searchFilterTypes"
:key="rule.name"
border="~ base rounded-md" px2 py1
flex="~ items-center gap-1"
select-none
:title="rule.description"
class="cursor-pointer module-type-filter"
>
<input
type="checkbox"
mr1
:checked="filterModuleTypes?.includes(rule.name)"
@change="toggleModuleType(rule)"
>
<div :class="rule.icon" icon-catppuccin />
<div text-sm>{{ rule.description || rule.name }}</div>
</label>
</div>
</template>
</VMenu>
</button>
</div>
<div v-if="selectedFields.includes('duration')" role="columnheader" rounded-tr-2 bg-base flex-none ws-nowrap p1 text-center font-600 w-27>
<button flex="~ row gap1 items-center justify-center" w-full @click="toggleDurationSortType">
Duration
<span w-6 h-6 rounded-full cursor-pointer hover="bg-active" flex="~ items-center justify-center">
<i text-xs class="i-ph-funnel-duotone" :class="filterModuleTypes.length !== searchFilterTypes.length ? 'text-primary op100' : 'op50'" />
<i text-xs :class="[durationSortType !== 'asc' ? 'i-ph-arrow-down-duotone' : 'i-ph-arrow-up-duotone', durationSortType ? 'op100 text-primary' : 'op50']" />
</span>
<template #popper>
<div class="p2" flex="~ col gap2">
<label
v-for="rule of searchFilterTypes"
:key="rule.name"
border="~ base rounded-md" px2 py1
flex="~ items-center gap-1"
select-none
:title="rule.description"
class="cursor-pointer module-type-filter"
>
<input
type="checkbox"
mr1
:checked="filterModuleTypes?.includes(rule.name)"
@change="toggleModuleType(rule)"
>
<div :class="rule.icon" icon-catppuccin />
<div text-sm>{{ rule.description || rule.name }}</div>
</label>
</div>
</template>
</VMenu>
</button>
</div>
<div v-if="selectedFields.includes('duration')" role="columnheader" rounded-tr-2 bg-base flex-none ws-nowrap p1 text-center font-600 w-27>
<button flex="~ row gap1 items-center justify-center" w-full @click="toggleDurationSortType">
Duration
<span w-6 h-6 rounded-full cursor-pointer hover="bg-active" flex="~ items-center justify-center">
<i text-xs :class="[durationSortType !== 'asc' ? 'i-ph-arrow-down-duotone' : 'i-ph-arrow-up-duotone', durationSortType ? 'op100 text-primary' : 'op50']" />
</span>
</button>
</div>
<div v-if="selectedFields.includes('startTime')" role="columnheader" rounded-tr-2 bg-base flex-none min-w52 ws-nowrap p1 text-center font-600>
Start Time
</div>
<div v-if="selectedFields.includes('endTime')" role="columnheader" rounded-tr-2 bg-base flex-none min-w52 ws-nowrap p1 text-center font-600>
End Time
</button>
</div>
<div v-if="selectedFields.includes('startTime')" role="columnheader" rounded-tr-2 bg-base flex-none min-w52 ws-nowrap p1 text-center font-600>
Start Time
</div>
<div v-if="selectedFields.includes('endTime')" role="columnheader" rounded-tr-2 bg-base flex-none min-w52 ws-nowrap p1 text-center font-600>
End Time
</div>
</div>
</div>
</template>

<DataVirtualList
v-if="filtered.length && selectedFields.length"
role="rowgroup"
:items="filtered"
key-prop="id"
>
<template #default="{ item, index }">
<div
role="row"
flex="~ row"
class="border-base border-b border-dashed"
:class="[index === filtered.length - 1 ? 'border-b-0' : '']"
>
<div v-if="selectedFields.includes('hookName')" role="cell" flex="~ items-center justify-center" flex-none w32 ws-nowrap op80>
<DisplayBadge :text="HOOK_NAME_MAP[item.type]" />
</div>
<div v-if="selectedFields.includes('module')" role="cell" flex-1 min-w100 text-left text-ellipsis line-clamp-2>
<DisplayModuleId
:id="item.module"
w-full border-none ws-nowrap
:session="session"
:link="`/session/${session.id}/graph?module=${item.module}`"
hover="bg-active"
border="~ base rounded" block px2 py1
/>
</div>
<div v-if="selectedFields.includes('duration')" role="cell" flex="~ items-center justify-center" flex-none text-center text-sm w-27>
<DisplayDuration :duration="item.duration" />
</div>
<div v-if="selectedFields.includes('startTime')" role="cell" flex="~ items-center justify-center" flex-none text-center font-mono text-sm min-w52 op80>
{{ normalizeTimestamp(item.timestamp_start) }}
</div>
<div v-if="selectedFields.includes('endTime')" role="cell" flex="~ items-center justify-center" flex-none text-center font-mono text-sm min-w52 op80>
{{ normalizeTimestamp(item.timestamp_end) }}
</div>
<template #default="{ item, index }">
<div
role="row"
flex="~ row"
class="border-base border-b border-dashed"
:class="[index === filtered.length - 1 ? 'border-b-0' : '']"
>
<div v-if="selectedFields.includes('hookName')" role="cell" flex="~ items-center justify-center" flex-none w32 ws-nowrap op80>
<DisplayBadge :text="HOOK_NAME_MAP[item.type]" />
</div>
<div v-if="selectedFields.includes('module')" role="cell" flex-1 min-w100 text-left text-ellipsis line-clamp-2>
<DisplayModuleId
:id="item.module"
w-full border-none ws-nowrap
:session="session"
:link="`/session/${session.id}/graph?module=${item.module}`"
hover="bg-active"
border="~ base rounded" block px2 py1
/>
</div>
<div v-if="selectedFields.includes('duration')" role="cell" flex="~ items-center justify-center" flex-none text-center text-sm w-27>
<DisplayDuration :duration="item.duration" />
</div>
</template>
</DataVirtualList>
<div v-else>
<div p4>
<div w-full h-48 flex="~ items-center justify-center" op50 italic>
<p v-if="!selectedFields.length">
No columns selected
</p>
<p v-else>
No data
</p>
<div v-if="selectedFields.includes('startTime')" role="cell" flex="~ items-center justify-center" flex-none text-center font-mono text-sm min-w52 op80>
{{ normalizeTimestamp(item.timestamp_start) }}
</div>
<div v-if="selectedFields.includes('endTime')" role="cell" flex="~ items-center justify-center" flex-none text-center font-mono text-sm min-w52 op80>
{{ normalizeTimestamp(item.timestamp_end) }}
</div>
</div>
</template>
</DataVirtualList>
<div v-else role="table" min-w-max h-full>
<div p4>
<div w-full h-48 flex="~ items-center justify-center" op50 italic>
<p v-if="!selectedFields.length">
No columns selected
</p>
<p v-else>
No data
</p>
</div>
</div>
</div>
</template>

<style scoped>
.plugin-details-table:deep(.vue-recycle-scroller__slot) {
position: sticky;
top: 0;
z-index: 10;
}
</style>
4 changes: 2 additions & 2 deletions packages/rolldown/src/app/components/flowmap/PluginFlow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ function toggleShowType() {
</template>
</FlowmapPluginFlowTimeline>
</div>
<div flex-1 of-y-auto h-full flex="~ col">
<div flex-1 h-full min-h-0 flex="~ col">
<div flex="~ items-center justify-between" border="b base" px2 h10 bg-base rounded-t-2 of-x-auto ws-nowrap>
<div flex="~ items-center" h-full>
<button v-if="!expanded" w8 h8 rounded-full cursor-pointer mr1 hover="bg-active" flex="~ items-center justify-center" @click="toggleExpanded(true)">
Expand All @@ -137,7 +137,7 @@ function toggleShowType() {
</button>
</div>
</div>
<div flex-1 of-y-auto overscroll-contain>
<div flex-1 min-h-0 overscroll-contain>
<DataPluginDetailsTable
:session="session"
:build-metrics="buildMetrics"
Expand Down
36 changes: 22 additions & 14 deletions packages/ui/src/components/DataVirtualList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@
import { DynamicScroller, DynamicScrollerItem } from 'vue-virtual-scroller'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'

defineProps<{
withDefaults(defineProps<{
items: T[]
keyProp: keyof T
}>()
pageMode?: boolean
}>(), {
pageMode: true,
})

defineSlots<{
before?: () => void
default: (props: {
item: T
index: number
Expand All @@ -18,23 +22,27 @@ defineSlots<{

<template>
<DynamicScroller
v-slot="{ item, active, index }"
:items="items"
:min-item-size="30"
:key-field="(keyProp as string)"
page-mode
:page-mode="pageMode"
>
<DynamicScrollerItem
:item="(item as T)"
:active="active"
:data-index="index"
>
<slot
v-bind="{ key: (item as T)[keyProp] }"
<template #before>
<slot name="before" />
</template>
<template #default="{ item, active, index }">
<DynamicScrollerItem
:item="(item as T)"
:index="index"
:active="active"
/>
</DynamicScrollerItem>
:data-index="index"
>
<slot
v-bind="{ key: (item as T)[keyProp] }"
:item="(item as T)"
:index="index"
:active="active"
/>
</DynamicScrollerItem>
</template>
</DynamicScroller>
</template>
Loading