'use strict' ; import type BBoxObject from '../../Core/Renderer/BBoxObject' ; import type Chart from '../../Core/Chart/Chart' ; import type ColorAxisComposition from '../../Core/Axis/Color/ColorAxisComposition' ; import type ColorType from '../../Core/Color/ColorType' ; import type CSSObject from '../../Core/Renderer/CSSObject' ; import type DataExtremesObject from '../../Core/Series/DataExtremesObject' ; import type DataLabelOptions from '../../Core/Series/DataLabelOptions' ; import type { TreemapSeriesLayoutAlgorithmValue , TreemapSeriesOptions , TreemapSeriesUpButtonOptions } from './TreemapSeriesOptions' ; import type { SeriesOptions , SeriesStateHoverOptions } from '../../Core/Series/SeriesOptions' ; import type { StatesOptionsKey } from '../../Core/Series/StatesOptions' ; import type SVGAttributes from '../../Core/Renderer/SVG/SVGAttributes' ; import type SVGElement from '../../Core/Renderer/SVG/SVGElement' ; import type SVGLabel from '../../Core/Renderer/SVG/SVGLabel' ; import Color from '../../Core/Color/Color.js' ; const { parse : color } = Color ; import ColorMapMixin from '../ColorMapMixin.js' ; import H from '../../Core/Globals.js' ; const { noop } = H ; import LegendSymbol from '../../Core/Legend/LegendSymbol.js' ; import { Palette } from '../../Core/Color/Palettes.js' ; import SeriesRegistry from '../../Core/Series/SeriesRegistry.js' ; const { series : Series , seriesTypes : { column : ColumnSeries , heatmap : HeatmapSeries , scatter : ScatterSeries } } = SeriesRegistry ; import TreemapAlgorithmGroup from './TreemapAlgorithmGroup.js' ; import TreemapPoint from './TreemapPoint.js' ; import TreemapUtilities from './TreemapUtilities.js' ; import TU from '../TreeUtilities.js' ; import Breadcrumbs from '../../Extensions/Breadcrumbs.js' ; const { getColor , getLevelOptions , updateRootId } = TU ; import U from '../../Core/Utilities.js' ; const { addEvent , correctFloat , defined , error , extend , fireEvent , isArray , isNumber , isObject , isString , merge , pick , stableSort } = U ; import './TreemapComposition.js' ; private class name augments Highcharts . Series class TreemapSeries extends ScatterSeries { sample extends plotOptions . scatter excluding product requires optionparent static defaultOptions : TreemapSeriesOptions = merge ( ScatterSeries . defaultOptions , { sample deprecated type { boolean } default since product apioption sample since product allowTraversingTree : false , animationLimit : 250 , /**
         * The border radius for each treemap item.
         */ borderRadius : 0 , since product extends breadcrumbs optionparent type { number } default since product apioption sample type { Function } default since product apioption sample sample type { boolean } since product apioption sample type { number } since product apioption type { Array < Highcharts . ColorString | Highcharts . GradientColorObject | Highcharts . PatternObject > } since product apioption /**
         * Whether to display this series type or specific series item in the
         * legend.
         */ showInLegend : false , ignore-option marker : void 0 , see since product apioption colorByPoint : false , since dataLabels : { defer : false , enabled : true , formatter : function ( ) : string { const point = this && this . point ? this . point : ( { } as any ) , name = isString ( point . name ) ? point . name : '' ; return name ; } , inside : true , verticalAlign : 'middle' } , tooltip : { headerFormat : '' , pointFormat : '<b>{point.name}</b>: {point.value}<br/>' } , since ignoreHiddenPoint : true , see sample sample sample sample since validvalue layoutAlgorithm : 'sliceAndDice' , since validvalue layoutStartingDirection : 'vertical' , sample since alternateStartingDirection : false , since levelIsConstant : true , deprecated traverseUpButton : { /**
             * The position of the button.
             */ position : { type { Highcharts . VerticalAlignValue } default product apioption type { Highcharts . AlignValue } align : 'right' , /**
                 * Horizontal offset of the button.
                 */ x : - 10 , /**
                 * Vertical offset of the button.
                 */ y : 10 } } , sample sample type { Array < * > } since product apioption type { Highcharts . ColorString } since product apioption type { Highcharts . DashStyleValue } since product apioption type { number } since product apioption type { Highcharts . ColorString | Highcharts . GradientColorObject | Highcharts . PatternObject } since product apioption sample since product apioption type { string } since product validvalue apioption type { number } since product apioption extends plotOptions . treemap . dataLabels since product apioption type { string } since product validvalue apioption type { string } since product validvalue apioption sample type { number } since product apioption type { Highcharts . ColorString } borderColor : Palette . neutralColor10 , /**
         * The width of the border surrounding each tree map item.
         */ borderWidth : 1 , colorKey : 'colorValue' , since opacity : 0.15 , extends plotOptions . heatmap . states states : { extends plotOptions . heatmap . states . hover excluding hover : { /**
                 * The border color for the hovered state.
                 */ borderColor : Palette . neutralColor40 , type { number } default brightness : HeatmapSeries ? 0 : 0.1 , extends plotOptions . heatmap . states . hover . halo halo : false , since opacity : 0.75 , /**
                 * The shadow option for hovered state.
                 */ shadow : false } } } as TreemapSeriesOptions ) ; public axisRatio : number = void 0 as any ; public colorValueData ? : Array < number > ; public colorAxis ? : ColorAxisComposition . SeriesComposition [ 'colorAxis' ] ; public data : Array < TreemapPoint > = void 0 as any ; public drillUpButton ? : SVGElement ; public idPreviousRoot ? : string ; public mapOptionsToLevel : Record < string , TreemapSeriesOptions > = void 0 as any ; public nodeMap : Record < string , TreemapSeries . NodeObject > = void 0 as any ; public options : TreemapSeriesOptions = void 0 as any ; public points : Array < TreemapPoint > = void 0 as any ; public rootNode : string = void 0 as any ; public tree : TreemapSeries . NodeObject = void 0 as any ; public level ? : number = void 0 as any ; public algorithmCalcPoints ( directionChange , last , group , childrenArea ) { let pX , pY , pW , pH , gW = group . lW , gH = group . lH , plot = group . plot , keep , i = 0 , end = group . elArr . length - 1 ; if ( last ) { gW = group . nW ; gH = group . nH ; } else { keep = group . elArr [ group . elArr . length - 1 ] ; } group . elArr . forEach ( function ( p ) : void { if ( last || ( i < end ) ) { if ( group . direction === 0 ) { pX = plot . x ; pY = plot . y ; pW = gW ; pH = p / pW ; } else { pX = plot . x ; pY = plot . y ; pH = gH ; pW = p / pH ; } childrenArea . push ( { x : pX , y : pY , width : pW , height : correctFloat ( pH ) } ) ; if ( group . direction === 0 ) { plot . y = plot . y + pH ; } else { plot . x = plot . x + pW ; } } i = i + 1 ; } ) ; group . reset ( ) ; if ( group . direction === 0 ) { group . width = group . width - gW ; } else { group . height = group . height - gH ; } plot . y = plot . parent . y + ( plot . parent . height - group . height ) ; plot . x = plot . parent . x + ( plot . parent . width - group . width ) ; if ( directionChange ) { group . direction = 1 - group . direction ; } if ( ! last ) { group . addElement ( keep as any ) ; } } public algorithmFill ( directionChange , parent , children ) { let childrenArea = [ ] , pTot , direction = parent . direction , x = parent . x , y = parent . y , width = parent . width , height = parent . height , pX , pY , pW , pH ; children . forEach ( function ( child ) : void { pTot = ( parent . width * parent . height ) * ( child . val / parent . val ) ; pX = x ; pY = y ; if ( direction === 0 ) { pH = height ; pW = pTot / pH ; width = width - pW ; x = x + pW ; } else { pW = width ; pH = pTot / pW ; height = height - pH ; y = y + pH ; } childrenArea . push ( { x : pX , y : pY , width : pW , height : pH } ) ; if ( directionChange ) { direction = 1 - direction ; } } ) ; return childrenArea ; } public algorithmLowAspectRatio ( directionChange , parent , children ) { let childrenArea = [ ] , series = this , pTot , plot = { x : parent . x , y : parent . y , parent : parent } , direction = parent . direction , i = 0 , end = children . length - 1 , group = new TreemapAlgorithmGroup ( parent . height , parent . width , direction , plot ) ; children . forEach ( function ( child ) : void { pTot = ( parent . width * parent . height ) * ( child . val / parent . val ) ; group . addElement ( pTot ) ; if ( group . lP . nR > group . lP . lR ) { ( series . algorithmCalcPoints as any ) ( directionChange , false , group , childrenArea , plot ) ; } if ( i === end ) { ( series . algorithmCalcPoints as any ) ( directionChange , true , group , childrenArea , plot ) ; } i = i + 1 ; } ) ; return childrenArea ; } private public alignDataLabel ( point , dataLabel , labelOptions ) { const style = labelOptions . style ; if ( style && ! defined ( style . textOverflow ) && dataLabel . text && dataLabel . getBBox ( ) . width > dataLabel . text . textWidth ) { dataLabel . css ( { textOverflow : 'ellipsis' , width : style . width += 'px' } ) ; } ColumnSeries . prototype . alignDataLabel . apply ( this , arguments ) ; if ( point . dataLabel ) { point . dataLabel . attr ( { zIndex : ( point . node . zIndex || 0 ) + 1 } ) ; } } public buildNode ( id , i , level , list , parent ? ) { let series = this , children = [ ] , point = series . points [ i ] , height = 0 , node , child ; ( ( list [ id ] || [ ] ) ) . forEach ( function ( i ) : void { child = series . buildNode ( series . points [ i ] . id , i , ( level + 1 ) , list , id ) ; height = Math . max ( child . height + 1 , height ) ; children . push ( child ) ; } ) ; node = { id , i , children , height , level , parent , visible : false } as any ; series . nodeMap [ node . id ] = node ; if ( point ) { point . node = node ; } return node ; } private function param { Object } node param { Object } area public calculateChildrenAreas ( parent , area ) { let series = this , options = series . options , mapOptionsToLevel = series . mapOptionsToLevel , level = mapOptionsToLevel [ parent . level + 1 ] , algorithm = pick < TreemapSeriesLayoutAlgorithmValue | undefined , TreemapSeriesLayoutAlgorithmValue > ( ( ( series as any ) [ ( level && level . layoutAlgorithm ) as any ] && level . layoutAlgorithm ) , options . layoutAlgorithm as any ) , alternate = options . alternateStartingDirection , childrenValues = [ ] , children ; children = parent . children . filter ( function ( n ) : boolean { return ! n . ignore ; } ) ; if ( level && level . layoutStartingDirection ) { area . direction = level . layoutStartingDirection === 'vertical' ? 0 : 1 ; } childrenValues = series [ algorithm ] ( area as any , children ) as any ; children . forEach ( function ( child , index ) : void { const values = childrenValues [ index ] ; child . values = merge ( values , { val : child . childrenTotal , direction : ( alternate ? 1 - area . direction : area . direction ) } ) ; child . pointValues = merge ( values , { x : ( values . x / series . axisRatio ) , y : TreemapUtilities . AXIS_MAX - values . y - values . height , width : ( values . width / series . axisRatio ) } as TreemapSeries . NodeValuesObject ) ; if ( child . children . length ) { series . calculateChildrenAreas ( child , child . values ) ; } } ) ; } requires function param { TreemapSeries } this public createList ( e ) { const chart = this . chart , breadcrumbs = chart . breadcrumbs , list = [ ] ; if ( breadcrumbs ) { let currentLevelNumber = 0 ; list . push ( { level : currentLevelNumber , levelOptions : chart . series [ 0 ] } ) ; let node = e . target . nodeMap [ e . newRootId ] ; const extraNodes = [ ] ; while ( node . parent || node . parent === '' ) { extraNodes . push ( node ) ; node = e . target . nodeMap [ node . parent ] ; } extraNodes . reverse ( ) . forEach ( function ( node ) : void { list . push ( { level : ++ currentLevelNumber , levelOptions : node } ) ; } ) ; if ( list . length <= 1 ) { list . length = 0 ; } } return list ; } private public drawDataLabels ( ) { let series = this , mapOptionsToLevel = series . mapOptionsToLevel , points = series . points . filter ( function ( n ) : boolean { return n . node . visible ; } ) , options , level ; points . forEach ( function ( point ) : void { level = mapOptionsToLevel [ point . node . level ] ; options = { style : { } } ; if ( ! point . node . isLeaf ) { options . enabled = false ; } if ( level && level . dataLabels ) { options = merge ( options , level . dataLabels ) ; series . _hasPointLabels = true ; } if ( point . shapeArgs ) { ( options . style as any ) . width = point . shapeArgs . width ; if ( point . dataLabel ) { point . dataLabel . css ( { width : point . shapeArgs . width + 'px' } ) ; } } point . dlOptions = merge ( options , point . options . dataLabels ) ; } ) ; Series . prototype . drawDataLabels . call ( this ) ; } private public drawPoints ( ) { const series = this , chart = series . chart , renderer = chart . renderer , points = series . points , styledMode = chart . styledMode , options = series . options , shadow = styledMode ? { } : options . shadow , borderRadius = options . borderRadius , withinAnimationLimit = chart . pointCount < ( options . animationLimit as any ) , allowTraversingTree = options . allowTraversingTree ; points . forEach ( function ( point ) : void { const levelDynamic = point . node . levelDynamic , animatableAttribs = { } , attribs = { } , css = { } , groupKey = 'level-group-' + point . node . level , hasGraphic = ! ! point . graphic , shouldAnimate = withinAnimationLimit && hasGraphic , shapeArgs = point . shapeArgs ; if ( point . shouldDraw ( ) ) { point . isInside = true ; if ( borderRadius ) { attribs . r = borderRadius ; } merge ( true , shouldAnimate ? animatableAttribs : attribs , hasGraphic ? shapeArgs : { } , styledMode ? { } : series . pointAttribs ( point , point . selected ? 'select' : void 0 ) ) ; if ( series . colorAttribs && styledMode ) { extend < CSSObject | SVGAttributes > ( css , series . colorAttribs ( point as any ) ) ; } if ( ! ( series as any ) [ groupKey ] ) { ( series as any ) [ groupKey ] = renderer . g ( groupKey ) . attr ( { zIndex : 1000 - ( levelDynamic || 0 ) } ) . add ( series . group ) ; ( series as any ) [ groupKey ] . survive = true ; } } point . draw ( { animatableAttribs , attribs , css , group : ( series as any ) [ groupKey ] , renderer , shadow , shapeArgs , shapeType : 'rect' } ) ; if ( allowTraversingTree && point . graphic ) { point . drillId = options . interactByLeaf ? series . drillToByLeaf ( point ) : series . drillToByGroup ( point ) ; } } ) ; } private public drillToByGroup ( point ) { let series = this , drillId = false ; if ( ( point . node . level - series . nodeMap [ series . rootNode ] . level ) === 1 && ! point . node . isLeaf ) { drillId = point . id ; } return drillId ; } private public drillToByLeaf ( point ) { let series = this , drillId = false , nodeParent ; if ( ( point . node . parent !== series . rootNode ) && point . node . isLeaf ) { nodeParent = point . node ; while ( ! drillId ) { nodeParent = series . nodeMap [ nodeParent . parent as any ] ; if ( nodeParent . parent === series . rootNode ) { drillId = nodeParent . id ; } } } return drillId ; } todo private public drillToNode ( id , redraw ? ) { error ( 32 , false , void 0 , { 'treemap.drillToNode' : 'use treemap.setRootNode' } ) ; this . setRootNode ( id , redraw ) ; } public drillUp ( ) { const series = this , node = series . nodeMap [ series . rootNode ] ; if ( node && isString ( node . parent ) ) { series . setRootNode ( node . parent , true , { trigger : 'traverseUpButton' } ) ; } } public getExtremes ( ) { const { dataMin , dataMax } = Series . prototype . getExtremes . call ( this , this . colorValueData ) ; this . valueMin = dataMin ; this . valueMax = dataMax ; return Series . prototype . getExtremes . call ( this ) ; } private function param { Highcharts . SeriesTreemapDataOptions } data param { Array < string > } existingIds return { Object } public getListOfParents ( data , existingIds ) { const arr = isArray ( data ) ? data : [ ] , ids = isArray ( existingIds ) ? existingIds : [ ] , listOfParents = arr . reduce ( function ( prev , curr , i ) : TreemapSeries . ListOfParentsObject { const parent = pick ( curr . parent , '' ) ; if ( typeof prev [ parent ] === 'undefined' ) { prev [ parent ] = [ ] ; } prev [ parent ] . push ( i ) ; return prev ; } , { '' : [ ] } ) ; TreemapUtilities . eachObject ( listOfParents , function ( children , parent , list ) : void { if ( ( parent !== '' ) && ( ids . indexOf ( parent ) === - 1 ) ) { children . forEach ( function ( child ) : void { list [ '' ] . push ( child ) ; } ) ; delete list [ parent ] ; } } ) ; return listOfParents ; } private public getTree ( ) { const series = this , allIds = this . data . map ( function ( d ) : string { return d . id ; } ) , parentList = series . getListOfParents ( this . data , allIds ) ; series . nodeMap = { } ; return series . buildNode ( '' , - 1 , 0 , parentList ) ; } private public hasData ( ) { return ! ! this . processedXData . length ; } public init ( chart , options ) { const series = this , breadcrumbsOptions = merge ( options . drillUpButton , options . breadcrumbs ) ; let setOptionsEvent ; this . colorAttribs = ColorMapMixin . SeriesMixin . colorAttribs ; setOptionsEvent = addEvent ( series , 'setOptions' , function ( event ) : void { const options = event . userOptions ; if ( defined ( options . allowDrillToNode ) && ! defined ( options . allowTraversingTree ) ) { options . allowTraversingTree = options . allowDrillToNode ; delete options . allowDrillToNode ; } if ( defined ( options . drillUpButton ) && ! defined ( options . traverseUpButton ) ) { options . traverseUpButton = options . drillUpButton ; delete options . drillUpButton ; } } ) ; Series . prototype . init . call ( series , chart , options ) ; delete series . opacity ; series . eventsToUnbind . push ( setOptionsEvent ) ; if ( series . options . allowTraversingTree ) { series . eventsToUnbind . push ( addEvent ( series , 'click' , series . onClickDrillToNode as any ) ) ; series . eventsToUnbind . push ( addEvent ( series , 'setRootNode' , function ( e ) : void { const chart = series . chart ; if ( chart . breadcrumbs ) { chart . breadcrumbs . updateProperties ( series . createList ( e ) ) ; } } ) ) ; series . eventsToUnbind . push ( addEvent ( series , 'update' , function ( e , redraw ? ) : void { const breadcrumbs = this . chart . breadcrumbs ; if ( breadcrumbs && e . options . breadcrumbs ) { breadcrumbs . update ( e . options . breadcrumbs ) ; } } ) ) ; series . eventsToUnbind . push ( addEvent ( series , 'destroy' , function destroyEvents ( e ) : void { const chart = this . chart ; if ( chart . breadcrumbs ) { chart . breadcrumbs . destroy ( ) ; if ( ! e . keepEventsForUpdate ) { chart . breadcrumbs = void 0 ; } } } ) ) ; } if ( ! chart . breadcrumbs ) { chart . breadcrumbs = new Breadcrumbs ( chart as Chart , breadcrumbsOptions as any ) ; } series . eventsToUnbind . push ( addEvent ( chart . breadcrumbs , 'up' , function ( e ) : void { const drillUpsNumber = this . level - e . newLevel ; for ( let i = 0 ; i < drillUpsNumber ; i ++ ) { series . drillUp ( ) ; } } ) ) ; } private public onClickDrillToNode ( event ) { const series = this , point = event . point , drillId = point && point . drillId ; if ( isString ( drillId ) ) { point . setState ( '' ) ; series . setRootNode ( drillId , true , { trigger : 'click' } ) ; } } private public pointAttribs ( point , state ? ) { let series = this , mapOptionsToLevel = ( isObject ( series . mapOptionsToLevel ) ? series . mapOptionsToLevel : { } ) , level = point && mapOptionsToLevel [ point . node . level ] || { } , options = this . options , attr , stateOptions = ( state && ( options . states as any ) [ state ] ) || { } , className = ( point && point . getClassName ( ) ) || '' , opacity ; attr = { 'stroke' : ( point && ( point as any ) . borderColor ) || level . borderColor || stateOptions . borderColor || options . borderColor , 'stroke-width' : pick ( point && ( point as any ) . borderWidth , level . borderWidth , stateOptions . borderWidth , options . borderWidth ) , 'dashstyle' : ( point && ( point as any ) . borderDashStyle ) || level . borderDashStyle || stateOptions . borderDashStyle || options . borderDashStyle , 'fill' : ( point && point . color ) || this . color } ; if ( className . indexOf ( 'highcharts-above-level' ) !== - 1 ) { attr . fill = 'none' ; attr [ 'stroke-width' ] = 0 ; } else if ( className . indexOf ( 'highcharts-internal-node-interactive' ) !== - 1 ) { opacity = pick ( stateOptions . opacity , options . opacity as any ) ; attr . fill = color ( attr . fill ) . setOpacity ( opacity ) . get ( ) ; attr . cursor = 'pointer' ; } else if ( className . indexOf ( 'highcharts-internal-node' ) !== - 1 ) { attr . fill = 'none' ; } else if ( state ) { attr . fill = color ( attr . fill ) . brighten ( stateOptions . brightness as any ) . get ( ) ; } return attr ; } private public setColorRecursive ( node , parentColor ? , colorIndex ? , index ? , siblings ? ) { let series = this , chart = series && series . chart , colors = chart && chart . options && chart . options . colors , colorInfo , point ; if ( node ) { colorInfo = getColor ( node , { colors : colors , index : index , mapOptionsToLevel : series . mapOptionsToLevel , parentColor : parentColor , parentColorIndex : colorIndex , series : series , siblings : siblings } ) ; point = series . points [ node . i ] ; if ( point ) { point . color = colorInfo . color ; point . colorIndex = colorInfo . colorIndex ; } ( node . children || [ ] ) . forEach ( function ( child , i ) : void { series . setColorRecursive ( child , colorInfo . color , colorInfo . colorIndex , i , node . children . length ) ; } ) ; } } public setPointValues ( ) { const series = this ; const { points , xAxis , yAxis } = series ; const styledMode = series . chart . styledMode ; const getCrispCorrection = ( point ) : number => ( styledMode ? 0 : ( ( series . pointAttribs ( point ) [ 'stroke-width' ] || 0 ) % 2 ) / 2 ) ; points . forEach ( function ( point ) : void { const { pointValues : values , visible } = point . node ; if ( values && visible ) { const { height , width , x , y } = values ; const crispCorr = getCrispCorrection ( point ) ; const x1 = Math . round ( xAxis . toPixels ( x , true ) ) - crispCorr ; const x2 = Math . round ( xAxis . toPixels ( x + width , true ) ) - crispCorr ; const y1 = Math . round ( yAxis . toPixels ( y , true ) ) - crispCorr ; const y2 = Math . round ( yAxis . toPixels ( y + height , true ) ) - crispCorr ; const shapeArgs = { x : Math . min ( x1 , x2 ) , y : Math . min ( y1 , y2 ) , width : Math . abs ( x2 - x1 ) , height : Math . abs ( y2 - y1 ) } ; point . plotX = shapeArgs . x + ( shapeArgs . width / 2 ) ; point . plotY = shapeArgs . y + ( shapeArgs . height / 2 ) ; point . shapeArgs = shapeArgs ; } else { delete point . plotX ; delete point . plotY ; } } ) ; } private function param { string } id param { boolean } redraw param eventArguments param { string } eventArguments . newRootId param { string } eventArguments . previousRootId param { boolean } eventArguments . redraw param { Object } eventArguments . series param { string } eventArguments . trigger emits public setRootNode ( id , redraw ? , eventArguments ? ) { const series = this , eventArgs = extend < TreemapSeries . SetRootNodeObject > ( { newRootId : id , previousRootId : series . rootNode , redraw : pick ( redraw , true ) , series : series } , eventArguments as any ) ; private param args param { string } args . newRootId param { string } args . previousRootId param { boolean } args . redraw param { Object } args . series param { string } args . trigger const defaultFn = function ( args ) : void { const series = args . series ; series . idPreviousRoot = args . previousRootId ; series . rootNode = args . newRootId ; series . isDirty = true ; if ( args . redraw ) { series . chart . redraw ( ) ; } } ; fireEvent ( series , 'setRootNode' , eventArgs , defaultFn ) ; } private public setState ( state ) { this . options . inactiveOtherPoints = true ; Series . prototype . setState . call ( this , state , false ) ; this . options . inactiveOtherPoints = false ; } public setTreeValues ( tree ) { let series = this , options = series . options , idRoot = series . rootNode , mapIdToNode = series . nodeMap , nodeRoot = mapIdToNode [ idRoot ] , levelIsConstant = ( TreemapUtilities . isBoolean ( options . levelIsConstant ) ? options . levelIsConstant : true ) , childrenTotal = 0 , children = [ ] , val , point = series . points [ tree . i ] ; tree . children . forEach ( function ( child ) : void { child = series . setTreeValues ( child ) ; children . push ( child ) ; if ( ! child . ignore ) { childrenTotal += child . val as any ; } } ) ; stableSort ( children , function ( a , b ) : number { return ( a . sortIndex || 0 ) - ( b . sortIndex || 0 ) ; } ) ; val = pick ( point && point . options . value , childrenTotal ) ; if ( point ) { point . value = val ; } extend ( tree , { children : children , childrenTotal : childrenTotal , ignore : ! ( pick ( point && point . visible , true ) && ( val > 0 ) ) , isLeaf : tree . visible && ! childrenTotal , levelDynamic : ( tree . level - ( levelIsConstant ? 0 : nodeRoot . level ) ) , name : pick ( point && point . name , '' ) , sortIndex : pick ( point && point . sortIndex , - val ) , val : val } ) ; return tree ; } public sliceAndDice ( parent , children ) { return this . algorithmFill ( true , parent , children ) ; } public squarified ( parent , children ) { return this . algorithmLowAspectRatio ( true , parent , children ) ; } public strip ( parent , children ) { return this . algorithmLowAspectRatio ( false , parent , children ) ; } public stripes ( parent , children ) { return this . algorithmFill ( false , parent , children ) ; } public translate ( ) { let series = this , options = series . options , rootId = updateRootId ( series ) , rootNode , pointValues , seriesArea , tree , val ; Series . prototype . translate . call ( series ) ; tree = series . tree = series . getTree ( ) ; rootNode = series . nodeMap [ rootId ] ; if ( rootId !== '' && ( ! rootNode || ! rootNode . children . length ) ) { series . setRootNode ( '' , false ) ; rootId = series . rootNode ; rootNode = series . nodeMap [ rootId ] ; } series . mapOptionsToLevel = getLevelOptions < this > ( { from : rootNode . level + 1 , levels : options . levels , to : tree . height , defaults : { levelIsConstant : series . options . levelIsConstant , colorByPoint : options . colorByPoint } } ) as any ; TreemapUtilities . recursive ( series . nodeMap [ series . rootNode ] , function ( node ) : ( boolean | TreemapSeries . NodeObject ) { let next = false , p = node . parent ; node . visible = true ; if ( p || p === '' ) { next = series . nodeMap [ p ] ; } return next ; } ) ; TreemapUtilities . recursive ( series . nodeMap [ series . rootNode ] . children , function ( children ) : ( boolean | Array < TreemapSeries . NodeObject > ) { let next = false ; children . forEach ( function ( child ) : void { child . visible = true ; if ( child . children . length ) { next = ( ( next as any ) || [ ] ) . concat ( child . children ) ; } } ) ; return next ; } ) ; series . setTreeValues ( tree ) ; series . axisRatio = ( series . xAxis . len / series . yAxis . len ) ; series . nodeMap [ '' ] . pointValues = pointValues = { x : 0 , y : 0 , width : TreemapUtilities . AXIS_MAX , height : TreemapUtilities . AXIS_MAX } as any ; series . nodeMap [ '' ] . values = seriesArea = merge ( pointValues , { width : ( pointValues . width * series . axisRatio ) , direction : ( options . layoutStartingDirection === 'vertical' ? 0 : 1 ) , val : tree . val } ) ; series . calculateChildrenAreas ( tree , seriesArea ) ; if ( ! series . colorAxis && ! options . colorByPoint ) { series . setColorRecursive ( series . tree ) ; } if ( options . allowTraversingTree ) { val = rootNode . pointValues as any ; series . xAxis . setExtremes ( val . x , val . x + val . width , false ) ; series . yAxis . setExtremes ( val . y , val . y + val . height , false ) ; series . xAxis . setScale ( ) ; series . yAxis . setScale ( ) ; } series . setPointValues ( ) ; } } interface TreemapSeries extends TU . Series { colorAttribs ? : ColorMapMixin . ColorMapSeries [ 'colorAttribs' ] ; colorKey : string ; directTouch : boolean ; drawLegendSymbol : typeof LegendSymbol . drawRectangle ; getExtremesFromAll : boolean ; optionalAxis : string ; parallelArrays : Array < string > ; pointArrayMap : Array < string > ; pointClass : typeof TreemapPoint ; trackerGroups : Array < string > ; utils : { recursive : typeof TreemapUtilities . recursive ; } ; } extend ( TreemapSeries . prototype , { buildKDTree : noop , colorKey : 'colorValue' , directTouch : true , drawLegendSymbol : LegendSymbol . drawRectangle , getExtremesFromAll : true , getSymbol : noop , optionalAxis : 'colorAxis' , parallelArrays : [ 'x' , 'y' , 'value' , 'colorValue' ] , pointArrayMap : [ 'value' ] , pointClass : TreemapPoint , trackerGroups : [ 'group' , 'dataLabelsGroup' ] , utils : { recursive : TreemapUtilities . recursive } } ) ; namespace TreemapSeries { export interface AreaObject { direction : number ; } export type ListOfParentsObject = Record < string , Array < number > > ; export interface NodeObject extends TU . NodeObject { children : Array < NodeObject > ; childrenTotal ? : number ; height : number ; ignore ? : boolean ; isLeaf ? : boolean ; levelDynamic ? : number ; name ? : string ; parent ? : string ; pointValues ? : NodeValuesObject ; sortIndex ? : number ; val : number ; values ? : NodeValuesObject ; zIndex ? : number ; } export interface NodeValuesObject extends BBoxObject { direction : number ; val : number ; } export interface SetRootNodeObject { newRootId ? : string ; previousRootId ? : string ; redraw ? : boolean ; series ? : object ; trigger ? : string ; } } declare module '../../Core/Series/SeriesType' { interface SeriesTypeRegistry { treemap : typeof TreemapSeries ; } } SeriesRegistry . registerSeriesType ( 'treemap' , TreemapSeries ) ; export default TreemapSeries ; extends series excluding product requires apioption sample sample type { Array < number | null | * > } extends series . heatmap . data excluding product apioption type { number | null } product apioption type { number } since product apioption sample sample type { string } since product apioption '' ;