@swimlane/ngx-charts
Version:
Declarative Charting Framework for Angular
1 lines • 1.1 MB
Source Map (JSON)
{"version":3,"file":"swimlane-ngx-charts.mjs","sources":["../../../../projects/swimlane/ngx-charts/src/lib/utils/throttle.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/tooltip/position/placement-type.enum.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/tooltip/position/position.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/tooltip/tooltip.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/tooltip/injection-registery.service.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/tooltip/injection.service.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/tooltip/tooltip.service.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/types/legend.model.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/types/scale-type.enum.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/label.helper.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/legend/legend-entry.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/legend/legend.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/legend/scale-legend.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/charts/chart.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/utils/visibility-observer.ts","../../../../projects/swimlane/ngx-charts/src/lib/utils/types.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/base-chart.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/types/orientation.enum.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/axes/axis-label.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/trim-label.helper.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/axes/ticks.helper.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/types/text-anchor.enum.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/axes/x-axis-ticks.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/axes/x-axis.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/shape.helper.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/axes/y-axis-ticks.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/axes/y-axis.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/axes/axes.module.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/tooltip/style.type.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/tooltip/show.type.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/tooltip/tooltip.directive.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/tooltip/tooltip.module.ts","../../../../projects/swimlane/ngx-charts/src/lib/utils/id.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/types/bar-orientation.enum.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/circle.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/svg-linear-gradient.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/circle-series.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/grid-panel.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/grid-panel-series.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/svg-radial-gradient.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/area.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/count/count.helper.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/count/count.directive.ts","../../../../projects/swimlane/ngx-charts/src/lib/events.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/tooltip-area.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/timeline/timeline.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/legend/advanced-legend.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/chart-common.module.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/view-dimensions.helper.ts","../../../../projects/swimlane/ngx-charts/src/lib/utils/color-sets.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/color.helper.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/domain.helper.ts","../../../../projects/swimlane/ngx-charts/src/lib/utils/sort.ts","../../../../projects/swimlane/ngx-charts/src/lib/area-chart/area-series.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/area-chart/area-chart.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/area-chart/area-chart-normalized.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/area-chart/area-chart-stacked.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/area-chart/area-chart.module.ts","../../../../projects/swimlane/ngx-charts/src/lib/bar-chart/bar.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/bar-chart/types/bar-chart-type.enum.ts","../../../../projects/swimlane/ngx-charts/src/lib/bar-chart/types/d0-type.enum.ts","../../../../projects/swimlane/ngx-charts/src/lib/bar-chart/bar-label.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/bar-chart/series-horizontal.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/bar-chart/bar-horizontal.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/bar-chart/bar-horizontal-2d.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/bar-chart/bar-horizontal-normalized.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/bar-chart/bar-horizontal-stacked.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/bar-chart/series-vertical.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/bar-chart/bar-vertical.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/bar-chart/bar-vertical-2d.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/bar-chart/bar-vertical-normalized.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/bar-chart/bar-vertical-stacked.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/bar-chart/bar-chart.module.ts","../../../../projects/swimlane/ngx-charts/src/lib/box-chart/box.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/box-chart/box-series.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/box-chart/box-chart.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/box-chart/box-chart.module.ts","../../../../projects/swimlane/ngx-charts/src/lib/bubble-chart/bubble-chart.utils.ts","../../../../projects/swimlane/ngx-charts/src/lib/bubble-chart/bubble-series.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/bubble-chart/bubble-chart.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/bubble-chart/bubble-chart.module.ts","../../../../projects/swimlane/ngx-charts/src/lib/heat-map/heat-map-cell.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/heat-map/heat-map-cell-series.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/heat-map/heat-map.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/heat-map/heat-map.module.ts","../../../../projects/swimlane/ngx-charts/src/lib/line-chart/line.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/line-chart/line-series.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/line-chart/line-chart.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/line-chart/line-chart.module.ts","../../../../projects/swimlane/ngx-charts/src/lib/pie-chart/pie-label.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/polar-chart/polar-series.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/polar-chart/polar-chart.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/pie-chart/pie-arc.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/pie-chart/pie-series.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/pie-chart/advanced-pie-chart.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/pie-chart/pie-chart.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/grid-layout.helper.ts","../../../../projects/swimlane/ngx-charts/src/lib/pie-chart/pie-grid-series.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/pie-chart/pie-grid.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/pie-chart/pie-chart.module.ts","../../../../projects/swimlane/ngx-charts/src/lib/polar-chart/polar-chart.module.ts","../../../../projects/swimlane/ngx-charts/src/lib/utils/calculate-width.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/constants/font-widths.ts","../../../../projects/swimlane/ngx-charts/src/lib/number-card/card.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/utils/color-utils.ts","../../../../projects/swimlane/ngx-charts/src/lib/number-card/card-series.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/number-card/number-card.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/number-card/number-card.module.ts","../../../../projects/swimlane/ngx-charts/src/lib/tree-map/tree-map-cell.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/tree-map/tree-map-cell-series.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/tree-map/tree-map.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/tree-map/tree-map.module.ts","../../../../projects/swimlane/ngx-charts/src/lib/gauge/linear-gauge.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/gauge/gauge-arc.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/gauge/gauge-axis.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/gauge/gauge.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/gauge/percent-gauge/percent-gauge.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/gauge/gauge.module.ts","../../../../projects/swimlane/ngx-charts/src/lib/polyfills.ts","../../../../projects/swimlane/ngx-charts/src/lib/sankey/sankey.component.ts","../../../../projects/swimlane/ngx-charts/src/lib/sankey/sankey.module.ts","../../../../projects/swimlane/ngx-charts/src/lib/ngx-charts.module.ts","../../../../projects/swimlane/ngx-charts/src/lib/common/tick-format.helper.ts","../../../../projects/swimlane/ngx-charts/src/lib/models/chart-data.model.ts","../../../../projects/swimlane/ngx-charts/src/public-api.ts","../../../../projects/swimlane/ngx-charts/src/swimlane-ngx-charts.ts"],"sourcesContent":["/**\n * Throttle a function\n *\n */\nexport function throttle(func: any, wait: number, options?: any) {\n options = options || {};\n let context;\n let args;\n let result;\n let timeout = null;\n let previous = 0;\n\n function later() {\n previous = options.leading === false ? 0 : +new Date();\n timeout = null;\n result = func.apply(context, args);\n }\n\n return function () {\n const now = +new Date();\n\n if (!previous && options.leading === false) {\n previous = now;\n }\n\n const remaining = wait - (now - previous);\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n context = this;\n // eslint-disable-next-line prefer-rest-params\n args = arguments;\n\n if (remaining <= 0) {\n clearTimeout(timeout);\n timeout = null;\n previous = now;\n result = func.apply(context, args);\n } else if (!timeout && options.trailing !== false) {\n timeout = setTimeout(later, remaining);\n }\n\n return result;\n };\n}\n\n/**\n * Throttle decorator\n *\n * class MyClass {\n * throttleable(10)\n * myFn() { ... }\n * }\n */\nexport function throttleable(duration: number, options?: any) {\n return function innerDecorator(target, key, descriptor) {\n return {\n configurable: true,\n enumerable: descriptor.enumerable,\n get: function getter() {\n Object.defineProperty(this, key, {\n configurable: true,\n enumerable: descriptor.enumerable,\n value: throttle(descriptor.value, duration, options)\n });\n\n return this[key];\n }\n };\n };\n}\n","export enum PlacementTypes {\n Top = 'top',\n Bottom = 'bottom',\n Left = 'left',\n Right = 'right',\n Center = 'center'\n}\n","import { PlacementTypes } from './placement-type.enum';\n\nconst caretOffset = 7;\n\nfunction verticalPosition(elDimensions: DOMRect, popoverDimensions: DOMRect, alignment: PlacementTypes): number {\n if (alignment === PlacementTypes.Top) {\n return elDimensions.top - caretOffset;\n }\n\n if (alignment === PlacementTypes.Bottom) {\n return elDimensions.top + elDimensions.height - popoverDimensions.height + caretOffset;\n }\n\n if (alignment === PlacementTypes.Center) {\n return elDimensions.top + elDimensions.height / 2 - popoverDimensions.height / 2;\n }\n\n return undefined;\n}\n\nfunction horizontalPosition(elDimensions: DOMRect, popoverDimensions: DOMRect, alignment: PlacementTypes): number {\n if (alignment === PlacementTypes.Left) {\n return elDimensions.left - caretOffset;\n }\n\n if (alignment === PlacementTypes.Right) {\n return elDimensions.left + elDimensions.width - popoverDimensions.width + caretOffset;\n }\n\n if (alignment === PlacementTypes.Center) {\n return elDimensions.left + elDimensions.width / 2 - popoverDimensions.width / 2;\n }\n\n return undefined;\n}\n\n/**\n * Position helper for the popover directive.\n *\n * @export\n */\nexport class PositionHelper {\n /**\n * Calculate vertical alignment position\n *\n * @memberOf PositionHelper\n */\n static calculateVerticalAlignment(\n elDimensions: DOMRect,\n popoverDimensions: DOMRect,\n alignment: PlacementTypes\n ): number {\n let result = verticalPosition(elDimensions, popoverDimensions, alignment);\n\n if (result + popoverDimensions.height > window.innerHeight) {\n result = window.innerHeight - popoverDimensions.height;\n }\n\n return result;\n }\n\n /**\n * Calculate vertical caret position\n *\n * @memberOf PositionHelper\n */\n static calculateVerticalCaret(\n elDimensions: DOMRect,\n popoverDimensions: DOMRect,\n caretDimensions: DOMRect,\n alignment: PlacementTypes\n ): number {\n let result;\n\n if (alignment === PlacementTypes.Top) {\n result = elDimensions.height / 2 - caretDimensions.height / 2 + caretOffset;\n }\n\n if (alignment === PlacementTypes.Bottom) {\n result = popoverDimensions.height - elDimensions.height / 2 - caretDimensions.height / 2 - caretOffset;\n }\n\n if (alignment === PlacementTypes.Center) {\n result = popoverDimensions.height / 2 - caretDimensions.height / 2;\n }\n\n const popoverPosition = verticalPosition(elDimensions, popoverDimensions, alignment);\n if (popoverPosition + popoverDimensions.height > window.innerHeight) {\n result += popoverPosition + popoverDimensions.height - window.innerHeight;\n }\n\n return result;\n }\n\n /**\n * Calculate horz alignment position\n *\n * @memberOf PositionHelper\n */\n static calculateHorizontalAlignment(\n elDimensions: DOMRect,\n popoverDimensions: DOMRect,\n alignment: PlacementTypes\n ): number {\n let result = horizontalPosition(elDimensions, popoverDimensions, alignment);\n\n if (result + popoverDimensions.width > window.innerWidth) {\n result = window.innerWidth - popoverDimensions.width;\n }\n\n return result;\n }\n\n /**\n * Calculate horz caret position\n *\n * @memberOf PositionHelper\n */\n static calculateHorizontalCaret(\n elDimensions: DOMRect,\n popoverDimensions: DOMRect,\n caretDimensions: DOMRect,\n alignment: PlacementTypes\n ): number {\n let result;\n\n if (alignment === PlacementTypes.Left) {\n result = elDimensions.width / 2 - caretDimensions.width / 2 + caretOffset;\n }\n\n if (alignment === PlacementTypes.Right) {\n result = popoverDimensions.width - elDimensions.width / 2 - caretDimensions.width / 2 - caretOffset;\n }\n\n if (alignment === PlacementTypes.Center) {\n result = popoverDimensions.width / 2 - caretDimensions.width / 2;\n }\n\n const popoverPosition = horizontalPosition(elDimensions, popoverDimensions, alignment);\n if (popoverPosition + popoverDimensions.width > window.innerWidth) {\n result += popoverPosition + popoverDimensions.width - window.innerWidth;\n }\n\n return result;\n }\n\n /**\n * Checks if the element's position should be flipped\n *\n * @memberOf PositionHelper\n */\n static shouldFlip(\n elDimensions: DOMRect,\n popoverDimensions: DOMRect,\n placement: PlacementTypes,\n spacing: number\n ): boolean {\n let flip = false;\n\n if (placement === PlacementTypes.Right) {\n if (elDimensions.left + elDimensions.width + popoverDimensions.width + spacing > window.innerWidth) {\n flip = true;\n }\n }\n\n if (placement === PlacementTypes.Left) {\n if (elDimensions.left - popoverDimensions.width - spacing < 0) {\n flip = true;\n }\n }\n\n if (placement === PlacementTypes.Top) {\n if (elDimensions.top - popoverDimensions.height - spacing < 0) {\n flip = true;\n }\n }\n\n if (placement === PlacementTypes.Bottom) {\n if (elDimensions.top + elDimensions.height + popoverDimensions.height + spacing > window.innerHeight) {\n flip = true;\n }\n }\n\n return flip;\n }\n\n /**\n * Position caret\n *\n * @memberOf PositionHelper\n */\n static positionCaret(placement, elmDim, hostDim, caretDimensions, alignment: PlacementTypes): any {\n let top = 0;\n let left = 0;\n\n if (placement === PlacementTypes.Right) {\n left = -7;\n top = PositionHelper.calculateVerticalCaret(hostDim, elmDim, caretDimensions, alignment);\n } else if (placement === PlacementTypes.Left) {\n left = elmDim.width;\n top = PositionHelper.calculateVerticalCaret(hostDim, elmDim, caretDimensions, alignment);\n } else if (placement === PlacementTypes.Top) {\n top = elmDim.height;\n left = PositionHelper.calculateHorizontalCaret(hostDim, elmDim, caretDimensions, alignment);\n } else if (placement === PlacementTypes.Bottom) {\n top = -7;\n left = PositionHelper.calculateHorizontalCaret(hostDim, elmDim, caretDimensions, alignment);\n }\n\n return { top, left };\n }\n\n /**\n * Position content\n *\n * @memberOf PositionHelper\n */\n static positionContent(placement, elmDim, hostDim, spacing, alignment): any {\n let top = 0;\n let left = 0;\n\n if (placement === PlacementTypes.Right) {\n left = hostDim.left + hostDim.width + spacing;\n top = PositionHelper.calculateVerticalAlignment(hostDim, elmDim, alignment);\n } else if (placement === PlacementTypes.Left) {\n left = hostDim.left - elmDim.width - spacing;\n top = PositionHelper.calculateVerticalAlignment(hostDim, elmDim, alignment);\n } else if (placement === PlacementTypes.Top) {\n top = hostDim.top - elmDim.height - spacing;\n left = PositionHelper.calculateHorizontalAlignment(hostDim, elmDim, alignment);\n } else if (placement === PlacementTypes.Bottom) {\n top = hostDim.top + hostDim.height + spacing;\n left = PositionHelper.calculateHorizontalAlignment(hostDim, elmDim, alignment);\n }\n\n return { top, left };\n }\n\n /**\n * Determine placement based on flip\n *\n * @memberOf PositionHelper\n */\n static determinePlacement(placement: PlacementTypes, elmDim: DOMRect, hostDim: DOMRect, spacing: number): any {\n const shouldFlip = PositionHelper.shouldFlip(hostDim, elmDim, placement, spacing);\n\n if (shouldFlip) {\n if (placement === PlacementTypes.Right) {\n return PlacementTypes.Left;\n } else if (placement === PlacementTypes.Left) {\n return PlacementTypes.Right;\n } else if (placement === PlacementTypes.Top) {\n return PlacementTypes.Bottom;\n } else if (placement === PlacementTypes.Bottom) {\n return PlacementTypes.Top;\n }\n }\n\n return placement;\n }\n}\n","import {\n Input,\n Component,\n ElementRef,\n AfterViewInit,\n ViewEncapsulation,\n HostListener,\n ViewChild,\n HostBinding,\n Renderer2,\n PLATFORM_ID,\n Inject,\n TemplateRef\n} from '@angular/core';\n\nimport { throttleable } from '../../utils/throttle';\nimport { PositionHelper, PlacementTypes } from './position';\n\nimport { StyleTypes } from './style.type';\nimport { isPlatformBrowser } from '@angular/common';\n\n@Component({\n selector: 'ngx-tooltip-content',\n template: `\n <div>\n <span #caretElm [hidden]=\"!showCaret\" class=\"tooltip-caret position-{{ this.placement }}\"> </span>\n <div class=\"tooltip-content\">\n <span *ngIf=\"!title\">\n <ng-template [ngTemplateOutlet]=\"template\" [ngTemplateOutletContext]=\"{ model: context }\"> </ng-template>\n </span>\n <span *ngIf=\"title\" [innerHTML]=\"title\"> </span>\n </div>\n </div>\n `,\n encapsulation: ViewEncapsulation.None,\n styleUrls: ['./tooltip.component.scss'],\n standalone: false\n})\nexport class TooltipContentComponent implements AfterViewInit {\n @Input() host: ElementRef;\n @Input() showCaret: boolean;\n @Input() type: StyleTypes;\n @Input() placement: PlacementTypes;\n @Input() alignment: PlacementTypes;\n @Input() spacing: number;\n @Input() cssClass: string;\n @Input() title: string;\n @Input() template: TemplateRef<any>;\n @Input() context: any;\n\n @ViewChild('caretElm') caretElm: ElementRef;\n\n @HostBinding('class')\n get cssClasses(): string {\n let clz = 'ngx-charts-tooltip-content';\n clz += ` position-${this.placement}`;\n clz += ` type-${this.type}`;\n clz += ` ${this.cssClass}`;\n return clz;\n }\n\n constructor(public element: ElementRef, private renderer: Renderer2, @Inject(PLATFORM_ID) private platformId: any) {}\n\n ngAfterViewInit(): void {\n setTimeout(this.position.bind(this));\n }\n\n position(): void {\n if (!isPlatformBrowser(this.platformId)) {\n return;\n }\n\n const nativeElm = this.element.nativeElement;\n const hostDim = this.host.nativeElement.getBoundingClientRect();\n\n // if no dims were found, never show\n if (!hostDim.height && !hostDim.width) return;\n\n const elmDim = nativeElm.getBoundingClientRect();\n this.checkFlip(hostDim, elmDim);\n this.positionContent(nativeElm, hostDim, elmDim);\n\n if (this.showCaret) {\n this.positionCaret(hostDim, elmDim);\n }\n\n // animate its entry\n setTimeout(() => this.renderer.addClass(nativeElm, 'animate'), 1);\n }\n\n positionContent(nativeElm: HTMLElement, hostDim: DOMRect, elmDim: DOMRect): void {\n const { top, left } = PositionHelper.positionContent(this.placement, elmDim, hostDim, this.spacing, this.alignment);\n\n this.renderer.setStyle(nativeElm, 'top', `${top}px`);\n this.renderer.setStyle(nativeElm, 'left', `${left}px`);\n }\n\n positionCaret(hostDim: DOMRect, elmDim: DOMRect): void {\n const caretElm = this.caretElm.nativeElement;\n const caretDimensions = caretElm.getBoundingClientRect();\n const { top, left } = PositionHelper.positionCaret(\n this.placement,\n elmDim,\n hostDim,\n caretDimensions,\n this.alignment\n );\n\n this.renderer.setStyle(caretElm, 'top', `${top}px`);\n this.renderer.setStyle(caretElm, 'left', `${left}px`);\n }\n\n checkFlip(hostDim: DOMRect, elmDim: DOMRect): void {\n this.placement = PositionHelper.determinePlacement(this.placement, elmDim, hostDim, this.spacing);\n }\n\n @HostListener('window:resize')\n @throttleable(100)\n onWindowResize(): void {\n this.position();\n }\n}\n","import { ComponentRef, Type } from '@angular/core';\nimport { InjectionService } from './injection.service';\n\nexport interface PartialBindings {\n inputs?: object;\n outputs?: object;\n}\n\nexport abstract class InjectionRegisteryService<T = any> {\n protected abstract type: Type<T>;\n\n protected defaults: PartialBindings = {};\n protected components: Map<any, Array<ComponentRef<T>>> = new Map();\n\n constructor(public injectionService: InjectionService) {}\n\n getByType(type: Type<T> = this.type) {\n return this.components.get(type);\n }\n\n create(bindings: object): ComponentRef<T> {\n return this.createByType(this.type, bindings);\n }\n\n createByType(type: Type<T>, bindings: PartialBindings): ComponentRef<T> {\n bindings = this.assignDefaults(bindings);\n\n const component = this.injectComponent(type, bindings);\n this.register(type, component);\n\n return component;\n }\n\n destroy(instance: ComponentRef<T>): void {\n const compsByType = this.components.get(instance.componentType);\n\n if (compsByType && compsByType.length) {\n const idx = compsByType.indexOf(instance);\n\n if (idx > -1) {\n const component = compsByType[idx];\n component.destroy();\n compsByType.splice(idx, 1);\n }\n }\n }\n\n destroyAll(): void {\n this.destroyByType(this.type);\n }\n\n destroyByType(type: Type<T>): void {\n const comps = this.components.get(type);\n\n if (comps && comps.length) {\n let i = comps.length - 1;\n while (i >= 0) {\n this.destroy(comps[i--]);\n }\n }\n }\n\n protected injectComponent(type: Type<T>, bindings: PartialBindings): ComponentRef<T> {\n return this.injectionService.appendComponent(type, bindings);\n }\n\n protected assignDefaults(bindings: PartialBindings): PartialBindings {\n const inputs = { ...this.defaults.inputs };\n const outputs = { ...this.defaults.outputs };\n\n if (!bindings.inputs && !bindings.outputs) {\n bindings = { inputs: bindings };\n }\n\n if (inputs) {\n bindings.inputs = { ...inputs, ...bindings.inputs };\n }\n\n if (outputs) {\n bindings.outputs = { ...outputs, ...bindings.outputs };\n }\n\n return bindings;\n }\n\n protected register(type: Type<T>, component: ComponentRef<T>): void {\n if (!this.components.has(type)) {\n this.components.set(type, []);\n }\n\n const types = this.components.get(type);\n types.push(component);\n }\n}\n","import {\n ApplicationRef,\n ComponentFactoryResolver,\n ComponentRef,\n Injectable,\n Injector,\n ViewContainerRef,\n EmbeddedViewRef,\n Type\n} from '@angular/core';\nimport { DomPortalOutlet, ComponentPortal } from '@angular/cdk/portal';\n\nfunction isViewContainerRef(x: any): x is ViewContainerRef {\n return x.element;\n}\n\n/**\n * Injection service is a helper to append components\n * dynamically to a known location in the DOM, most\n * noteably for dialogs/tooltips appending to body.\n *\n * @export\n */\n@Injectable()\nexport class InjectionService {\n static globalRootViewContainer: ViewContainerRef = null;\n\n /**\n * Sets a default global root view container. This is useful for\n * things like ngUpgrade that doesn't have a ApplicationRef root.\n *\n * @param container\n */\n static setGlobalRootViewContainer(container: ViewContainerRef): void {\n InjectionService.globalRootViewContainer = container;\n }\n\n private _container: ViewContainerRef;\n\n constructor(private applicationRef: ApplicationRef, private injector: Injector) {}\n\n /**\n * Gets the root view container to inject the component to.\n *\n * @memberOf InjectionService\n */\n getRootViewContainer(): ViewContainerRef | ComponentRef<any> {\n if (this._container) return this._container;\n if (InjectionService.globalRootViewContainer) return InjectionService.globalRootViewContainer;\n\n if (this.applicationRef.components.length) return this.applicationRef.components[0];\n\n throw new Error(\n 'View Container not found! ngUpgrade needs to manually set this via setRootViewContainer or setGlobalRootViewContainer.'\n );\n }\n\n /**\n * Overrides the default root view container. This is useful for\n * things like ngUpgrade that doesn't have a ApplicationRef root.\n *\n * @param container\n *\n * @memberOf InjectionService\n */\n setRootViewContainer(container: ViewContainerRef): void {\n this._container = container;\n }\n\n /**\n * Gets the html element for a component ref.\n *\n * @param componentRef\n *\n * @memberOf InjectionService\n */\n getComponentRootNode(component: ViewContainerRef | ComponentRef<any>): HTMLElement {\n if (isViewContainerRef(component)) {\n return component.element.nativeElement;\n }\n if (component.hostView && (component.hostView as EmbeddedViewRef<any>).rootNodes.length > 0) {\n return (component.hostView as EmbeddedViewRef<any>).rootNodes[0] as HTMLElement;\n }\n\n // the top most component root node has no `hostView`\n return component.location.nativeElement;\n }\n\n /**\n * Gets the root component container html element.\n *\n * @memberOf InjectionService\n */\n getRootViewContainerNode(component: ViewContainerRef | ComponentRef<any>): HTMLElement {\n return this.getComponentRootNode(component);\n }\n\n /**\n * Projects the bindings onto the component\n *\n * @param component\n * @param options\n *\n * @memberOf InjectionService\n */\n projectComponentBindings(component: ComponentRef<any>, bindings: any): ComponentRef<any> {\n if (bindings) {\n if (bindings.inputs !== undefined) {\n const bindingKeys = Object.getOwnPropertyNames(bindings.inputs);\n for (const bindingName of bindingKeys) {\n component.instance[bindingName] = bindings.inputs[bindingName];\n }\n }\n\n if (bindings.outputs !== undefined) {\n const eventKeys = Object.getOwnPropertyNames(bindings.outputs);\n for (const eventName of eventKeys) {\n component.instance[eventName] = bindings.outputs[eventName];\n }\n }\n }\n\n return component;\n }\n\n /**\n * Appends a component to a adjacent location\n *\n * @param componentClass\n * @param [options={}]\n * @param [location]\n *\n * @memberOf InjectionService\n */\n appendComponent<T>(componentClass: Type<T>, bindings: any = {}, location?: any): ComponentRef<any> {\n if (!location) location = this.getRootViewContainer();\n const appendLocation = this.getComponentRootNode(location);\n\n const portalHost = new DomPortalOutlet(appendLocation, this.applicationRef, this.injector);\n\n const portal = new ComponentPortal(componentClass);\n\n const componentRef = portalHost.attach(portal);\n this.projectComponentBindings(componentRef, bindings);\n return componentRef;\n }\n}\n","import { Injectable } from '@angular/core';\nimport { InjectionService } from './injection.service';\nimport { TooltipContentComponent } from './tooltip.component';\nimport { InjectionRegisteryService } from './injection-registery.service';\n@Injectable()\nexport class TooltipService extends InjectionRegisteryService<TooltipContentComponent> {\n type: any = TooltipContentComponent;\n\n constructor(injectionService: InjectionService) {\n super(injectionService);\n }\n}\n","import { ScaleType } from './scale-type.enum';\n\nexport interface LegendOptions {\n colors: any;\n domain: any[];\n position: LegendPosition;\n title: string;\n scaleType: ScaleType;\n}\n\nexport enum LegendPosition {\n Right = 'right',\n Below = 'below'\n}\n\nexport enum LegendType {\n ScaleLegend = 'scaleLegend',\n Legend = 'legend'\n}\n","export enum ScaleType {\n Time = 'time',\n Linear = 'linear',\n Ordinal = 'ordinal',\n Quantile = 'quantile'\n}\n","/**\n * Formats a label given a date, number or string.\n *\n * @export\n */\nexport function formatLabel(label: any): string {\n if (label instanceof Date) {\n label = label.toLocaleDateString();\n } else {\n label = label.toLocaleString();\n }\n\n return label;\n}\n\n/**\n * Escapes a label.\n *\n * @export\n */\nexport function escapeLabel(label: any): string {\n return label.toLocaleString().replace(/[&'`\"<>]/g, match => {\n return {\n '&': '&',\n // tslint:disable-next-line: quotemark\n \"'\": ''',\n '`': '`',\n '\"': '"',\n '<': '<',\n '>': '>'\n }[match];\n });\n}\n","import { Component, Input, Output, ChangeDetectionStrategy, HostListener, EventEmitter } from '@angular/core';\n\n@Component({\n selector: 'ngx-charts-legend-entry',\n template: `\n <span [title]=\"formattedLabel\" tabindex=\"-1\" [class.active]=\"isActive\" (click)=\"select.emit(formattedLabel)\">\n <span class=\"legend-label-color\" [style.background-color]=\"color\" (click)=\"toggle.emit(formattedLabel)\"> </span>\n <span class=\"legend-label-text\">\n {{ trimmedLabel }}\n </span>\n </span>\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n standalone: false\n})\nexport class LegendEntryComponent {\n @Input() color: string;\n @Input() label: string;\n @Input() formattedLabel: string;\n @Input() isActive: boolean = false;\n\n @Output() select: EventEmitter<string> = new EventEmitter();\n @Output() activate: EventEmitter<{ name: string }> = new EventEmitter();\n @Output() deactivate: EventEmitter<{ name: string }> = new EventEmitter();\n @Output() toggle: EventEmitter<string> = new EventEmitter();\n\n get trimmedLabel(): string {\n return this.formattedLabel || '(empty)';\n }\n\n @HostListener('mouseenter')\n onMouseEnter(): void {\n this.activate.emit({ name: this.label });\n }\n\n @HostListener('mouseleave')\n onMouseLeave(): void {\n this.deactivate.emit({ name: this.label });\n }\n}\n","import {\n Component,\n Input,\n ChangeDetectionStrategy,\n Output,\n EventEmitter,\n SimpleChanges,\n OnChanges,\n ChangeDetectorRef,\n ViewEncapsulation\n} from '@angular/core';\nimport { formatLabel } from '../label.helper';\nimport { ColorHelper } from '../color.helper';\n\nexport interface LegendEntry {\n color: string;\n formattedLabel: string;\n label: string;\n}\n\n@Component({\n selector: 'ngx-charts-legend',\n template: `\n <div [style.width.px]=\"width\">\n <header class=\"legend-title\" *ngIf=\"title?.length > 0\">\n <span class=\"legend-title-text\">{{ title }}</span>\n </header>\n <div class=\"legend-wrap\">\n <ul class=\"legend-labels\" [class.horizontal-legend]=\"horizontal\" [style.max-height.px]=\"height - 45\">\n <li *ngFor=\"let entry of legendEntries; trackBy: trackBy\" class=\"legend-label\">\n <ngx-charts-legend-entry\n [label]=\"entry.label\"\n [formattedLabel]=\"entry.formattedLabel\"\n [color]=\"entry.color\"\n [isActive]=\"isActive(entry)\"\n (select)=\"labelClick.emit($event)\"\n (activate)=\"activate($event)\"\n (deactivate)=\"deactivate($event)\"\n >\n </ngx-charts-legend-entry>\n </li>\n </ul>\n </div>\n </div>\n `,\n styleUrls: ['./legend.component.scss'],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n standalone: false\n})\nexport class LegendComponent implements OnChanges {\n @Input() data: string[];\n @Input() title: string;\n @Input() colors: ColorHelper;\n @Input() height: number;\n @Input() width: number;\n @Input() activeEntries;\n @Input() horizontal = false;\n\n @Output() labelClick: EventEmitter<string> = new EventEmitter();\n @Output() labelActivate: EventEmitter<{ name: string }> = new EventEmitter();\n @Output() labelDeactivate: EventEmitter<{ name: string }> = new EventEmitter();\n\n legendEntries: LegendEntry[] = [];\n\n constructor(private cd: ChangeDetectorRef) {}\n\n ngOnChanges(changes: SimpleChanges): void {\n this.update();\n }\n\n update(): void {\n this.cd.markForCheck();\n this.legendEntries = this.getLegendEntries();\n }\n\n getLegendEntries(): LegendEntry[] {\n const items = [];\n for (const label of this.data) {\n const formattedLabel = formatLabel(label);\n\n const idx = items.findIndex(i => {\n return i.label === formattedLabel;\n });\n\n if (idx === -1) {\n items.push({\n label,\n formattedLabel,\n color: this.colors.getColor(label)\n });\n }\n }\n\n return items;\n }\n\n isActive(entry: LegendEntry): boolean {\n if (!this.activeEntries) return false;\n const item = this.activeEntries.find(d => {\n return entry.label === d.name;\n });\n return item !== undefined;\n }\n\n activate(item: { name: string }) {\n this.labelActivate.emit(item);\n }\n\n deactivate(item: { name: string }) {\n this.labelDeactivate.emit(item);\n }\n\n trackBy(index: number, item: LegendEntry): string {\n return item.label;\n }\n}\n","import { Component, Input, OnChanges, ChangeDetectionStrategy, SimpleChanges, ViewEncapsulation } from '@angular/core';\n\n@Component({\n selector: 'ngx-charts-scale-legend',\n template: `\n <div\n class=\"scale-legend\"\n [class.horizontal-legend]=\"horizontal\"\n [style.height.px]=\"horizontal ? undefined : height\"\n [style.width.px]=\"width\"\n >\n <div class=\"scale-legend-label\">\n <span>{{ valueRange[1].toLocaleString() }}</span>\n </div>\n <div class=\"scale-legend-wrap\" [style.background]=\"gradient\"></div>\n <div class=\"scale-legend-label\">\n <span>{{ valueRange[0].toLocaleString() }}</span>\n </div>\n </div>\n `,\n styleUrls: ['./scale-legend.component.scss'],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n standalone: false\n})\nexport class ScaleLegendComponent implements OnChanges {\n @Input() valueRange: number[];\n @Input() colors: any;\n @Input() height: number;\n @Input() width: number;\n @Input() horizontal: boolean = false;\n\n gradient: string;\n\n ngOnChanges(changes: SimpleChanges): void {\n const gradientValues = this.gradientString(this.colors.range(), this.colors.domain());\n const direction = this.horizontal ? 'right' : 'bottom';\n this.gradient = `linear-gradient(to ${direction}, ${gradientValues})`;\n }\n\n /**\n * Generates the string used in the gradient stylesheet properties\n * @param colors array of colors\n * @param splits array of splits on a scale of (0, 1)\n */\n gradientString(colors: string[], splits: number[]): string {\n // add the 100%\n splits.push(1);\n const pairs = [];\n colors.reverse().forEach((c, i) => {\n pairs.push(`${c} ${Math.round(splits[i] * 100)}%`);\n });\n\n return pairs.join(', ');\n }\n}\n","import {\n Component,\n Input,\n OnChanges,\n ChangeDetectionStrategy,\n EventEmitter,\n Output,\n SimpleChanges\n} from '@angular/core';\nimport { TooltipService } from '../tooltip/tooltip.service';\nimport { LegendOptions, LegendType, LegendPosition } from '../types/legend.model';\nimport { ScaleType } from '../types/scale-type.enum';\n\n@Component({\n providers: [TooltipService],\n selector: 'ngx-charts-chart',\n template: `\n <div class=\"ngx-charts-outer\" [style.width.px]=\"view[0]\" [style.height.px]=\"view[1]\">\n <svg class=\"ngx-charts\" [attr.width]=\"chartWidth\" [attr.height]=\"view[1]\">\n <ng-content></ng-content>\n </svg>\n <ngx-charts-scale-legend\n *ngIf=\"showLegend && legendType === LegendType.ScaleLegend\"\n class=\"chart-legend\"\n [horizontal]=\"legendOptions && legendOptions.position === LegendPosition.Below\"\n [valueRange]=\"legendOptions.domain\"\n [colors]=\"legendOptions.colors\"\n [height]=\"view[1]\"\n [width]=\"legendWidth\"\n >\n </ngx-charts-scale-legend>\n <ngx-charts-legend\n *ngIf=\"showLegend && legendType === LegendType.Legend\"\n class=\"chart-legend\"\n [horizontal]=\"legendOptions && legendOptions.position === LegendPosition.Below\"\n [data]=\"legendOptions.domain\"\n [title]=\"legendOptions.title\"\n [colors]=\"legendOptions.colors\"\n [height]=\"view[1]\"\n [width]=\"legendWidth\"\n [activeEntries]=\"activeEntries\"\n (labelClick)=\"legendLabelClick.emit($event)\"\n (labelActivate)=\"legendLabelActivate.emit($event)\"\n (labelDeactivate)=\"legendLabelDeactivate.emit($event)\"\n >\n </ngx-charts-legend>\n </div>\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n standalone: false\n})\nexport class ChartComponent implements OnChanges {\n @Input() view: [number, number];\n @Input() showLegend: boolean = false;\n @Input() legendOptions: LegendOptions;\n @Input() legendType: LegendType;\n @Input() activeEntries: any[];\n @Input() animations: boolean = true;\n\n @Output() legendLabelClick = new EventEmitter<string>();\n @Output() legendLabelActivate = new EventEmitter<{ name: string }>();\n @Output() legendLabelDeactivate = new EventEmitter<{ name: string }>();\n\n chartWidth: number;\n title: string;\n legendWidth: number;\n\n readonly LegendPosition = LegendPosition;\n readonly LegendType = LegendType;\n\n ngOnChanges(changes: SimpleChanges): void {\n this.update();\n }\n\n update(): void {\n let legendColumns = 0;\n if (this.showLegend) {\n this.legendType = this.getLegendType();\n\n if (!this.legendOptions || this.legendOptions.position === LegendPosition.Right) {\n if (this.legendType === LegendType.ScaleLegend) {\n legendColumns = 1;\n } else {\n legendColumns = 2;\n }\n }\n }\n\n const chartColumns = 12 - legendColumns;\n\n this.chartWidth = Math.floor((this.view[0] * chartColumns) / 12.0);\n this.legendWidth =\n !this.legendOptions || this.legendOptions.position === LegendPosition.Right\n ? Math.floor((this.view[0] * legendColumns) / 12.0)\n : this.chartWidth;\n }\n\n getLegendType(): LegendType {\n return this.legendOptions.scaleType === ScaleType.Linear ? LegendType.ScaleLegend : LegendType.Legend;\n }\n}\n","import { Output, EventEmitter, NgZone, Directive, ElementRef } from '@angular/core';\n\n/**\n * Visibility Observer\n */\n@Directive({\n selector: 'visibility-observer',\n standalone: false\n})\nexport class VisibilityObserver {\n @Output() visible: EventEmitter<any> = new EventEmitter();\n\n timeout: any;\n isVisible: boolean = false;\n\n constructor(private element: ElementRef, private zone: NgZone) {\n this.runCheck();\n }\n\n destroy(): void {\n clearTimeout(this.timeout);\n }\n\n onVisibilityChange(): void {\n // trigger zone recalc for columns\n this.zone.run(() => {\n this.isVisible = true;\n this.visible.emit(true);\n });\n }\n\n runCheck(): void {\n const check = () => {\n if (!this.element) {\n return;\n }\n\n // https://davidwalsh.name/offsetheight-visibility\n const { offsetHeight, offsetWidth } = this.element.nativeElement;\n\n if (offsetHeight && offsetWidth) {\n clearTimeout(this.timeout);\n this.onVisibilityChange();\n } else {\n clearTimeout(this.timeout);\n this.zone.runOutsideAngular(() => {\n this.timeout = setTimeout(() => check(), 100);\n });\n }\n };\n\n this.zone.runOutsideAngular(() => {\n this.timeout = setTimeout(() => check());\n });\n }\n}\n","export function isDate(value): boolean {\n return toString.call(value) === '[object Date]';\n}\n\nexport function isNumber(value): boolean {\n return typeof value === 'number';\n}\n","import { isPlatformBrowser, isPlatformServer } from '@angular/common';\nimport {\n ElementRef,\n NgZone,\n ChangeDetectorRef,\n Component,\n Input,\n Output,\n EventEmitter,\n AfterViewInit,\n OnDestroy,\n OnChanges,\n SimpleChanges,\n PLATFORM_ID,\n Inject,\n OnInit\n} from '@angular/core';\n\nimport { fromEvent as observableFromEvent } from 'rxjs';\nimport { debounceTime } from 'rxjs/operators';\nimport { VisibilityObserver } from '../utils/visibility-observer';\nimport { isDate } from '../utils/types';\nimport { Color } from '../utils/color-sets';\nimport { ScaleType } from './types/scale-type.enum';\nimport { ViewDimensions } from './types/view-dimension.interface';\n\n@Component({\n selector: 'base-chart',\n template: ` <div></div> `,\n standalone: false\n})\nexport class BaseChartComponent implements OnChanges, AfterViewInit, OnDestroy, OnInit {\n @Input() declare results: any;\n @Input() view: [number, number];\n @Input() scheme: string | Color = 'cool';\n @Input() schemeType: ScaleType = ScaleType.Ordinal;\n @Input() customColors: any;\n @Input() animations: boolean = true;\n\n @Output() select = new EventEmitter();\n\n width: number;\n height: number;\n resizeSubscription: any;\n visibilityObserver: VisibilityObserver;\n\n constructor(\n protected chartElement: ElementRef,\n protected zone: NgZone,\n protected cd: ChangeDetectorRef,\n @Inject(PLATFORM_ID) public platformId: any\n ) {}\n\n ngOnInit() {\n if (isPlatformServer(this.platformId)) {\n this.animations = false;\n }\n }\n\n ngAfterViewInit(): void {\n this.bindWindowResizeEvent();\n\n // listen for visibility of the element for hidden by default scenario\n this.visibilityObserver = new VisibilityObserver(this.chartElement, this.zone);\n this.visibilityObserver.visible.subscribe(this.update.bind(this));\n }\n\n ngOnDestroy(): void {\n this.unbindEvents();\n if (this.visibilityObserver) {\n this.visibilityObserver.visible.unsubscribe();\n this.visibilityObserver.destroy();\n }\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n this.update();\n }\n\n update(): void {\n if (this.results) {\n this.results = this.cloneData(this.results);\n } else {\n this.results = [];\n }\n\n if (this.view) {\n this.width = this.view[0];\n this.height = this.view[1];\n } else {\n const dims = this.getContainerDims();\n if (dims) {\n this.width = dims.width;\n this.height = dims.height;\n }\n }\n\n // default values if width or height are 0 or undefined\n if (!this.width) {\n this.width = 600;\n }\n\n if (!this.height) {\n this.height = 400;\n }\n\n this.width = Math.floor(this.width);\n this.height = Math.floor(this.height);\n\n if (this.cd) {\n this.cd.markForCheck();\n }\n }\n\n getContainerDims(): ViewDimensions {\n let width;\n let height;\n const hostElem = this.chartElement.nativeElement;\n\n if (isPlatformBrowser(this.platformId) && hostElem.parentNode !== null) {\n // Get the container dimensions\n const dims = hostElem.parentNode.getBoundingClientRect();\n width = dims.width;\n height = dims.height;\n }\n\n if (width && height) {\n return { width, height };\n }\n\n return null;\n }\n\n /**\n * Converts all date objects that appear as name\n * into formatted date strings\n */\n formatDates(): void {\n for (let i = 0; i < this.results.length; i++) {\n const g = this.results[i];\n g.label = g.name;\n if (isDate(g.label)) {\n g.label = g.label.toLocaleDateString();\n }\n\n if (g.series) {\n for (let j = 0; j < g.series.length; j++) {\n const d = g.series[j];\n d.label = d.name;\n if (isDate(d.label)) {\n d.label = d.label.toLocaleDateString();\n }\n }\n }\n }\n }\n\n protected unbindEvents(): void {\n if (this.resizeSubscription) {\n this.resizeSubscription.unsubscribe();\n }\n }\n\n private bindWindowResizeEvent(): void {\n if (!isPlatformBrowser(this.platformId)) {\n return;\n }\n\n const source = observableFromEvent(window, 'resize');\n const subscription = source.pipe(debounceTime(200)).subscribe(e => {\n this.update();\n if (this.cd) {\n this.cd.markForCheck();\n }\n });\n this.resizeSubscription = subscription;\n }\n\n /**\n * Clones the data into a new object\n *\n * @memberOf BaseChart\n */\n private cloneData(data): any {\n const results = [];\n\n for (const item of data) {\n const copy = {};\n\n if (item['name'] !== undefined) {\n copy['name'] = item['name'];\n }\n\n if (item['value'] !== undefined) {\n copy['value'] = item['value'];\n }\n\n if (item['series'] !== undefined) {\n copy['series'] = [];\n for (const seriesItem of item['series']) {\n const seriesItemCopy = Object.assign({}, seriesItem);\n copy['series'].push(seriesItemCopy);\n }\n }\n\n if (item['extra'] !== undefined) {\n copy['extra'] = JSON.parse(JSON.stringify(item['extra']));\n }\n\n if (item['source'] !== undefined) {\n copy['source'] = item['source'];\n }\n\n if (item['target'] !== undefined) {\n copy['target'] = item['target'];\n }\n\n results.push(copy);\n }\n\n return results;\n }\n}\n","export enum Orientation {\n Top = 'top',\n Bottom = 'bottom',\n Left = 'left',\n Right = 'right'\n}\n","import { Component, Input, ElementRef, OnChanges, SimpleChanges, ChangeDetectionStrategy } from '@angular/core';\nimport { Orientation } from '../types/orientation.enum';\n\n@Component({\n selector: 'g[ngx-charts-axis-label]',\n template: `\n <svg:text\n [attr.stroke-width]=\"strokeWidth\"\n [attr.x]=\"x\"\n [attr.y]=\"y\"\n [attr.text-anchor]=\"textAnchor\"\n [attr.transform]=\"transform\"\n >\n {{ label }}\n </svg:text>\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n