This demo uses imperative chart updates. The generated code is a faithful Angular translation: open it in CodeSandbox to run and tweak.

import { Component, AfterViewInit, OnDestroy, ViewChild } from '@angular/core';
import {
  ChartComponent,
  ApexAxisChartSeries,
  ApexNonAxisChartSeries,
  ApexChart,
  ApexXAxis,
  ApexYAxis,
  ApexTitleSubtitle,
  ApexDataLabels,
  ApexStroke,
  ApexFill,
  ApexLegend,
  ApexTooltip,
  ApexMarkers,
  ApexPlotOptions,
  ApexResponsive,
  ApexGrid,
  ApexAnnotations,
  ApexStates,
  ApexTheme,
  NgApexchartsModule,
} from 'ng-apexcharts';

export type ChartOptions = {
  series?: ApexAxisChartSeries | ApexNonAxisChartSeries;
  chart?: ApexChart;
  xaxis?: ApexXAxis;
  yaxis?: ApexYAxis | ApexYAxis[];
  title?: ApexTitleSubtitle;
  subtitle?: ApexTitleSubtitle;
  dataLabels?: ApexDataLabels;
  stroke?: ApexStroke;
  fill?: ApexFill;
  legend?: ApexLegend;
  tooltip?: ApexTooltip;
  markers?: ApexMarkers;
  plotOptions?: ApexPlotOptions;
  responsive?: ApexResponsive[];
  grid?: ApexGrid;
  annotations?: ApexAnnotations;
  states?: ApexStates;
  theme?: ApexTheme;
  colors?: string[];
  labels?: any;
};

@Component({
  selector: 'app-chart',
  standalone: true,
  imports: [NgApexchartsModule],
  templateUrl: './chart.component.html',
})
export class AppChart implements AfterViewInit, OnDestroy {
  @ViewChild('chart') chart!: ChartComponent;
  private TAXONOMY: any = [
          {
            sector: 'Information Technology',
            weight: 30,
            drift: 0.9,
            industries: [
              { name: 'Semiconductors', n: 14, weight: 12 },
              { name: 'Software', n: 16, weight: 11 },
              { name: 'Hardware & Devices', n: 9, weight: 7 },
            ],
          },
          {
            sector: 'Financials',
            weight: 15,
            drift: -0.3,
            industries: [
              { name: 'Banks', n: 15, weight: 6 },
              { name: 'Insurance', n: 11, weight: 4 },
              { name: 'Capital Markets', n: 10, weight: 5 },
            ],
          },
          {
            sector: 'Health Care',
            weight: 14,
            drift: 0.2,
            industries: [
              { name: 'Pharmaceuticals', n: 12, weight: 6 },
              { name: 'Biotechnology', n: 14, weight: 4 },
              { name: 'Medical Devices', n: 10, weight: 4 },
            ],
          },
          {
            sector: 'Consumer Discretionary',
            weight: 11,
            drift: -0.6,
            industries: [
              { name: 'Retail', n: 13, weight: 5 },
              { name: 'Automobiles', n: 8, weight: 4 },
              { name: 'Hotels & Leisure', n: 9, weight: 2 },
            ],
          },
          {
            sector: 'Communication Services',
            weight: 9,
            drift: 1.4,
            industries: [
              { name: 'Interactive Media', n: 9, weight: 5 },
              { name: 'Telecom', n: 8, weight: 2 },
              { name: 'Entertainment', n: 9, weight: 2 },
            ],
          },
          {
            sector: 'Industrials',
            weight: 8,
            drift: 0.1,
            industries: [
              { name: 'Aerospace & Defence', n: 8, weight: 3 },
              { name: 'Machinery', n: 10, weight: 3 },
              { name: 'Transport', n: 9, weight: 2 },
            ],
          },
          {
            sector: 'Consumer Staples',
            weight: 6,
            drift: 0.4,
            industries: [
              { name: 'Food & Beverage', n: 11, weight: 3 },
              { name: 'Household Products', n: 8, weight: 3 },
            ],
          },
          {
            sector: 'Energy',
            weight: 5,
            drift: -1.7,
            industries: [
              { name: 'Oil & Gas', n: 12, weight: 4 },
              { name: 'Renewables', n: 8, weight: 1 },
            ],
          },
          {
            sector: 'Utilities',
            weight: 4,
            drift: -0.2,
            industries: [
              { name: 'Electric Utilities', n: 9, weight: 3 },
              { name: 'Water & Gas', n: 6, weight: 1 },
            ],
          },
          {
            sector: 'Real Estate',
            weight: 4,
            drift: -0.9,
            industries: [
              { name: 'REITs', n: 11, weight: 3 },
              { name: 'Property Services', n: 6, weight: 1 },
            ],
          },
          {
            sector: 'Materials',
            weight: 4,
            drift: 0.6,
            industries: [
              { name: 'Chemicals', n: 9, weight: 2 },
              { name: 'Metals & Mining', n: 9, weight: 2 },
            ],
          },
        ];

  private rng = (seed: any): any => {
          var s = seed >>> 0
          return function () {
            s = (s * 1664525 + 1013904223) >>> 0
            return s / 4294967296
          }
        };

  private gauss = (u: any): any => {
          var g = 0
          for (var k = 0; k < 6; k++) g += u()
          return (g - 3) / Math.sqrt(0.5)
        };

  private LETTERS: any = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';

  private ticker = (u: any): any => {
          var out = ''
          var len = 3 + (u() > 0.65 ? 1 : 0)
          for (var i = 0; i < len; i++) {
            out += this.LETTERS.charAt(Math.floor(u() * 26))
          }
          return out
        };

  private seen: any = {};

  private u: any = this.rng(20260812);

