@@ -39,6 +39,7 @@ import {
3939} from "powerbi-visuals-utils-svgutils" ;
4040
4141import { ILegend , LegendData , LegendDataPoint , LegendPosition } from "./legendInterfaces" ;
42+ import { isBottom , isRight , isTopOrBottom , isCentered , isRightAligned } from "./legend" ;
4243
4344import * as Markers from "./markers" ;
4445
@@ -168,14 +169,11 @@ export class SVGLegend implements ILegend {
168169 "width" , legendViewport . width || ( orientation === LegendPosition . None ? 0 : this . parentViewport . width )
169170 ) ;
170171
171- const isRight = orientation === LegendPosition . Right || orientation === LegendPosition . RightCenter ,
172- isBottom = orientation === LegendPosition . Bottom || orientation === LegendPosition . BottomCenter ;
173-
174172 this . svg . style (
175- "margin-left" , isRight ? ( this . parentViewport . width - legendViewport . width ) + "px" : null
173+ "margin-left" , isRight ( orientation ) ? ( this . parentViewport . width - legendViewport . width ) + "px" : null
176174 ) ;
177175 this . svg . style (
178- "margin-top" , isBottom ? ( this . parentViewport . height - legendViewport . height ) + "px" : null ,
176+ "margin-top" , isBottom ( orientation ) ? ( this . parentViewport . height - legendViewport . height ) + "px" : null ,
179177 ) ;
180178 }
181179
@@ -185,6 +183,8 @@ export class SVGLegend implements ILegend {
185183 case LegendPosition . Bottom :
186184 case LegendPosition . TopCenter :
187185 case LegendPosition . BottomCenter :
186+ case LegendPosition . TopRight :
187+ case LegendPosition . BottomRight :
188188 const pixelHeight = PixelConverter . fromPointToPixel ( this . data && this . data . fontSize
189189 ? this . data . fontSize
190190 : SVGLegend . DefaultFontSizeInPt ) ;
@@ -259,7 +259,7 @@ export class SVGLegend implements ILegend {
259259
260260 // Adding back the workaround for Legend Left/Right position for Map
261261 const mapControls = this . element . getElementsByClassName ( "mapControl" ) ;
262- if ( mapControls . length > 0 && ! this . isTopOrBottom ( this . orientation ) ) {
262+ if ( mapControls . length > 0 && ! isTopOrBottom ( this . orientation ) ) {
263263 for ( let i = 0 ; i < mapControls . length ; ++ i ) {
264264 const element = < HTMLElement > mapControls [ i ] ;
265265 element . style . display = "inline-block" ;
@@ -274,18 +274,22 @@ export class SVGLegend implements ILegend {
274274
275275 const group = this . group ;
276276
277- // transform the wrapping group if position is centered
278- if ( this . isCentered ( this . orientation ) ) {
277+ // transform the wrapping group if position is centered or right-aligned
278+ if ( isCentered ( this . orientation ) ) {
279279 let centerOffset = 0 ;
280- if ( this . isTopOrBottom ( this . orientation ) ) {
280+ if ( isTopOrBottom ( this . orientation ) ) {
281281 centerOffset = Math . max ( 0 , ( this . parentViewport . width - this . visibleLegendWidth ) / 2 ) ;
282282 group . attr ( "transform" , svgManipulation . translate ( centerOffset , 0 ) ) ;
283283 }
284284 else {
285- centerOffset = Math . max ( ( this . parentViewport . height - this . visibleLegendHeight ) / 2 ) ;
285+ centerOffset = Math . max ( 0 , ( this . parentViewport . height - this . visibleLegendHeight ) / 2 ) ;
286286 group . attr ( "transform" , svgManipulation . translate ( 0 , centerOffset ) ) ;
287287 }
288288 }
289+ else if ( isRightAligned ( this . orientation ) ) {
290+ const rightOffset = Math . max ( 0 , this . parentViewport . width - this . visibleLegendWidth ) ;
291+ group . attr ( "transform" , svgManipulation . translate ( rightOffset , 0 ) ) ;
292+ }
289293 else {
290294 group . attr ( "transform" , null ) ;
291295 }
@@ -444,7 +448,7 @@ export class SVGLegend implements ILegend {
444448 const hasTitle = ! ! title ;
445449
446450 if ( hasTitle ) {
447- const isHorizontal = this . isTopOrBottom ( this . orientation ) ;
451+ const isHorizontal = isTopOrBottom ( this . orientation ) ;
448452
449453 const textProperties = SVGLegend . getTextProperties ( title , this . data . fontSize , this . data . fontFamily ) ;
450454 let text = title ;
@@ -498,7 +502,7 @@ export class SVGLegend implements ILegend {
498502 let navArrows : NavigationArrow [ ] ;
499503 let numberOfItems : number ;
500504
501- if ( this . isTopOrBottom ( this . orientation ) ) {
505+ if ( isTopOrBottom ( this . orientation ) ) {
502506 navArrows = this . isScrollable ? this . calculateHorizontalNavigationArrowsLayout ( title ) : [ ] ;
503507 numberOfItems = this . calculateHorizontalLayout ( dataPoints , title , navArrows ) ;
504508 }
@@ -786,6 +790,20 @@ export class SVGLegend implements ILegend {
786790 }
787791
788792 this . visibleLegendWidth = occupiedWidth ;
793+
794+ // When the legend is right-aligned (TopRight/BottomRight):
795+ // - If everything fits, the group is translated to the right edge in
796+ // drawLegendInternal and items render right-aligned with no arrow.
797+ // - If items overflow, native visuals fall back to left-aligned rendering
798+ // with the "next" arrow at the right edge of the viewport — matching the
799+ // standard Top/Bottom overflow behavior. We achieve that here by setting
800+ // visibleLegendWidth to the full parent width so the translation in
801+ // drawLegendInternal becomes 0; the arrow keeps its default x set by
802+ // updateNavigationArrowLayout (parentViewport.width - LegendArrowWidth).
803+ if ( isRightAligned ( this . orientation ) && numberOfItems !== dataPointsLength ) {
804+ this . visibleLegendWidth = this . parentViewport . width ;
805+ }
806+
789807 this . updateNavigationArrowLayout ( navigationArrows , dataPointsLength , numberOfItems ) ;
790808
791809 return numberOfItems ;
@@ -955,30 +973,6 @@ export class SVGLegend implements ILegend {
955973 . attr ( "transform" , ( d : NavigationArrow ) => d . rotateTransform ) ;
956974 }
957975
958- private isTopOrBottom ( orientation : LegendPosition ) : boolean {
959- switch ( orientation ) {
960- case LegendPosition . Top :
961- case LegendPosition . Bottom :
962- case LegendPosition . BottomCenter :
963- case LegendPosition . TopCenter :
964- return true ;
965- default :
966- return false ;
967- }
968- }
969-
970- private isCentered ( orientation : LegendPosition ) : boolean {
971- switch ( orientation ) {
972- case LegendPosition . BottomCenter :
973- case LegendPosition . LeftCenter :
974- case LegendPosition . RightCenter :
975- case LegendPosition . TopCenter :
976- return true ;
977- default :
978- return false ;
979- }
980- }
981-
982976 public reset ( ) : void { }
983977
984978 private static getTextProperties (
0 commit comments