@@ -18,6 +18,10 @@ const afterTotalWidth = computed(() => {
1818 return calculateTotalSectionsDuration (props .after );
1919});
2020
21+ const maxTotalWidth = computed (() => {
22+ return Math .max (beforeTotalWidth .value , afterTotalWidth .value );
23+ });
24+
2125const SECTIONS_PALETTE = [
2226 " #7768AE" ,
2327 " #FFCf96" ,
@@ -35,35 +39,61 @@ function calculate_width(value: number, totalDuration: number): string {
3539 return ` ${(fraction * 100 ).toFixed (2 )}% ` ;
3640}
3741
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+
3853function formatPercent(
3954 sections : CompilationSections ,
4055 sectionName : string
4156): 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 ;
4560 const total = calculateTotalSectionsDuration (sections );
4661 const percent = (value / total ) * 100 ;
4762 return ` ${percent .toFixed (2 )}% ` ;
4863}
4964
65+ function getRowWidth(): number {
66+ return maxTotalWidth .value ;
67+ }
68+
5069const chartRows: ComputedRef <Array <[string , CompilationSections ]>> = computed (
5170 () => [
5271 [" Before" , props .before ],
5372 [" After" , props .after ],
5473 ]
5574);
5675const 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+ }>
5884> = computed (() => {
5985 const items = [];
6086 for (const section of props .before .sections ) {
6187 items .push ({
6288 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+ " ??" ,
6797 color: getSectionColor (items .length ),
6898 });
6999 }
@@ -81,52 +111,81 @@ function deactivate() {
81111 </script >
82112
83113<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" >
102120 <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+ }"
105129 >
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 >
112158 </div >
113159 </div >
114160 </div >
115161 </div >
116162 </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 >
130189 </div >
131190 </div >
132191 </div >
@@ -135,11 +194,12 @@ function deactivate() {
135194<style scoped lang="scss">
136195.wrapper {
137196 display : flex ;
197+ align-items : center ;
138198}
139199.chart {
140200 display : flex ;
141201 justify-content : flex-end ;
142- width : 600 px ;
202+ width : 500 px ;
143203
144204 & :first-child {
145205 margin-bottom : 10px ;
@@ -173,10 +233,6 @@ function deactivate() {
173233 }
174234}
175235
176- .active {
177- box-shadow : inset 0 0 1px 2px #000 ;
178- }
179-
180236.section :first-child {
181237 border-radius : 5px 0 0 5px ;
182238}
@@ -187,17 +243,26 @@ function deactivate() {
187243.legend {
188244 margin-left : 40px ;
189245
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 ;
200250 }
201251 }
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 ;
202267}
203268 </style >
0 commit comments