@@ -45,8 +45,9 @@ export function calculateAttributeArea(baseBounds: RectBounds, renderSettings: A
4545 if ( widthType === '%' ) {
4646 width = trackWidth * 0.01 * renderSettings . displayWidth . val ;
4747 }
48+ const leftAnchored = [ 'SW' , 'NW' ] . includes ( renderSettings ?. corner || '' ) ;
4849 // calculate center position for point
49- const displayX = baseBounds [ 2 ] + 0.5 * width ;
50+ const displayX = leftAnchored ? ( baseBounds [ 0 ] - 0.5 * width ) : ( baseBounds [ 2 ] + 0.5 * width ) ;
5051 const valueX = displayX ;
5152 // Calcualte Y Position
5253 const trackHeight = baseBounds [ 3 ] - baseBounds [ 1 ] ;
@@ -58,12 +59,19 @@ export function calculateAttributeArea(baseBounds: RectBounds, renderSettings: A
5859 if ( heightType === '%' ) {
5960 height = trackHeight * 0.01 * renderSettings . displayHeight . val ;
6061 }
61- // So I think we want to set Display/Value
62- const displayHeight = baseBounds [ 1 ] + ( height * renderIndex ) + height * ( 1 / 3 ) ;
63- const valueHeight = baseBounds [ 1 ] + ( height * renderIndex ) + height * ( 2 / 3 ) ;
62+ const bottomAnchored = [ 'SW' , 'SE' ] . includes ( renderSettings ?. corner || '' ) ;
63+ const topY = bottomAnchored
64+ ? ( baseBounds [ 3 ] - ( height * ( renderIndex + 1 ) ) )
65+ : ( baseBounds [ 1 ] + ( height * renderIndex ) ) ;
66+ const bottomY = topY + height ;
67+ // Place display/value text within each vertical segment.
68+ const displayHeight = topY + height * ( 1 / 3 ) ;
69+ const valueHeight = topY + height * ( 2 / 3 ) ;
6470
6571 // [x1, y1, x2, y2] as (left, top), (bottom, right)
66- const newBounds : RectBounds = [ baseBounds [ 2 ] , baseBounds [ 1 ] + ( height * renderIndex ) , baseBounds [ 2 ] + width , baseBounds [ 1 ] + ( height * renderIndex ) + height ] ;
72+ const newBounds : RectBounds = leftAnchored
73+ ? [ baseBounds [ 0 ] - width , topY , baseBounds [ 0 ] , bottomY ]
74+ : [ baseBounds [ 2 ] , topY , baseBounds [ 2 ] + width , bottomY ] ;
6775 const textAlign = renderSettings . location === 'outside' ? 'center' : 'start' ;
6876 return {
6977 displayX, displayHeight, valueX, valueHeight, newBounds, offsetX : 0 , offsetY : 0 , textAlign,
@@ -166,6 +174,28 @@ function defaultFormatter(
166174 lineHeight = baseHeight * 1.30 ;
167175 }
168176
177+ // For vertical layouts, compute stacking independently for left and right sides.
178+ // This keeps %/auto sizing and indexing separate per side.
179+ const verticalLeft : number [ ] = [ ] ;
180+ const verticalRight : number [ ] = [ ] ;
181+ renderFiltered . forEach ( ( item , idx ) => {
182+ const render = item . render ;
183+ if ( render ?. layout === 'vertical' ) {
184+ if ( [ 'SW' , 'NW' ] . includes ( render . corner || '' ) ) {
185+ verticalLeft . push ( idx ) ;
186+ } else {
187+ verticalRight . push ( idx ) ;
188+ }
189+ }
190+ } ) ;
191+ const verticalLayoutMeta = new Map < number , { index : number ; length : number } > ( ) ;
192+ verticalLeft . forEach ( ( itemIdx , sideIndex ) => {
193+ verticalLayoutMeta . set ( itemIdx , { index : sideIndex , length : verticalLeft . length } ) ;
194+ } ) ;
195+ verticalRight . forEach ( ( itemIdx , sideIndex ) => {
196+ verticalLayoutMeta . set ( itemIdx , { index : sideIndex , length : verticalRight . length } ) ;
197+ } ) ;
198+
169199 for ( let i = 0 ; i < renderFiltered . length ; i += 1 ) {
170200 const currentRender = renderFiltered [ i ] . render ;
171201 const { name } = renderFiltered [ i ] ;
@@ -227,9 +257,16 @@ function defaultFormatter(
227257 value = newVal ;
228258 }
229259 }
260+ const sideMeta = verticalLayoutMeta . get ( i ) ;
230261 const {
231262 displayX, displayHeight, valueX, valueHeight, offsetY, offsetX, textAlign,
232- } = calculateAttributeArea ( bounds , currentRender , i , renderFiltered . length , lineHeight ) ;
263+ } = calculateAttributeArea (
264+ bounds ,
265+ currentRender ,
266+ currentRender . layout === 'vertical' && sideMeta ? sideMeta . index : i ,
267+ currentRender . layout === 'vertical' && sideMeta ? sideMeta . length : renderFiltered . length ,
268+ lineHeight ,
269+ ) ;
233270
234271 const displayColor = currentRender . displayColor === 'auto' ? renderAttr [ i ] . color : currentRender . displayColor ;
235272 const { displayTextSize } = currentRender ;
0 commit comments