  private marketSeries: any = [
          {
            name: 'Market',
            data: this.TAXONOMY.map(function (sec) {
              return {
                x: sec.sector,
                children: sec.industries.map(function (ind) {
                  var companies = []
                  for (var i = 0; i < ind.n; i++) {
                    // Heavy tail: a few names carry most of the industry's value.
                    var scale = Math.exp(this.gauss(this.u) * 0.85)
                    var cap = Math.max(4, Math.round((ind.weight * 90 * scale) / ind.n))
                    // The day's move: the sector drifts, the name adds its own noise.
                    var change = Math.round((sec.drift + this.gauss(this.u) * 1.6) * 100) / 100
                    var t = this.ticker(this.u)
                    while (this.seen[t]) t = this.ticker(this.u)
                    this.seen[t] = true
                    companies.push({ x: t, y: cap, colorValue: change })
                  }
                  return { x: ind.name, children: companies }
                }),
              }
            }),
          },
        ];

  private fmtCap = (v: any): any => {
          return v >= 1000 ? '$' + (v / 1000).toFixed(2) + 'T' : '$' + v + 'B'
        };

  private fmtPct = (v: any): any => {
          return (v > 0 ? '+' : '') + v.toFixed(2) + '%'
        };

  public chartOptions: Partial<ChartOptions> = {
          series: this.marketSeries,
          chart: {
            id: 'marketMap',
            type: 'treemap',
            height: 620,
            fontFamily: 'inherit',
            background: 'transparent',
            animations: {
              enabled: true,
              speed: 500,
            },
            toolbar: {
              show: false,
            },
          },
          theme: {
            mode: 'dark',
          },
          title: {
            // Kept to one line: the breadcrumb that appears once you zoom in sits in the
            // band between the title and the plot, and a subtitle would squeeze it out.
            text: "Market map by sector - area is market value, colour is the day's move",
            align: 'left',
            style: {
              fontSize: '14px',
              fontWeight: 600,
            },
          },
          legend: {
            show: true,
            position: 'bottom',
          },
          stroke: {
            width: 1,
            colors: ['#0f1115'],
          },
          dataLabels: {
            enabled: true,
            style: {
              fontSize: '11px',
              fontWeight: 600,
            },
          },
          tooltip: {
            enabled: true,
            custom: ({ seriesIndex, dataPointIndex, w }) => {
              var d = w.config.series[seriesIndex].data[dataPointIndex]
              var up = d.colorValue >= 0
              return (
                '<div class="apexcharts-tooltip-title" style="font-weight:600">' +
                d.x +
                '</div>' +
                '<div style="padding:6px 10px 8px">' +
                this.fmtCap(d.y) +
                ' &nbsp;<span style="color:' +
                (up ? '#3ddc84' : '#ff6b5e') +
                '">' +
                this.fmtPct(d.colorValue) +
                '</span></div>'
              )
            },
          },
          plotOptions: {
            treemap: {
              borderRadius: 2,
              dataLabels: {
                format: 'truncate',
              },
              colorScale: {
                // Colour by the day's move, not by market value.
                colorValue: 'colorValue',
                gradient: {
                  colors: ['#c0392b', '#5b6570', '#1e9e57'],
                  midpoint: 0,
                },
                gradientLegend: {
                  enabled: true,
                  width: '46%',
                  thickness: 10,
                  formatter: (v) => {
                    return (v > 0 ? '+' : '') + v.toFixed(1) + '%'
                  },
                },
              },
              // Click a sector or an industry to fill the canvas with it.
              zoom: {
                enabled: true,
              },
              parents: {
                padding: 3,
                tooltip: {
                  formatter: (o) => {
                    return (
                      '<div class="apexcharts-tooltip-title" style="font-weight:600">' +
                      o.name +
                      '</div>' +
                      '<div style="padding:6px 10px 8px">' +
                      this.fmtCap(o.value) +
                      ' &nbsp;&middot;&nbsp; ' +
                      o.leafCount +
                      ' companies &nbsp;&middot;&nbsp; ' +
                      o.percentOfTotal.toFixed(1) +
                      '% of market</div>'
                    )
                  },
                },
              },
              levels: [
                {
                  // Sector.
                  padding: 5,
                  header: {
                    height: 26,
                    minWidth: 64,
                    style: {
                      fontSize: '13px',
                      fontWeight: 700,
                    },
                    formatter: (name, o) => {
                      return name + '   ' + this.fmtCap(o.value)
                    },
                  },
                },
                {
                  // Industry.
                  padding: 2,
                  header: {
                    height: 15,
                    minWidth: 46,
                    style: {
                      fontSize: '10px',
                      fontWeight: 500,
                    },
                  },
                },
              ],
            },
          },
        };
  ngAfterViewInit() {
    (window as any).ApexCharts.setLicense('APEX-eyJleHBpcnlEYXRlIjoiMjEyNi0wNy0wNCIsImlzc3VlRGF0ZSI6IjIwMjYtMDctMjgiLCJwbGFuIjoicHJlbWl1bSIsImRvbWFpbnMiOlsiYXBleGNoYXJ0cy5jb20iLCIxMjcuMC4wLjEiLCJsb2NhbGhvc3QiXSwic2lnIjoieVBmb1VCc0Z3TU9ZdUEyaEZkR0I2Y1FtZ0JITUtXcVdJSjB2NVRESXRZbFR3eDJMUmh6R2x0RUc3VXJ4X0s3b25ZMWRZb2Z2VGItN01ydFYyNDVyOWcifQ==');
  }

  ngOnDestroy() {
    // no cleanup needed
  }
}
Nested Market Map - Angular Treemap Charts | ApexCharts.js | ApexCharts.js