@@ -18,6 +18,10 @@ const afterTotalWidth = computed(() => {
18
18
return calculateTotalSectionsDuration (props .after );
19
19
});
20
20
21
+ const maxTotalWidth = computed (() => {
22
+ return Math .max (beforeTotalWidth .value , afterTotalWidth .value );
23
+ });
24
+
21
25
const SECTIONS_PALETTE = [
22
26
" #7768AE" ,
23
27
" #FFCf96" ,
@@ -35,35 +39,61 @@ function calculate_width(value: number, totalDuration: number): string {
35
39
return ` ${(fraction * 100 ).toFixed (2 )}% ` ;
36
40
}
37
41
42
+ function getSectionByName(
43
+ sections : CompilationSections ,
44
+ name : string
45
+ ): CompilationSection | null {
46
+ const values = sections .sections .filter ((s ) => s .name === name );
47
+ if (values .length === 0 ) {
48
+ return null ;
49
+ }
50
+ return values [0 ];
51
+ }
52
+
38
53
function formatPercent(
39
54
sections : CompilationSections ,
40
55
sectionName : string
41
56
): string {
42
- const values = sections . sections . filter (( s ) => s . name === sectionName );
43
- if (values . length === 0 ) return " ??" ;
44
- const value = values [ 0 ] .value ;
57
+ const section = getSectionByName ( sections , sectionName );
58
+ if (section === null ) return " ??" ;
59
+ const value = section .value ;
45
60
const total = calculateTotalSectionsDuration (sections );
46
61
const percent = (value / total ) * 100 ;
47
62
return ` ${percent .toFixed (2 )}% ` ;
48
63
}
49
64
65
+ function getRowWidth(): number {
66
+ return maxTotalWidth .value ;
67
+ }
68
+
50
69
const chartRows: ComputedRef <Array <[string , CompilationSections ]>> = computed (
51
70
() => [
52
71
[" Before" , props .before ],
53
72
[" After" , props .after ],
54
73
]
55
74
);
56
75
const legendItems: ComputedRef <
57
- Array <{section: CompilationSection ; label: string ; color: string }>
76
+ Array <{
77
+ section: CompilationSection ;
78
+ color: string ;
79
+ beforePercent: string ;
80
+ beforeAbsolute: string ;
81
+ afterPercent: string ;
82
+ afterAbsolute: string ;
83
+ }>
58
84
> = computed (() => {
59
85
const items = [];
60
86
for (const section of props .before .sections ) {
61
87
items .push ({
62
88
section ,
63
- label: ` ${section .name } (${formatPercent (
64
- props .before ,
65
- section .name
66
- )} -> ${formatPercent (props .after , section .name )}) ` ,
89
+ beforePercent: formatPercent (props .before , section .name ),
90
+ beforeAbsolute:
91
+ getSectionByName (props .before , section .name )?.value ?.toLocaleString () ??
92
+ " ??" ,
93
+ afterPercent: formatPercent (props .after , section .name ),
94
+ afterAbsolute:
95
+ getSectionByName (props .after , section .name )?.value ?.toLocaleString () ??
96
+ " ??" ,
67
97
color: getSectionColor (items .length ),
68
98
});
69
99
}
@@ -81,52 +111,81 @@ function deactivate() {
81
111
</script >
82
112
83
113
<template >
84
- <div class =" wrapper" >
85
- <div class =" chart-wrapper" >
86
- <div class =" chart" v-for =" ([label, sections], rowIndex) in chartRows" >
87
- <span class =" label" >{{ label }}</span >
88
- <div class =" section-wrapper" >
89
- <div
90
- v-for =" (section, index) in sections.sections"
91
- :class =" {section: true, active: activeSection === section.name}"
92
- @mouseenter =" activate(section.name)"
93
- @mouseleave =" deactivate"
94
- :style =" {
95
- width: calculate_width(
96
- section.value,
97
- rowIndex == 0 ? beforeTotalWidth : afterTotalWidth
98
- ),
99
- backgroundColor: getSectionColor(index),
100
- }"
101
- >
114
+ <div >
115
+ <div class =" wrapper" >
116
+ <div class =" chart-wrapper" >
117
+ <div class =" chart" v-for =" ([label, sections], rowIndex) in chartRows" >
118
+ <span class =" label" >{{ label }}</span >
119
+ <div class =" section-wrapper" >
102
120
<div
103
- class =" description"
104
- v-if =" rowIndex == 1 && activeSection === section.name"
121
+ v-for =" (section, index) in sections.sections"
122
+ :class =" {section: true, active: activeSection === section.name}"
123
+ @mouseenter =" activate(section.name)"
124
+ @mouseleave =" deactivate"
125
+ :style =" {
126
+ width: calculate_width(section.value, getRowWidth()),
127
+ backgroundColor: getSectionColor(index),
128
+ }"
105
129
>
106
- <div >
107
- <b >{{ section.name }}</b >
108
- </div >
109
- <div >
110
- {{ formatPercent(props.before, section.name) }} ->
111
- {{ formatPercent(props.after, section.name) }}
130
+ <div
131
+ class =" description"
132
+ v-if =" rowIndex == 1 && activeSection === section.name"
133
+ >
134
+ <div >
135
+ <b >{{ section.name }}</b >
136
+ </div >
137
+ <div >
138
+ <div >
139
+ {{ formatPercent(props.before, section.name) }} ->
140
+ {{ formatPercent(props.after, section.name) }}
141
+ </div >
142
+ <div >
143
+ {{
144
+ getSectionByName(
145
+ props.before,
146
+ section.name
147
+ )?.value?.toLocaleString() ?? "??"
148
+ }}
149
+ ->
150
+ {{
151
+ getSectionByName(
152
+ props.after,
153
+ section.name
154
+ )?.value.toLocaleString() ?? "??"
155
+ }}
156
+ </div >
157
+ </div >
112
158
</div >
113
159
</div >
114
160
</div >
115
161
</div >
116
162
</div >
117
- </div >
118
- <div class =" legend" >
119
- <div
120
- class =" item"
121
- v-for =" item in legendItems"
122
- @mouseenter =" activate(item.section.name)"
123
- @mouseleave =" deactivate"
124
- >
125
- <div
126
- :class =" {color: true, active: activeSection === item.section.name}"
127
- :style =" {backgroundColor: item.color}"
128
- ></div >
129
- <div class =" name" >{{ item.label }}</div >
163
+ <div class =" legend" >
164
+ <table >
165
+ <thead >
166
+ <tr >
167
+ <th ></th >
168
+ <th >Section</th >
169
+ <th >Relative change</th >
170
+ <th >Absolute change</th >
171
+ </tr >
172
+ </thead >
173
+ <tbody >
174
+ <tr
175
+ v-for =" item in legendItems"
176
+ @mouseenter =" activate(item.section.name)"
177
+ @mouseleave =" deactivate"
178
+ :class =" {active: activeSection === item.section.name}"
179
+ >
180
+ <td >
181
+ <div class =" color" :style =" {backgroundColor: item.color}" ></div >
182
+ </td >
183
+ <td class =" name" >{{ item.section.name }}</td >
184
+ <td >{{ item.beforePercent }} -> {{ item.afterPercent }}</td >
185
+ <td >{{ item.beforeAbsolute }} -> {{ item.afterAbsolute }}</td >
186
+ </tr >
187
+ </tbody >
188
+ </table >
130
189
</div >
131
190
</div >
132
191
</div >
@@ -135,11 +194,12 @@ function deactivate() {
135
194
<style scoped lang="scss">
136
195
.wrapper {
137
196
display : flex ;
197
+ align-items : center ;
138
198
}
139
199
.chart {
140
200
display : flex ;
141
201
justify-content : flex-end ;
142
- width : 600 px ;
202
+ width : 500 px ;
143
203
144
204
& :first-child {
145
205
margin-bottom : 10px ;
@@ -173,10 +233,6 @@ function deactivate() {
173
233
}
174
234
}
175
235
176
- .active {
177
- box-shadow : inset 0 0 1px 2px #000 ;
178
- }
179
-
180
236
.section :first-child {
181
237
border-radius : 5px 0 0 5px ;
182
238
}
@@ -187,17 +243,26 @@ function deactivate() {
187
243
.legend {
188
244
margin-left : 40px ;
189
245
190
- .item {
191
- display : flex ;
192
- margin-bottom : 5px ;
193
-
194
- .color {
195
- width : 15px ;
196
- height : 15px ;
197
- }
198
- .name {
199
- margin-left : 5px ;
246
+ table {
247
+ td ,
248
+ th {
249
+ padding : 5px ;
200
250
}
201
251
}
252
+ .color {
253
+ width : 15px ;
254
+ height : 15px ;
255
+ }
256
+ .active {
257
+ font-weight : bold ;
258
+ }
259
+ .name {
260
+ margin-left : 5px ;
261
+ }
262
+ }
263
+
264
+ .active .color ,
265
+ .active.section {
266
+ box-shadow : inset 0 0 1px 2px #000 ;
202
267
}
203
268
</style >
0 commit comments