@nanahoshi/mona-ui 0.18.5 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/README.md +71 -13
  2. package/fesm2022/nanahoshi-mona-ui-auto-complete.mjs +11 -3
  3. package/fesm2022/nanahoshi-mona-ui-breadcrumb.mjs +17 -9
  4. package/fesm2022/nanahoshi-mona-ui-button-group.mjs +16 -7
  5. package/fesm2022/nanahoshi-mona-ui-calendar.mjs +122 -48
  6. package/fesm2022/nanahoshi-mona-ui-card.mjs +22 -14
  7. package/fesm2022/nanahoshi-mona-ui-chart.mjs +78 -18
  8. package/fesm2022/nanahoshi-mona-ui-check-box.mjs +1 -1
  9. package/fesm2022/nanahoshi-mona-ui-chip.mjs +199 -77
  10. package/fesm2022/nanahoshi-mona-ui-circular-progress-bar.mjs +1 -2
  11. package/fesm2022/nanahoshi-mona-ui-color-gradient.mjs +23 -5
  12. package/fesm2022/nanahoshi-mona-ui-color-palette.mjs +49 -28
  13. package/fesm2022/nanahoshi-mona-ui-color-picker.mjs +42 -26
  14. package/fesm2022/nanahoshi-mona-ui-combo-box.mjs +11 -3
  15. package/fesm2022/nanahoshi-mona-ui-date-picker.mjs +28 -16
  16. package/fesm2022/nanahoshi-mona-ui-datetime-picker.mjs +74 -51
  17. package/fesm2022/nanahoshi-mona-ui-dialog.mjs +57 -25
  18. package/fesm2022/nanahoshi-mona-ui-dropdown-list.mjs +13 -5
  19. package/fesm2022/nanahoshi-mona-ui-dropdowns.mjs +17 -6
  20. package/fesm2022/nanahoshi-mona-ui-editor.mjs +178 -59
  21. package/fesm2022/nanahoshi-mona-ui-filter.mjs +137 -54
  22. package/fesm2022/{nanahoshi-mona-ui-grid-grid-footer-cell.component-WEDbZ5vy.mjs → nanahoshi-mona-ui-grid-grid-footer-cell.component-Bg7rckst.mjs} +2 -2
  23. package/fesm2022/{nanahoshi-mona-ui-grid-grid-footer-table-cell.directive-ibH5osCg.mjs → nanahoshi-mona-ui-grid-grid-footer-table-cell.directive-BSSpaCLL.mjs} +2 -2
  24. package/fesm2022/nanahoshi-mona-ui-grid-grid-list.component-D9AwQFDV.mjs +145 -0
  25. package/fesm2022/{nanahoshi-mona-ui-grid-grid-toggle.component-hc-LeIb0.mjs → nanahoshi-mona-ui-grid-grid-toggle.component-Byb9iTes.mjs} +21 -17
  26. package/fesm2022/{nanahoshi-mona-ui-grid-grid-virtual-list.component-DYajpOb9.mjs → nanahoshi-mona-ui-grid-grid-virtual-list.component-CBmdtrXm.mjs} +5 -5
  27. package/fesm2022/{nanahoshi-mona-ui-grid-nanahoshi-mona-ui-grid-Pm8Fbp6M.mjs → nanahoshi-mona-ui-grid-nanahoshi-mona-ui-grid-DPmJmCap.mjs} +90 -42
  28. package/fesm2022/nanahoshi-mona-ui-grid.mjs +1 -1
  29. package/fesm2022/nanahoshi-mona-ui-i18n.mjs +1168 -0
  30. package/fesm2022/nanahoshi-mona-ui-internal-list.mjs +12 -4
  31. package/fesm2022/nanahoshi-mona-ui-internal-tree.mjs +48 -21
  32. package/fesm2022/nanahoshi-mona-ui-list-box.mjs +33 -18
  33. package/fesm2022/nanahoshi-mona-ui-list-view.mjs +10 -10
  34. package/fesm2022/nanahoshi-mona-ui-list.mjs +2 -0
  35. package/fesm2022/nanahoshi-mona-ui-menubar.mjs +29 -16
  36. package/fesm2022/nanahoshi-mona-ui-multi-select.mjs +12 -3
  37. package/fesm2022/nanahoshi-mona-ui-notification.mjs +23 -18
  38. package/fesm2022/nanahoshi-mona-ui-numeric-text-box.mjs +211 -106
  39. package/fesm2022/nanahoshi-mona-ui-otp-input.mjs +14 -6
  40. package/fesm2022/nanahoshi-mona-ui-pager.mjs +46 -19
  41. package/fesm2022/nanahoshi-mona-ui-popup-menu.mjs +57 -46
  42. package/fesm2022/nanahoshi-mona-ui-popup.mjs +35 -15
  43. package/fesm2022/nanahoshi-mona-ui-progress-bar.mjs +38 -17
  44. package/fesm2022/nanahoshi-mona-ui-rating.mjs +25 -7
  45. package/fesm2022/nanahoshi-mona-ui-scroll-view.mjs +431 -101
  46. package/fesm2022/nanahoshi-mona-ui-segmented.mjs +1 -1
  47. package/fesm2022/nanahoshi-mona-ui-sheet.mjs +26 -8
  48. package/fesm2022/nanahoshi-mona-ui-sidebar.mjs +222 -28
  49. package/fesm2022/nanahoshi-mona-ui-slider.mjs +91 -36
  50. package/fesm2022/nanahoshi-mona-ui-spinner.mjs +34 -15
  51. package/fesm2022/nanahoshi-mona-ui-split-button.mjs +39 -23
  52. package/fesm2022/nanahoshi-mona-ui-splitter.mjs +50 -25
  53. package/fesm2022/nanahoshi-mona-ui-stepper.mjs +32 -14
  54. package/fesm2022/nanahoshi-mona-ui-switch.mjs +9 -9
  55. package/fesm2022/nanahoshi-mona-ui-tabs.mjs +74 -56
  56. package/fesm2022/nanahoshi-mona-ui-text-box.mjs +16 -8
  57. package/fesm2022/nanahoshi-mona-ui-time-picker.mjs +33 -19
  58. package/fesm2022/nanahoshi-mona-ui-time-selector.mjs +66 -27
  59. package/fesm2022/nanahoshi-mona-ui-tree-view.mjs +23 -15
  60. package/fesm2022/nanahoshi-mona-ui-window.mjs +71 -40
  61. package/i18n/package.json +4 -0
  62. package/package.json +5 -1
  63. package/types/nanahoshi-mona-ui-auto-complete.d.ts +6 -1
  64. package/types/nanahoshi-mona-ui-breadcrumb.d.ts +9 -3
  65. package/types/nanahoshi-mona-ui-button-group.d.ts +9 -3
  66. package/types/nanahoshi-mona-ui-calendar.d.ts +13 -3
  67. package/types/nanahoshi-mona-ui-card.d.ts +8 -2
  68. package/types/nanahoshi-mona-ui-chart.d.ts +10 -1
  69. package/types/nanahoshi-mona-ui-chip.d.ts +14 -5
  70. package/types/nanahoshi-mona-ui-color-gradient.d.ts +6 -1
  71. package/types/nanahoshi-mona-ui-color-palette.d.ts +21 -10
  72. package/types/nanahoshi-mona-ui-color-picker.d.ts +30 -20
  73. package/types/nanahoshi-mona-ui-combo-box.d.ts +6 -1
  74. package/types/nanahoshi-mona-ui-date-picker.d.ts +7 -2
  75. package/types/nanahoshi-mona-ui-datetime-picker.d.ts +33 -8
  76. package/types/nanahoshi-mona-ui-dialog.d.ts +16 -7
  77. package/types/nanahoshi-mona-ui-dropdown-list.d.ts +6 -1
  78. package/types/nanahoshi-mona-ui-dropdowns.d.ts +4 -1
  79. package/types/nanahoshi-mona-ui-editor.d.ts +6 -1
  80. package/types/nanahoshi-mona-ui-filter.d.ts +16 -10
  81. package/types/nanahoshi-mona-ui-grid.d.ts +38 -1
  82. package/types/nanahoshi-mona-ui-i18n.d.ts +633 -0
  83. package/types/nanahoshi-mona-ui-internal-list.d.ts +7 -2
  84. package/types/nanahoshi-mona-ui-internal-tree.d.ts +7 -3
  85. package/types/nanahoshi-mona-ui-list-box.d.ts +9 -4
  86. package/types/nanahoshi-mona-ui-list-view.d.ts +6 -6
  87. package/types/nanahoshi-mona-ui-list.d.ts +1 -1
  88. package/types/nanahoshi-mona-ui-menubar.d.ts +59 -58
  89. package/types/nanahoshi-mona-ui-multi-select.d.ts +6 -1
  90. package/types/nanahoshi-mona-ui-notification.d.ts +11 -5
  91. package/types/nanahoshi-mona-ui-numeric-text-box.d.ts +24 -15
  92. package/types/nanahoshi-mona-ui-otp-input.d.ts +9 -3
  93. package/types/nanahoshi-mona-ui-pager.d.ts +19 -6
  94. package/types/nanahoshi-mona-ui-popup.d.ts +2 -1
  95. package/types/nanahoshi-mona-ui-progress-bar.d.ts +9 -7
  96. package/types/nanahoshi-mona-ui-rating.d.ts +19 -12
  97. package/types/nanahoshi-mona-ui-scroll-view.d.ts +34 -28
  98. package/types/nanahoshi-mona-ui-sheet.d.ts +8 -2
  99. package/types/nanahoshi-mona-ui-sidebar.d.ts +3 -0
  100. package/types/nanahoshi-mona-ui-slider.d.ts +44 -26
  101. package/types/nanahoshi-mona-ui-spinner.d.ts +13 -4
  102. package/types/nanahoshi-mona-ui-split-button.d.ts +62 -56
  103. package/types/nanahoshi-mona-ui-splitter.d.ts +9 -6
  104. package/types/nanahoshi-mona-ui-stepper.d.ts +9 -3
  105. package/types/nanahoshi-mona-ui-switch.d.ts +1 -1
  106. package/types/nanahoshi-mona-ui-tabs.d.ts +96 -35
  107. package/types/nanahoshi-mona-ui-text-box.d.ts +11 -5
  108. package/types/nanahoshi-mona-ui-time-picker.d.ts +7 -2
  109. package/types/nanahoshi-mona-ui-time-selector.d.ts +16 -5
  110. package/types/nanahoshi-mona-ui-tree-view.d.ts +15 -10
  111. package/types/nanahoshi-mona-ui-window.d.ts +26 -20
  112. package/fesm2022/nanahoshi-mona-ui-grid-grid-list.component-ZM3CneJ0.mjs +0 -145
@@ -1,6 +1,7 @@
1
1
  import { NgTemplateOutlet } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
3
  import { inject, TemplateRef, Directive, InjectionToken, ElementRef, input, isDevMode, Injectable, signal, computed, DestroyRef, viewChild, contentChild, output, effect, untracked, afterNextRender, Component, model } from '@angular/core';
4
+ import { MonaI18nService, injectComponentDirection, formatNumber } from '@nanahoshi/mona-ui/i18n';
4
5
  import { twMerge } from 'tailwind-merge';
5
6
  import { interpolate, parse, formatRgb, wcagContrast } from 'culori';
6
7
  import { scaleLinear, scaleLog, scaleSymlog, scalePow, scaleSqrt, scaleTime, scaleUtc, scaleBand } from 'd3-scale';
@@ -52,6 +53,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
52
53
  }]
53
54
  }] });
54
55
 
56
+ const CHART_DEFAULT_MESSAGES = {
57
+ change: "Change",
58
+ chart: "Chart",
59
+ chartLegend: "Chart legend",
60
+ close: "Close",
61
+ closeAbbreviation: "C",
62
+ colorScale: "Color scale",
63
+ conversion: "Conversion",
64
+ divergingRangeDescription: (title, min, mid, max) => `${title}, ${min} to ${mid} to ${max}`,
65
+ dropOff: "Drop-off",
66
+ falling: "Falling",
67
+ high: "High",
68
+ highAbbreviation: "H",
69
+ labelValueSeparator: ":",
70
+ low: "Low",
71
+ lowAbbreviation: "L",
72
+ noData: "No data available",
73
+ open: "Open",
74
+ openAbbreviation: "O",
75
+ overall: "Overall",
76
+ range: "Range",
77
+ rangeDescription: (title, min, max) => `${title}, ${min} to ${max}`,
78
+ rising: "Rising",
79
+ runningTotal: "Running Total",
80
+ size: "size",
81
+ unchanged: "Unchanged",
82
+ value: "Value",
83
+ visualIndicatorClamped: "Visual indicator clamped"
84
+ };
85
+
55
86
  class BrowserAnimationClock {
56
87
  cancelFrame(id) {
57
88
  if (typeof cancelAnimationFrame !== "undefined") {
@@ -52669,8 +52700,8 @@ const chartLegendBaseThemeVariants = cva("flex flex-wrap items-center gap-4 text
52669
52700
  // to non-empty (or vice versa), which would otherwise shift the
52670
52701
  // X axis vertically as the last/first series is toggled.
52671
52702
  bottom: "justify-center mt-3 min-h-5",
52672
- left: "flex-col justify-center mr-4",
52673
- right: "flex-col justify-center ml-4",
52703
+ left: "flex-col justify-center me-4",
52704
+ right: "flex-col justify-center ms-4",
52674
52705
  top: "justify-center mb-2 min-h-5"
52675
52706
  }
52676
52707
  }
@@ -52693,8 +52724,8 @@ const chartHeaderBaseThemeVariants = cva("flex flex-col gap-1 mb-3 select-none",
52693
52724
  variants: {
52694
52725
  align: {
52695
52726
  center: "items-center text-center",
52696
- left: "items-start text-left",
52697
- right: "items-end text-right"
52727
+ left: "items-start text-start",
52728
+ right: "items-end text-end"
52698
52729
  }
52699
52730
  }
52700
52731
  });
@@ -52734,6 +52765,7 @@ class ChartComponent {
52734
52765
  #dataLabelMeasurements;
52735
52766
  #destroyRef;
52736
52767
  #elementRef;
52768
+ #i18n;
52737
52769
  #hasInitializedDefaultSelection;
52738
52770
  #hasInitializedDefaultViewport;
52739
52771
  #internalSelectedMarkIds;
@@ -52836,6 +52868,7 @@ class ChartComponent {
52836
52868
  this.#dataLabelMeasurements = new Map();
52837
52869
  this.#destroyRef = inject(DestroyRef);
52838
52870
  this.#elementRef = inject(ElementRef);
52871
+ this.#i18n = inject(MonaI18nService);
52839
52872
  this.#hasInitializedDefaultSelection = signal(false, /* @ts-ignore */
52840
52873
  ...(ngDevMode ? [{ debugName: "#hasInitializedDefaultSelection" }] : /* istanbul ignore next */ []));
52841
52874
  this.#hasInitializedDefaultViewport = signal(false, /* @ts-ignore */
@@ -52939,6 +52972,7 @@ class ChartComponent {
52939
52972
  this.#suppressNextCanvasClick = false;
52940
52973
  this.#synchronizationController = null;
52941
52974
  this.#themeObserver = null;
52975
+ this.messages = this.#i18n.componentMessages("chart", CHART_DEFAULT_MESSAGES);
52942
52976
  this.activeAccessibilityText = signal("", /* @ts-ignore */
52943
52977
  ...(ngDevMode ? [{ debugName: "activeAccessibilityText" }] : /* istanbul ignore next */ []));
52944
52978
  this.animationDurationCss = computed(() => `${this.normalizedAnimationOptions().duration}ms`, /* @ts-ignore */
@@ -53081,7 +53115,7 @@ class ChartComponent {
53081
53115
  this.effectiveAriaLabel = computed(() => {
53082
53116
  const explicit = this.ariaLabel().trim();
53083
53117
  const builtIn = this.title().trim();
53084
- return explicit || builtIn || "Chart";
53118
+ return explicit || builtIn || this.messages().chart;
53085
53119
  }, /* @ts-ignore */
53086
53120
  ...(ngDevMode ? [{ debugName: "effectiveAriaLabel" }] : /* istanbul ignore next */ []));
53087
53121
  this.effectiveSelectedMarkIds = computed(() => {
@@ -54231,7 +54265,8 @@ class ChartComponent {
54231
54265
  const fromStr = matchingHit.formattedFrom ?? (matchingHit.fromValue !== undefined ? String(matchingHit.fromValue) : "");
54232
54266
  const toStr = matchingHit.formattedTo ?? (matchingHit.toValue !== undefined ? String(matchingHit.toValue) : "");
54233
54267
  if (isRange && fromStr && toStr) {
54234
- return `${matchingHit.seriesName}: ${xStr}, ${fromStr} to ${toStr}`;
54268
+ const title = `${matchingHit.seriesName}: ${xStr}`;
54269
+ return this.messages().rangeDescription(title, fromStr, toStr);
54235
54270
  }
54236
54271
  return `${matchingHit.seriesName}: ${xStr}, ${yStr}`;
54237
54272
  }
@@ -56943,7 +56978,7 @@ class ChartComponent {
56943
56978
  provide: CHART_CONTEXT,
56944
56979
  useExisting: ChartComponent
56945
56980
  }
56946
- ], queries: [{ propertyName: "noDataTemplate", first: true, predicate: ChartNoDataTemplateDirective, descendants: true, isSignal: true }, { propertyName: "subtitleTemplate", first: true, predicate: ChartSubtitleTemplateDirective, descendants: true, isSignal: true }, { propertyName: "titleTemplate", first: true, predicate: ChartTitleTemplateDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "canvasElement", first: true, predicate: ["canvas"], descendants: true, isSignal: true }, { propertyName: "plotSurfaceElement", first: true, predicate: ["plotSurface"], descendants: true, isSignal: true }, { propertyName: "svgElement", first: true, predicate: ["svgSurface"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (hasHeader()) {\n <div [class]=\"headerClasses()\" [style.text-align]=\"titleAlign()\">\n @if (titleTemplate(); as tpl) {\n <div data-mona-chart-export-role=\"title-template\">\n <ng-container\n [ngTemplateOutlet]=\"tpl.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: title(), title: title() }\" />\n </div>\n } @else if (title()) {\n <div [class]=\"titleClasses()\" data-mona-chart-export-role=\"title\">{{ title() }}</div>\n }\n @if (subtitleTemplate(); as subTpl) {\n <div data-mona-chart-export-role=\"subtitle-template\">\n <ng-container\n [ngTemplateOutlet]=\"subTpl.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: subtitle(), subtitle: subtitle() }\" />\n </div>\n } @else if (subtitle()) {\n <div [class]=\"subtitleClasses()\" data-mona-chart-export-role=\"subtitle\">{{ subtitle() }}</div>\n }\n </div>\n}\n<div [class]=\"layoutClasses()\">\n <div\n #plotSurface\n class=\"relative flex-1 min-h-0 min-w-0 w-full h-full overflow-hidden\"\n [style.order]=\"plotOrder()\"\n [style.touch-action]=\"touchActionStyle()\"\n [style.cursor]=\"viewportCursor() ?? 'default'\"\n (pointerdown)=\"onPointerDown($event)\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n (pointercancel)=\"onPointerCancel($event)\"\n (lostpointercapture)=\"onLostPointerCapture($event)\"\n (pointerleave)=\"onPointerLeave($event)\"\n (wheel)=\"onWheel($event)\"\n (click)=\"onCanvasClick($event)\">\n @if (renderer() === \"canvas\") {\n <canvas #canvas class=\"absolute inset-0 block h-full w-full pointer-events-none\"></canvas>\n } @else {\n <svg\n #svgSurface\n aria-hidden=\"true\"\n focusable=\"false\"\n class=\"absolute inset-0 block h-full w-full pointer-events-none\"\n xmlns=\"http://www.w3.org/2000/svg\"></svg>\n }\n\n <!-- DOM Cartesian Axis Labels & Titles -->\n @if (cartesianScene(); as cart) {\n @for (axisScene of cart.axes; track axisScene.axis + \":\" + (axisScene.axisId ?? \"\")) {\n @if (axisScene.visible) {\n @if (axisScene.labels !== false) {\n @for (\n tick of axisScene.ticks;\n track tick.tickKey ? tick.tickKey + \":\" + tick.index : tick.index\n ) {\n @if (tick.labelVisible !== false) {\n <div\n [class]=\"axisLabelClasses()\"\n [monaChartLabelMeasure]=\"tick.tickKey ?? ''\"\n data-mona-chart-export-role=\"axis-label\"\n [attr.data-mona-chart-export-mode]=\"\n resolveAxisLabelTemplate(axisScene) ? 'raster' : 'vector'\n \"\n [style.left.px]=\"axisLabelLeft(cart, axisScene, tick)\"\n [style.top.px]=\"axisLabelTop(cart, axisScene, tick)\"\n [style.max-width.px]=\"axisScene.labelMaxWidth ?? null\"\n [style.transform]=\"axisLabelTransform(axisScene, tick)\"\n [style.transform-origin]=\"axisLabelTransformOrigin(axisScene)\">\n @if (resolveAxisLabelTemplate(axisScene); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: tick.value,\n axis: axisScene.axis,\n axisId: axisScene.axisId,\n index: tick.index,\n position: axisScene.position,\n scaleType: axisScene.scaleType,\n value: tick.value\n }\" />\n } @else {\n {{ tick.formattedValue }}\n }\n </div>\n }\n }\n }\n\n <!-- Axis Title -->\n @if (axisScene.title) {\n <div\n class=\"mona-chart-axis-title absolute text-xs font-medium text-muted-foreground select-none pointer-events-none whitespace-nowrap\"\n data-mona-chart-export-role=\"axis-title\"\n data-mona-chart-export-mode=\"vector\"\n [style.left.px]=\"axisTitleLeft(cart, axisScene)\"\n [style.top.px]=\"axisTitleTop(cart, axisScene)\"\n [style.transform]=\"\n axisScene.axis === 'x'\n ? axisScene.position === 'top'\n ? 'translate(-50%, 0)'\n : 'translate(-50%, -100%)'\n : axisScene.position === 'right'\n ? 'translate(-50%, -50%) rotate(90deg)'\n : 'translate(-50%, -50%) rotate(-90deg)'\n \">\n {{ axisScene.title }}\n </div>\n }\n }\n }\n }\n\n <!-- DOM Sector Slice Labels and Donut Center Overlay -->\n @if (polarSectorScene(); as pol) {\n @for (seriesScene of pol.series; track seriesScene.id) {\n @for (slice of seriesScene.slices; track slice.sliceId) {\n @if (shouldShowSliceLabel(slice)) {\n @if (isOutsideLabel() && slice.label) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs text-foreground select-none whitespace-nowrap transition-opacity duration-[var(--mona-chart-animation-duration,300ms)] ease-[var(--mona-chart-animation-easing,cubic-bezier(0,0,0.2,1))]\"\n [class.opacity-0]=\"isAnimating() && isStructuralAnimation()\"\n [attr.data-mona-chart-export-animation-suppression]=\"\n isAnimating() && isStructuralAnimation() ? 'opacity' : null\n \"\n [monaChartLabelMeasure]=\"'sector:' + slice.sliceId\"\n data-mona-chart-export-role=\"sector-label\"\n [attr.data-mona-chart-export-mode]=\"\n polarSeriesRegistration()?.sliceLabelTemplate?.() ? 'raster' : 'vector'\n \"\n [style.left.px]=\"slice.label.position.x\"\n [style.top.px]=\"slice.label.position.y\"\n [style.transform]=\"\n slice.label.side === 'right' ? 'translate(0, -50%)' : 'translate(-100%, -50%)'\n \">\n @if (polarSeriesRegistration()?.sliceLabelTemplate?.(); as labelTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate.templateRef\"\n [ngTemplateOutletContext]=\"sliceLabelContext(slice)\" />\n } @else {\n {{ sliceLabelText(slice) }}\n }\n </div>\n } @else {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs font-semibold select-none whitespace-nowrap flex items-center justify-center transition-opacity duration-[var(--mona-chart-animation-duration,300ms)] ease-[var(--mona-chart-animation-easing,cubic-bezier(0,0,0.2,1))]\"\n [class.opacity-0]=\"isAnimating() && isStructuralAnimation()\"\n [attr.data-mona-chart-export-animation-suppression]=\"\n isAnimating() && isStructuralAnimation() ? 'opacity' : null\n \"\n data-mona-chart-export-role=\"sector-label\"\n [attr.data-mona-chart-export-mode]=\"\n polarSeriesRegistration()?.sliceLabelTemplate?.() ? 'raster' : 'vector'\n \"\n [style.left.px]=\"slice.insideLabelPoint.x\"\n [style.top.px]=\"slice.insideLabelPoint.y\"\n [style.transform]=\"'translate(-50%, -50%)'\"\n [style.color]=\"sliceContrastColor(slice)\">\n @if (polarSeriesRegistration()?.sliceLabelTemplate?.(); as labelTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate.templateRef\"\n [ngTemplateOutletContext]=\"sliceLabelContext(slice)\" />\n } @else {\n {{ sliceLabelText(slice) }}\n }\n </div>\n }\n }\n }\n }\n\n @for (seriesScene of pol.series; track seriesScene.id) {\n <!-- Donut Center Template -->\n @if (\n seriesScene.type === \"donut\" &&\n pol.hasRenderableData &&\n seriesScene.slices.length > 0 &&\n donutSeriesRegistration()?.centerTemplate?.();\n as centerTemplate\n ) {\n <div\n class=\"absolute pointer-events-none flex flex-col items-center justify-center text-center overflow-hidden\"\n data-mona-chart-export-role=\"donut-center\"\n data-mona-chart-export-mode=\"raster\"\n [style.left.px]=\"pol.center.x\"\n [style.top.px]=\"pol.center.y\"\n [style.transform]=\"'translate(-50%, -50%)'\"\n [style.max-width.px]=\"seriesScene.innerRadius * 1.6\"\n [style.max-height.px]=\"seriesScene.innerRadius * 1.6\">\n <ng-container\n [ngTemplateOutlet]=\"centerTemplate.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: seriesScene.total,\n total: seriesScene.total,\n formattedTotal: seriesScene.formattedTotal,\n visibleSliceCount: seriesScene.slices.length,\n seriesId: seriesScene.id,\n seriesName: seriesScene.name\n }\" />\n </div>\n }\n }\n }\n\n <!-- DOM Gauge Center Overlay -->\n @if (polarArcScene(); as arcScene) {\n @if (gaugeScene(); as gaugeSeries) {\n @if (gaugeSeriesRegistration()?.centerTemplate?.(); as centerTemplate) {\n <div\n class=\"absolute pointer-events-none flex flex-col items-center justify-center text-center overflow-hidden\"\n data-mona-chart-export-role=\"gauge-center\"\n data-mona-chart-export-mode=\"raster\"\n [style.left.px]=\"arcScene.center.x\"\n [style.top.px]=\"arcScene.center.y\"\n [style.transform]=\"'translate(-50%, -50%)'\"\n [style.max-width.px]=\"gaugeSeries.value.innerRadius * 1.6\"\n [style.max-height.px]=\"gaugeSeries.value.innerRadius * 1.6\">\n <ng-container\n [ngTemplateOutlet]=\"centerTemplate.templateRef\"\n [ngTemplateOutletContext]=\"gaugeCenterContext(gaugeSeries)\" />\n </div>\n } @else if (gaugeSeries.showValue) {\n <div\n class=\"absolute pointer-events-none flex flex-col items-center justify-center text-center font-bold text-foreground select-none\"\n data-mona-chart-export-role=\"gauge-value\"\n data-mona-chart-export-mode=\"vector\"\n [style.left.px]=\"arcScene.center.x\"\n [style.top.px]=\"arcScene.center.y\"\n [style.transform]=\"'translate(-50%, -50%)'\"\n [style.font-size.px]=\"gaugeFontSize(gaugeSeries)\">\n <span>{{ gaugeSeries.value.formattedValue }}</span>\n </div>\n }\n }\n }\n\n <!-- DOM Radial Axis Labels (Angular Categories/Degrees and Radial Values) -->\n @if (polarAxisScene(); as radScene) {\n <!-- Angular Spoke Labels -->\n @if (radScene.angularAxis?.visible && radScene.angularAxis?.labels) {\n @for (tick of radScene.angularAxis.ticks; track tick.index) {\n @if (tick.visible) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs text-foreground select-none whitespace-nowrap\"\n [monaChartLabelMeasure]=\"'angular:' + tick.tickKey\"\n data-mona-chart-export-role=\"polar-angular-label\"\n [attr.data-mona-chart-export-mode]=\"\n angularAxisRegistration()?.labelTemplate?.() ? 'raster' : 'vector'\n \"\n [style.left.px]=\"tick.labelPoint.x\"\n [style.top.px]=\"tick.labelPoint.y\"\n [style.transform]=\"angularLabelTransform(tick)\">\n @if (angularAxisRegistration()?.labelTemplate?.(); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: tick.value,\n axis: 'angular',\n index: tick.index,\n value: tick.value\n }\" />\n } @else {\n {{ tick.formattedValue }}\n }\n </div>\n }\n }\n }\n\n <!-- Radial Numeric Tick Labels -->\n @if (radScene.radialAxis?.visible && radScene.radialAxis?.labels) {\n @for (tick of radScene.radialAxis.ticks; track tick.index) {\n @if (tick.visible) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs text-muted-foreground select-none whitespace-nowrap\"\n [monaChartLabelMeasure]=\"'radial:' + tick.tickKey\"\n data-mona-chart-export-role=\"polar-radial-label\"\n [attr.data-mona-chart-export-mode]=\"\n radialAxisRegistration()?.labelTemplate?.() ? 'raster' : 'vector'\n \"\n [style.left.px]=\"tick.labelPoint.x\"\n [style.top.px]=\"tick.labelPoint.y\"\n [style.transform]=\"radialLabelTransform(tick, radScene.radialAxis.labelAngle)\">\n @if (radialAxisRegistration()?.labelTemplate?.(); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: tick.value,\n axis: 'radial',\n index: tick.index,\n value: tick.value\n }\" />\n } @else {\n {{ tick.formattedValue }}\n }\n </div>\n }\n }\n }\n }\n\n <!-- DOM Treemap Labels -->\n @if (treemapScene(); as tm) {\n @for (seriesScene of tm.series; track seriesScene.id) {\n @for (lbl of seriesScene.labels; track lbl.nodeId) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs select-none overflow-hidden text-ellipsis whitespace-nowrap px-1.5 py-0.5 flex flex-col justify-center transition-opacity duration-[var(--mona-chart-animation-duration,300ms)] ease-[var(--mona-chart-animation-easing,cubic-bezier(0,0,0.2,1))]\"\n [class.opacity-0]=\"isAnimating()\"\n [attr.data-mona-chart-export-animation-suppression]=\"isAnimating() ? 'opacity' : null\"\n data-mona-chart-export-role=\"treemap-label\"\n data-mona-chart-export-mode=\"raster\"\n [style.left.px]=\"lbl.bounds.x\"\n [style.top.px]=\"lbl.bounds.y\"\n [style.width.px]=\"lbl.bounds.width\"\n [style.height.px]=\"lbl.bounds.height\"\n [style.color]=\"lbl.textColor\">\n @if (treemapSeriesRegistration()?.labelTemplate?.(); as labelTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate.templateRef\"\n [ngTemplateOutletContext]=\"treemapLabelContext(lbl, seriesScene)\" />\n } @else {\n <span class=\"font-medium truncate\">{{ lbl.formattedLabel }}</span>\n @if (lbl.showValue) {\n <span class=\"text-[11px] opacity-80 truncate\">{{ lbl.formattedValue }}</span>\n }\n }\n </div>\n }\n }\n }\n\n <!-- DOM Funnel Labels -->\n @if (funnelScene(); as fn) {\n @for (seriesScene of fn.series; track seriesScene.id) {\n @for (lbl of seriesScene.labels; track lbl.stageId) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs select-none overflow-hidden text-ellipsis whitespace-nowrap flex flex-col items-center justify-center transition-opacity duration-[var(--mona-chart-animation-duration,300ms)] ease-[var(--mona-chart-animation-easing,cubic-bezier(0,0,0.2,1))]\"\n [class.opacity-0]=\"isAnimating()\"\n [attr.data-mona-chart-export-animation-suppression]=\"isAnimating() ? 'opacity' : null\"\n data-mona-chart-export-role=\"funnel-label\"\n data-mona-chart-export-mode=\"raster\"\n [style.left.px]=\"lbl.bounds.x\"\n [style.top.px]=\"lbl.bounds.y\"\n [style.width.px]=\"lbl.bounds.width\"\n [style.height.px]=\"lbl.bounds.height\"\n [style.color]=\"lbl.textColor\">\n @if (funnelSeriesRegistration()?.labelTemplate?.(); as labelTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate.templateRef\"\n [ngTemplateOutletContext]=\"funnelLabelContext(lbl, seriesScene)\" />\n } @else {\n <span class=\"font-medium truncate\">{{ lbl.text }}</span>\n }\n </div>\n }\n }\n }\n\n <!-- DOM Waterfall Labels -->\n @if (waterfallScene(); as wf) {\n @for (seriesScene of wf.series; track seriesScene.id) {\n @for (lbl of seriesScene.labels; track lbl.itemId) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs select-none overflow-hidden text-ellipsis whitespace-nowrap flex items-center justify-center transition-opacity duration-[var(--mona-chart-animation-duration,300ms)] ease-[var(--mona-chart-animation-easing,cubic-bezier(0,0,0.2,1))]\"\n [class.opacity-0]=\"isAnimating()\"\n [attr.data-mona-chart-export-animation-suppression]=\"isAnimating() ? 'opacity' : null\"\n data-mona-chart-export-role=\"waterfall-label\"\n data-mona-chart-export-mode=\"raster\"\n [style.left.px]=\"lbl.bounds.x\"\n [style.top.px]=\"lbl.bounds.y\"\n [style.width.px]=\"lbl.bounds.width\"\n [style.height.px]=\"lbl.bounds.height\"\n [style.color]=\"lbl.textColor\">\n @if (waterfallSeriesRegistration()?.labelTemplate?.(); as labelTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate.templateRef\"\n [ngTemplateOutletContext]=\"waterfallLabelContext(lbl, seriesScene)\" />\n } @else {\n <span class=\"font-medium truncate\">{{ lbl.text }}</span>\n }\n </div>\n }\n }\n }\n\n <!-- DOM Cartesian Overlays (Reference Lines, Reference Bands, Point Annotations) -->\n @if (cartesianOverlayScene(); as overlays) {\n <!-- Reference Lines -->\n @for (line of overlays.referenceLines; track line.id) {\n @if (line.label) {\n <div\n aria-hidden=\"true\"\n [class]=\"referenceLabelClasses() + (line.label.labelClass ? ' ' + line.label.labelClass : '')\"\n [class.hidden]=\"!line.label.formattedText && !resolveReferenceLineTemplate(line.id)\"\n [monaChartOverlayLabelMeasure]=\"'overlay:line:' + line.id\"\n data-mona-chart-export-role=\"reference-label\"\n [attr.data-mona-chart-export-mode]=\"resolveReferenceLineTemplate(line.id) ? 'raster' : 'vector'\"\n [style.left.px]=\"referenceLineLabelLeft(line)\"\n [style.top.px]=\"referenceLineLabelTop(line)\"\n [style.transform]=\"referenceLineLabelTransform(line)\">\n @if (resolveReferenceLineTemplate(line.id); as template) {\n @if (resolveReferenceLineRegistration(line.id); as reg) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: reg.value(),\n axis: line.axis,\n axisId: line.axisId,\n coordinate: line.coordinate,\n formattedValue: line.formattedValue,\n kind: 'line',\n value: reg.value()\n }\" />\n }\n } @else {\n {{ line.label.formattedText }}\n }\n </div>\n }\n }\n\n <!-- Reference Bands -->\n @for (band of overlays.referenceBands; track band.id) {\n @if (band.label) {\n <div\n aria-hidden=\"true\"\n [class]=\"referenceLabelClasses() + (band.label.labelClass ? ' ' + band.label.labelClass : '')\"\n [class.hidden]=\"!band.label.formattedText && !resolveReferenceBandTemplate(band.id)\"\n [monaChartOverlayLabelMeasure]=\"'overlay:band:' + band.id\"\n data-mona-chart-export-role=\"reference-label\"\n [attr.data-mona-chart-export-mode]=\"resolveReferenceBandTemplate(band.id) ? 'raster' : 'vector'\"\n [style.left.px]=\"referenceBandLabelLeft(band)\"\n [style.top.px]=\"referenceBandLabelTop(band)\"\n [style.transform]=\"referenceBandLabelTransform(band)\">\n @if (resolveReferenceBandTemplate(band.id); as template) {\n @if (resolveReferenceBandRegistration(band.id); as reg) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: { from: reg.from(), to: reg.to() },\n axis: band.axis,\n axisId: band.axisId,\n bounds: band.bounds,\n formattedFrom: band.formattedFrom,\n formattedTo: band.formattedTo,\n from: reg.from(),\n kind: 'band',\n to: reg.to()\n }\" />\n }\n } @else {\n {{ band.label.formattedText }}\n }\n </div>\n }\n }\n\n <!-- Point Annotations -->\n @for (ann of overlays.annotations; track ann.id) {\n @if (ann.label) {\n <div\n aria-hidden=\"true\"\n [class]=\"annotationLabelClasses() + (ann.label.labelClass ? ' ' + ann.label.labelClass : '')\"\n [class.hidden]=\"!ann.label.formattedText && !resolveAnnotationTemplate(ann.id)\"\n [monaChartOverlayLabelMeasure]=\"'overlay:ann:' + ann.id\"\n data-mona-chart-export-role=\"annotation-label\"\n [attr.data-mona-chart-export-mode]=\"resolveAnnotationTemplate(ann.id) ? 'raster' : 'vector'\"\n [style.left.px]=\"annotationLabelLeft(ann)\"\n [style.top.px]=\"annotationLabelTop(ann)\"\n [style.transform]=\"annotationLabelTransform(ann)\">\n @if (resolveAnnotationTemplate(ann.id); as template) {\n @if (resolveAnnotationRegistration(ann.id); as reg) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: ann.data,\n data: ann.data,\n formattedX: ann.formattedX,\n formattedY: ann.formattedY,\n point: ann.point,\n x: reg.x(),\n xAxisId: ann.xAxisId,\n y: reg.y(),\n yAxisId: ann.yAxisId\n }\" />\n }\n } @else {\n {{ ann.label.formattedText }}\n }\n </div>\n }\n }\n }\n\n <!-- DOM Cartesian Data Labels (Template Layer) -->\n @if (cartesianDataLabelScene(); as labelScene) {\n @for (label of labelScene.templateLabels; track label.seriesId + \":\" + label.markId) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none select-none whitespace-nowrap transition-opacity duration-[var(--mona-chart-animation-duration,300ms)] ease-[var(--mona-chart-animation-easing,cubic-bezier(0,0,0.2,1))]\"\n [class.opacity-0]=\"isAnimating()\"\n [attr.data-mona-chart-export-animation-suppression]=\"isAnimating() ? 'opacity' : null\"\n [monaChartDataLabelMeasure]=\"label.seriesId + ':' + label.markId\"\n data-mona-chart-export-role=\"data-label-template\"\n data-mona-chart-export-mode=\"raster\"\n [style.left.px]=\"label.bounds.x\"\n [style.top.px]=\"label.bounds.y\">\n <ng-container\n [ngTemplateOutlet]=\"label.template.templateRef\"\n [ngTemplateOutletContext]=\"label.context\" />\n </div>\n }\n }\n\n <!-- Crosshair DOM Axis Labels -->\n @if (crosshairState(); as chState) {\n @if (cartesianXYScene(); as cart) {\n @if (resolveCrosshairRegistration(); as chReg) {\n @if (chReg.enabled() !== false) {\n @if (chState.x && chReg.showAxisLabels() !== false && chReg.showXLabel() !== false) {\n <div\n aria-hidden=\"true\"\n [class]=\"crosshairLabelClasses()\"\n [monaChartOverlayLabelMeasure]=\"'crosshair:x'\"\n data-mona-chart-export-role=\"crosshair-label\"\n [attr.data-mona-chart-export-mode]=\"chReg.template?.() ? 'raster' : 'vector'\"\n [style.left.px]=\"crosshairXLabelLeft(cart, chState)\"\n [style.top.px]=\"crosshairXLabelTop(cart, chState)\"\n [style.transform]=\"crosshairXLabelTransform(cart, chState)\">\n @if (chReg.template?.(); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: chState.x.value,\n axis: 'x',\n axisId: chState.x.axisId,\n coordinate: chState.x.coordinate,\n formattedValue: chState.x.formattedValue,\n snapped: chState.snapped,\n source: chState.source,\n value: chState.x.value\n }\" />\n } @else {\n {{ chState.x.formattedValue }}\n }\n </div>\n }\n\n @if (chState.y && chReg.showAxisLabels() !== false && chReg.showYLabel() !== false) {\n <div\n aria-hidden=\"true\"\n [class]=\"crosshairLabelClasses()\"\n [monaChartOverlayLabelMeasure]=\"'crosshair:y'\"\n data-mona-chart-export-role=\"crosshair-label\"\n [attr.data-mona-chart-export-mode]=\"chReg.template?.() ? 'raster' : 'vector'\"\n [style.left.px]=\"crosshairYLabelLeft(cart, chState)\"\n [style.top.px]=\"crosshairYLabelTop(cart, chState)\"\n [style.transform]=\"crosshairYLabelTransform(cart, chState)\">\n @if (chReg.template?.(); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: chState.y.value,\n axis: 'y',\n axisId: chState.y.axisId,\n coordinate: chState.y.coordinate,\n formattedValue: chState.y.formattedValue,\n snapped: chState.snapped,\n source: chState.source,\n value: chState.y.value\n }\" />\n } @else {\n {{ chState.y.formattedValue }}\n }\n </div>\n }\n }\n }\n }\n }\n\n <!-- Tooltip overlay in plot-local coordinates -->\n <ng-content select=\"mona-chart-tooltip\"></ng-content>\n\n <!-- No Data Placeholder -->\n @if (hasNoData()) {\n <div\n [class]=\"noDataClasses()\"\n data-mona-chart-export-role=\"no-data\"\n [attr.data-mona-chart-export-mode]=\"noDataTemplate() ? 'raster' : 'vector'\">\n @if (noDataTemplate(); as template) {\n <ng-container [ngTemplateOutlet]=\"template.templateRef\" />\n } @else {\n <span>No data available</span>\n }\n </div>\n }\n\n <!-- Off-screen Accessible Live Region for Keyboard/Screen-reader Exploration -->\n <div class=\"sr-only\" aria-live=\"polite\" aria-atomic=\"true\">\n {{ activeAccessibilityText() }}\n </div>\n </div>\n\n <!-- Projected Legend Outside Plot Container -->\n <ng-content select=\"mona-chart-legend\"></ng-content>\n\n <!-- Other Projected Content (Series, Axes, Templates) -->\n <ng-content></ng-content>\n</div>\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: ChartLabelMeasureDirective, selector: "[monaChartLabelMeasure]", inputs: ["monaChartLabelMeasure"] }, { kind: "directive", type: ChartOverlayLabelMeasureDirective, selector: "[monaChartOverlayLabelMeasure]", inputs: ["monaChartOverlayLabelMeasure"] }, { kind: "directive", type: ChartDataLabelMeasureDirective, selector: "[monaChartDataLabelMeasure]", inputs: ["monaChartDataLabelMeasure"] }] }); }
56981
+ ], queries: [{ propertyName: "noDataTemplate", first: true, predicate: ChartNoDataTemplateDirective, descendants: true, isSignal: true }, { propertyName: "subtitleTemplate", first: true, predicate: ChartSubtitleTemplateDirective, descendants: true, isSignal: true }, { propertyName: "titleTemplate", first: true, predicate: ChartTitleTemplateDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "canvasElement", first: true, predicate: ["canvas"], descendants: true, isSignal: true }, { propertyName: "plotSurfaceElement", first: true, predicate: ["plotSurface"], descendants: true, isSignal: true }, { propertyName: "svgElement", first: true, predicate: ["svgSurface"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (hasHeader()) {\n <div [class]=\"headerClasses()\" [style.text-align]=\"titleAlign()\">\n @if (titleTemplate(); as tpl) {\n <div data-mona-chart-export-role=\"title-template\">\n <ng-container\n [ngTemplateOutlet]=\"tpl.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: title(), title: title() }\" />\n </div>\n } @else if (title()) {\n <div [class]=\"titleClasses()\" data-mona-chart-export-role=\"title\">{{ title() }}</div>\n }\n @if (subtitleTemplate(); as subTpl) {\n <div data-mona-chart-export-role=\"subtitle-template\">\n <ng-container\n [ngTemplateOutlet]=\"subTpl.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: subtitle(), subtitle: subtitle() }\" />\n </div>\n } @else if (subtitle()) {\n <div [class]=\"subtitleClasses()\" data-mona-chart-export-role=\"subtitle\">{{ subtitle() }}</div>\n }\n </div>\n}\n<div [class]=\"layoutClasses()\">\n <div\n #plotSurface\n class=\"relative flex-1 min-h-0 min-w-0 w-full h-full overflow-hidden\"\n [style.order]=\"plotOrder()\"\n [style.touch-action]=\"touchActionStyle()\"\n [style.cursor]=\"viewportCursor() ?? 'default'\"\n (pointerdown)=\"onPointerDown($event)\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n (pointercancel)=\"onPointerCancel($event)\"\n (lostpointercapture)=\"onLostPointerCapture($event)\"\n (pointerleave)=\"onPointerLeave($event)\"\n (wheel)=\"onWheel($event)\"\n (click)=\"onCanvasClick($event)\">\n @if (renderer() === \"canvas\") {\n <canvas #canvas class=\"absolute inset-0 block h-full w-full pointer-events-none\"></canvas>\n } @else {\n <svg\n #svgSurface\n aria-hidden=\"true\"\n focusable=\"false\"\n class=\"absolute inset-0 block h-full w-full pointer-events-none\"\n xmlns=\"http://www.w3.org/2000/svg\"></svg>\n }\n\n <!-- DOM Cartesian Axis Labels & Titles -->\n @if (cartesianScene(); as cart) {\n @for (axisScene of cart.axes; track axisScene.axis + \":\" + (axisScene.axisId ?? \"\")) {\n @if (axisScene.visible) {\n @if (axisScene.labels !== false) {\n @for (\n tick of axisScene.ticks;\n track tick.tickKey ? tick.tickKey + \":\" + tick.index : tick.index\n ) {\n @if (tick.labelVisible !== false) {\n <div\n [class]=\"axisLabelClasses()\"\n [monaChartLabelMeasure]=\"tick.tickKey ?? ''\"\n data-mona-chart-export-role=\"axis-label\"\n [attr.data-mona-chart-export-mode]=\"\n resolveAxisLabelTemplate(axisScene) ? 'raster' : 'vector'\n \"\n [style.left.px]=\"axisLabelLeft(cart, axisScene, tick)\"\n [style.top.px]=\"axisLabelTop(cart, axisScene, tick)\"\n [style.max-width.px]=\"axisScene.labelMaxWidth ?? null\"\n [style.transform]=\"axisLabelTransform(axisScene, tick)\"\n [style.transform-origin]=\"axisLabelTransformOrigin(axisScene)\">\n @if (resolveAxisLabelTemplate(axisScene); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: tick.value,\n axis: axisScene.axis,\n axisId: axisScene.axisId,\n index: tick.index,\n position: axisScene.position,\n scaleType: axisScene.scaleType,\n value: tick.value\n }\" />\n } @else {\n {{ tick.formattedValue }}\n }\n </div>\n }\n }\n }\n\n <!-- Axis Title -->\n @if (axisScene.title) {\n <div\n class=\"mona-chart-axis-title absolute text-xs font-medium text-muted-foreground select-none pointer-events-none whitespace-nowrap\"\n data-mona-chart-export-role=\"axis-title\"\n data-mona-chart-export-mode=\"vector\"\n [style.left.px]=\"axisTitleLeft(cart, axisScene)\"\n [style.top.px]=\"axisTitleTop(cart, axisScene)\"\n [style.transform]=\"\n axisScene.axis === 'x'\n ? axisScene.position === 'top'\n ? 'translate(-50%, 0)'\n : 'translate(-50%, -100%)'\n : axisScene.position === 'right'\n ? 'translate(-50%, -50%) rotate(90deg)'\n : 'translate(-50%, -50%) rotate(-90deg)'\n \">\n {{ axisScene.title }}\n </div>\n }\n }\n }\n }\n\n <!-- DOM Sector Slice Labels and Donut Center Overlay -->\n @if (polarSectorScene(); as pol) {\n @for (seriesScene of pol.series; track seriesScene.id) {\n @for (slice of seriesScene.slices; track slice.sliceId) {\n @if (shouldShowSliceLabel(slice)) {\n @if (isOutsideLabel() && slice.label) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs text-foreground select-none whitespace-nowrap transition-opacity duration-[var(--mona-chart-animation-duration,300ms)] ease-[var(--mona-chart-animation-easing,cubic-bezier(0,0,0.2,1))]\"\n [class.opacity-0]=\"isAnimating() && isStructuralAnimation()\"\n [attr.data-mona-chart-export-animation-suppression]=\"\n isAnimating() && isStructuralAnimation() ? 'opacity' : null\n \"\n [monaChartLabelMeasure]=\"'sector:' + slice.sliceId\"\n data-mona-chart-export-role=\"sector-label\"\n [attr.data-mona-chart-export-mode]=\"\n polarSeriesRegistration()?.sliceLabelTemplate?.() ? 'raster' : 'vector'\n \"\n [style.left.px]=\"slice.label.position.x\"\n [style.top.px]=\"slice.label.position.y\"\n [style.transform]=\"\n slice.label.side === 'right' ? 'translate(0, -50%)' : 'translate(-100%, -50%)'\n \">\n @if (polarSeriesRegistration()?.sliceLabelTemplate?.(); as labelTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate.templateRef\"\n [ngTemplateOutletContext]=\"sliceLabelContext(slice)\" />\n } @else {\n {{ sliceLabelText(slice) }}\n }\n </div>\n } @else {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs font-semibold select-none whitespace-nowrap flex items-center justify-center transition-opacity duration-[var(--mona-chart-animation-duration,300ms)] ease-[var(--mona-chart-animation-easing,cubic-bezier(0,0,0.2,1))]\"\n [class.opacity-0]=\"isAnimating() && isStructuralAnimation()\"\n [attr.data-mona-chart-export-animation-suppression]=\"\n isAnimating() && isStructuralAnimation() ? 'opacity' : null\n \"\n data-mona-chart-export-role=\"sector-label\"\n [attr.data-mona-chart-export-mode]=\"\n polarSeriesRegistration()?.sliceLabelTemplate?.() ? 'raster' : 'vector'\n \"\n [style.left.px]=\"slice.insideLabelPoint.x\"\n [style.top.px]=\"slice.insideLabelPoint.y\"\n [style.transform]=\"'translate(-50%, -50%)'\"\n [style.color]=\"sliceContrastColor(slice)\">\n @if (polarSeriesRegistration()?.sliceLabelTemplate?.(); as labelTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate.templateRef\"\n [ngTemplateOutletContext]=\"sliceLabelContext(slice)\" />\n } @else {\n {{ sliceLabelText(slice) }}\n }\n </div>\n }\n }\n }\n }\n\n @for (seriesScene of pol.series; track seriesScene.id) {\n <!-- Donut Center Template -->\n @if (\n seriesScene.type === \"donut\" &&\n pol.hasRenderableData &&\n seriesScene.slices.length > 0 &&\n donutSeriesRegistration()?.centerTemplate?.();\n as centerTemplate\n ) {\n <div\n class=\"absolute pointer-events-none flex flex-col items-center justify-center text-center overflow-hidden\"\n data-mona-chart-export-role=\"donut-center\"\n data-mona-chart-export-mode=\"raster\"\n [style.left.px]=\"pol.center.x\"\n [style.top.px]=\"pol.center.y\"\n [style.transform]=\"'translate(-50%, -50%)'\"\n [style.max-width.px]=\"seriesScene.innerRadius * 1.6\"\n [style.max-height.px]=\"seriesScene.innerRadius * 1.6\">\n <ng-container\n [ngTemplateOutlet]=\"centerTemplate.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: seriesScene.total,\n total: seriesScene.total,\n formattedTotal: seriesScene.formattedTotal,\n visibleSliceCount: seriesScene.slices.length,\n seriesId: seriesScene.id,\n seriesName: seriesScene.name\n }\" />\n </div>\n }\n }\n }\n\n <!-- DOM Gauge Center Overlay -->\n @if (polarArcScene(); as arcScene) {\n @if (gaugeScene(); as gaugeSeries) {\n @if (gaugeSeriesRegistration()?.centerTemplate?.(); as centerTemplate) {\n <div\n class=\"absolute pointer-events-none flex flex-col items-center justify-center text-center overflow-hidden\"\n data-mona-chart-export-role=\"gauge-center\"\n data-mona-chart-export-mode=\"raster\"\n [style.left.px]=\"arcScene.center.x\"\n [style.top.px]=\"arcScene.center.y\"\n [style.transform]=\"'translate(-50%, -50%)'\"\n [style.max-width.px]=\"gaugeSeries.value.innerRadius * 1.6\"\n [style.max-height.px]=\"gaugeSeries.value.innerRadius * 1.6\">\n <ng-container\n [ngTemplateOutlet]=\"centerTemplate.templateRef\"\n [ngTemplateOutletContext]=\"gaugeCenterContext(gaugeSeries)\" />\n </div>\n } @else if (gaugeSeries.showValue) {\n <div\n class=\"absolute pointer-events-none flex flex-col items-center justify-center text-center font-bold text-foreground select-none\"\n data-mona-chart-export-role=\"gauge-value\"\n data-mona-chart-export-mode=\"vector\"\n [style.left.px]=\"arcScene.center.x\"\n [style.top.px]=\"arcScene.center.y\"\n [style.transform]=\"'translate(-50%, -50%)'\"\n [style.font-size.px]=\"gaugeFontSize(gaugeSeries)\">\n <span>{{ gaugeSeries.value.formattedValue }}</span>\n </div>\n }\n }\n }\n\n <!-- DOM Radial Axis Labels (Angular Categories/Degrees and Radial Values) -->\n @if (polarAxisScene(); as radScene) {\n <!-- Angular Spoke Labels -->\n @if (radScene.angularAxis?.visible && radScene.angularAxis?.labels) {\n @for (tick of radScene.angularAxis.ticks; track tick.index) {\n @if (tick.visible) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs text-foreground select-none whitespace-nowrap\"\n [monaChartLabelMeasure]=\"'angular:' + tick.tickKey\"\n data-mona-chart-export-role=\"polar-angular-label\"\n [attr.data-mona-chart-export-mode]=\"\n angularAxisRegistration()?.labelTemplate?.() ? 'raster' : 'vector'\n \"\n [style.left.px]=\"tick.labelPoint.x\"\n [style.top.px]=\"tick.labelPoint.y\"\n [style.transform]=\"angularLabelTransform(tick)\">\n @if (angularAxisRegistration()?.labelTemplate?.(); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: tick.value,\n axis: 'angular',\n index: tick.index,\n value: tick.value\n }\" />\n } @else {\n {{ tick.formattedValue }}\n }\n </div>\n }\n }\n }\n\n <!-- Radial Numeric Tick Labels -->\n @if (radScene.radialAxis?.visible && radScene.radialAxis?.labels) {\n @for (tick of radScene.radialAxis.ticks; track tick.index) {\n @if (tick.visible) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs text-muted-foreground select-none whitespace-nowrap\"\n [monaChartLabelMeasure]=\"'radial:' + tick.tickKey\"\n data-mona-chart-export-role=\"polar-radial-label\"\n [attr.data-mona-chart-export-mode]=\"\n radialAxisRegistration()?.labelTemplate?.() ? 'raster' : 'vector'\n \"\n [style.left.px]=\"tick.labelPoint.x\"\n [style.top.px]=\"tick.labelPoint.y\"\n [style.transform]=\"radialLabelTransform(tick, radScene.radialAxis.labelAngle)\">\n @if (radialAxisRegistration()?.labelTemplate?.(); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: tick.value,\n axis: 'radial',\n index: tick.index,\n value: tick.value\n }\" />\n } @else {\n {{ tick.formattedValue }}\n }\n </div>\n }\n }\n }\n }\n\n <!-- DOM Treemap Labels -->\n @if (treemapScene(); as tm) {\n @for (seriesScene of tm.series; track seriesScene.id) {\n @for (lbl of seriesScene.labels; track lbl.nodeId) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs select-none overflow-hidden text-ellipsis whitespace-nowrap px-1.5 py-0.5 flex flex-col justify-center transition-opacity duration-[var(--mona-chart-animation-duration,300ms)] ease-[var(--mona-chart-animation-easing,cubic-bezier(0,0,0.2,1))]\"\n [class.opacity-0]=\"isAnimating()\"\n [attr.data-mona-chart-export-animation-suppression]=\"isAnimating() ? 'opacity' : null\"\n data-mona-chart-export-role=\"treemap-label\"\n data-mona-chart-export-mode=\"raster\"\n [style.left.px]=\"lbl.bounds.x\"\n [style.top.px]=\"lbl.bounds.y\"\n [style.width.px]=\"lbl.bounds.width\"\n [style.height.px]=\"lbl.bounds.height\"\n [style.color]=\"lbl.textColor\">\n @if (treemapSeriesRegistration()?.labelTemplate?.(); as labelTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate.templateRef\"\n [ngTemplateOutletContext]=\"treemapLabelContext(lbl, seriesScene)\" />\n } @else {\n <span class=\"font-medium truncate\">{{ lbl.formattedLabel }}</span>\n @if (lbl.showValue) {\n <span class=\"text-[11px] opacity-80 truncate\">{{ lbl.formattedValue }}</span>\n }\n }\n </div>\n }\n }\n }\n\n <!-- DOM Funnel Labels -->\n @if (funnelScene(); as fn) {\n @for (seriesScene of fn.series; track seriesScene.id) {\n @for (lbl of seriesScene.labels; track lbl.stageId) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs select-none overflow-hidden text-ellipsis whitespace-nowrap flex flex-col items-center justify-center transition-opacity duration-[var(--mona-chart-animation-duration,300ms)] ease-[var(--mona-chart-animation-easing,cubic-bezier(0,0,0.2,1))]\"\n [class.opacity-0]=\"isAnimating()\"\n [attr.data-mona-chart-export-animation-suppression]=\"isAnimating() ? 'opacity' : null\"\n data-mona-chart-export-role=\"funnel-label\"\n data-mona-chart-export-mode=\"raster\"\n [style.left.px]=\"lbl.bounds.x\"\n [style.top.px]=\"lbl.bounds.y\"\n [style.width.px]=\"lbl.bounds.width\"\n [style.height.px]=\"lbl.bounds.height\"\n [style.color]=\"lbl.textColor\">\n @if (funnelSeriesRegistration()?.labelTemplate?.(); as labelTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate.templateRef\"\n [ngTemplateOutletContext]=\"funnelLabelContext(lbl, seriesScene)\" />\n } @else {\n <span class=\"font-medium truncate\">{{ lbl.text }}</span>\n }\n </div>\n }\n }\n }\n\n <!-- DOM Waterfall Labels -->\n @if (waterfallScene(); as wf) {\n @for (seriesScene of wf.series; track seriesScene.id) {\n @for (lbl of seriesScene.labels; track lbl.itemId) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs select-none overflow-hidden text-ellipsis whitespace-nowrap flex items-center justify-center transition-opacity duration-[var(--mona-chart-animation-duration,300ms)] ease-[var(--mona-chart-animation-easing,cubic-bezier(0,0,0.2,1))]\"\n [class.opacity-0]=\"isAnimating()\"\n [attr.data-mona-chart-export-animation-suppression]=\"isAnimating() ? 'opacity' : null\"\n data-mona-chart-export-role=\"waterfall-label\"\n data-mona-chart-export-mode=\"raster\"\n [style.left.px]=\"lbl.bounds.x\"\n [style.top.px]=\"lbl.bounds.y\"\n [style.width.px]=\"lbl.bounds.width\"\n [style.height.px]=\"lbl.bounds.height\"\n [style.color]=\"lbl.textColor\">\n @if (waterfallSeriesRegistration()?.labelTemplate?.(); as labelTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate.templateRef\"\n [ngTemplateOutletContext]=\"waterfallLabelContext(lbl, seriesScene)\" />\n } @else {\n <span class=\"font-medium truncate\">{{ lbl.text }}</span>\n }\n </div>\n }\n }\n }\n\n <!-- DOM Cartesian Overlays (Reference Lines, Reference Bands, Point Annotations) -->\n @if (cartesianOverlayScene(); as overlays) {\n <!-- Reference Lines -->\n @for (line of overlays.referenceLines; track line.id) {\n @if (line.label) {\n <div\n aria-hidden=\"true\"\n [class]=\"referenceLabelClasses() + (line.label.labelClass ? ' ' + line.label.labelClass : '')\"\n [class.hidden]=\"!line.label.formattedText && !resolveReferenceLineTemplate(line.id)\"\n [monaChartOverlayLabelMeasure]=\"'overlay:line:' + line.id\"\n data-mona-chart-export-role=\"reference-label\"\n [attr.data-mona-chart-export-mode]=\"resolveReferenceLineTemplate(line.id) ? 'raster' : 'vector'\"\n [style.left.px]=\"referenceLineLabelLeft(line)\"\n [style.top.px]=\"referenceLineLabelTop(line)\"\n [style.transform]=\"referenceLineLabelTransform(line)\">\n @if (resolveReferenceLineTemplate(line.id); as template) {\n @if (resolveReferenceLineRegistration(line.id); as reg) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: reg.value(),\n axis: line.axis,\n axisId: line.axisId,\n coordinate: line.coordinate,\n formattedValue: line.formattedValue,\n kind: 'line',\n value: reg.value()\n }\" />\n }\n } @else {\n {{ line.label.formattedText }}\n }\n </div>\n }\n }\n\n <!-- Reference Bands -->\n @for (band of overlays.referenceBands; track band.id) {\n @if (band.label) {\n <div\n aria-hidden=\"true\"\n [class]=\"referenceLabelClasses() + (band.label.labelClass ? ' ' + band.label.labelClass : '')\"\n [class.hidden]=\"!band.label.formattedText && !resolveReferenceBandTemplate(band.id)\"\n [monaChartOverlayLabelMeasure]=\"'overlay:band:' + band.id\"\n data-mona-chart-export-role=\"reference-label\"\n [attr.data-mona-chart-export-mode]=\"resolveReferenceBandTemplate(band.id) ? 'raster' : 'vector'\"\n [style.left.px]=\"referenceBandLabelLeft(band)\"\n [style.top.px]=\"referenceBandLabelTop(band)\"\n [style.transform]=\"referenceBandLabelTransform(band)\">\n @if (resolveReferenceBandTemplate(band.id); as template) {\n @if (resolveReferenceBandRegistration(band.id); as reg) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: { from: reg.from(), to: reg.to() },\n axis: band.axis,\n axisId: band.axisId,\n bounds: band.bounds,\n formattedFrom: band.formattedFrom,\n formattedTo: band.formattedTo,\n from: reg.from(),\n kind: 'band',\n to: reg.to()\n }\" />\n }\n } @else {\n {{ band.label.formattedText }}\n }\n </div>\n }\n }\n\n <!-- Point Annotations -->\n @for (ann of overlays.annotations; track ann.id) {\n @if (ann.label) {\n <div\n aria-hidden=\"true\"\n [class]=\"annotationLabelClasses() + (ann.label.labelClass ? ' ' + ann.label.labelClass : '')\"\n [class.hidden]=\"!ann.label.formattedText && !resolveAnnotationTemplate(ann.id)\"\n [monaChartOverlayLabelMeasure]=\"'overlay:ann:' + ann.id\"\n data-mona-chart-export-role=\"annotation-label\"\n [attr.data-mona-chart-export-mode]=\"resolveAnnotationTemplate(ann.id) ? 'raster' : 'vector'\"\n [style.left.px]=\"annotationLabelLeft(ann)\"\n [style.top.px]=\"annotationLabelTop(ann)\"\n [style.transform]=\"annotationLabelTransform(ann)\">\n @if (resolveAnnotationTemplate(ann.id); as template) {\n @if (resolveAnnotationRegistration(ann.id); as reg) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: ann.data,\n data: ann.data,\n formattedX: ann.formattedX,\n formattedY: ann.formattedY,\n point: ann.point,\n x: reg.x(),\n xAxisId: ann.xAxisId,\n y: reg.y(),\n yAxisId: ann.yAxisId\n }\" />\n }\n } @else {\n {{ ann.label.formattedText }}\n }\n </div>\n }\n }\n }\n\n <!-- DOM Cartesian Data Labels (Template Layer) -->\n @if (cartesianDataLabelScene(); as labelScene) {\n @for (label of labelScene.templateLabels; track label.seriesId + \":\" + label.markId) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none select-none whitespace-nowrap transition-opacity duration-[var(--mona-chart-animation-duration,300ms)] ease-[var(--mona-chart-animation-easing,cubic-bezier(0,0,0.2,1))]\"\n [class.opacity-0]=\"isAnimating()\"\n [attr.data-mona-chart-export-animation-suppression]=\"isAnimating() ? 'opacity' : null\"\n [monaChartDataLabelMeasure]=\"label.seriesId + ':' + label.markId\"\n data-mona-chart-export-role=\"data-label-template\"\n data-mona-chart-export-mode=\"raster\"\n [style.left.px]=\"label.bounds.x\"\n [style.top.px]=\"label.bounds.y\">\n <ng-container\n [ngTemplateOutlet]=\"label.template.templateRef\"\n [ngTemplateOutletContext]=\"label.context\" />\n </div>\n }\n }\n\n <!-- Crosshair DOM Axis Labels -->\n @if (crosshairState(); as chState) {\n @if (cartesianXYScene(); as cart) {\n @if (resolveCrosshairRegistration(); as chReg) {\n @if (chReg.enabled() !== false) {\n @if (chState.x && chReg.showAxisLabels() !== false && chReg.showXLabel() !== false) {\n <div\n aria-hidden=\"true\"\n [class]=\"crosshairLabelClasses()\"\n [monaChartOverlayLabelMeasure]=\"'crosshair:x'\"\n data-mona-chart-export-role=\"crosshair-label\"\n [attr.data-mona-chart-export-mode]=\"chReg.template?.() ? 'raster' : 'vector'\"\n [style.left.px]=\"crosshairXLabelLeft(cart, chState)\"\n [style.top.px]=\"crosshairXLabelTop(cart, chState)\"\n [style.transform]=\"crosshairXLabelTransform(cart, chState)\">\n @if (chReg.template?.(); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: chState.x.value,\n axis: 'x',\n axisId: chState.x.axisId,\n coordinate: chState.x.coordinate,\n formattedValue: chState.x.formattedValue,\n snapped: chState.snapped,\n source: chState.source,\n value: chState.x.value\n }\" />\n } @else {\n {{ chState.x.formattedValue }}\n }\n </div>\n }\n\n @if (chState.y && chReg.showAxisLabels() !== false && chReg.showYLabel() !== false) {\n <div\n aria-hidden=\"true\"\n [class]=\"crosshairLabelClasses()\"\n [monaChartOverlayLabelMeasure]=\"'crosshair:y'\"\n data-mona-chart-export-role=\"crosshair-label\"\n [attr.data-mona-chart-export-mode]=\"chReg.template?.() ? 'raster' : 'vector'\"\n [style.left.px]=\"crosshairYLabelLeft(cart, chState)\"\n [style.top.px]=\"crosshairYLabelTop(cart, chState)\"\n [style.transform]=\"crosshairYLabelTransform(cart, chState)\">\n @if (chReg.template?.(); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: chState.y.value,\n axis: 'y',\n axisId: chState.y.axisId,\n coordinate: chState.y.coordinate,\n formattedValue: chState.y.formattedValue,\n snapped: chState.snapped,\n source: chState.source,\n value: chState.y.value\n }\" />\n } @else {\n {{ chState.y.formattedValue }}\n }\n </div>\n }\n }\n }\n }\n }\n\n <!-- Tooltip overlay in plot-local coordinates -->\n <ng-content select=\"mona-chart-tooltip\"></ng-content>\n\n <!-- No Data Placeholder -->\n @if (hasNoData()) {\n <div\n [class]=\"noDataClasses()\"\n data-mona-chart-export-role=\"no-data\"\n [attr.data-mona-chart-export-mode]=\"noDataTemplate() ? 'raster' : 'vector'\">\n @if (noDataTemplate(); as template) {\n <ng-container [ngTemplateOutlet]=\"template.templateRef\" />\n } @else {\n <span>{{ messages().noData }}</span>\n }\n </div>\n }\n\n <!-- Off-screen Accessible Live Region for Keyboard/Screen-reader Exploration -->\n <div class=\"sr-only\" aria-live=\"polite\" aria-atomic=\"true\">\n {{ activeAccessibilityText() }}\n </div>\n </div>\n\n <!-- Projected Legend Outside Plot Container -->\n <ng-content select=\"mona-chart-legend\"></ng-content>\n\n <!-- Other Projected Content (Series, Axes, Templates) -->\n <ng-content></ng-content>\n</div>\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: ChartLabelMeasureDirective, selector: "[monaChartLabelMeasure]", inputs: ["monaChartLabelMeasure"] }, { kind: "directive", type: ChartOverlayLabelMeasureDirective, selector: "[monaChartOverlayLabelMeasure]", inputs: ["monaChartOverlayLabelMeasure"] }, { kind: "directive", type: ChartDataLabelMeasureDirective, selector: "[monaChartDataLabelMeasure]", inputs: ["monaChartDataLabelMeasure"] }] }); }
56947
56982
  }
56948
56983
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ChartComponent, decorators: [{
56949
56984
  type: Component,
@@ -56967,7 +57002,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
56967
57002
  "[style.--mona-chart-animation-easing]": "animationEasingCss()",
56968
57003
  "(keydown)": "onKeyDown($event)",
56969
57004
  "(focusout)": "onFocusOut($event)"
56970
- }, template: "@if (hasHeader()) {\n <div [class]=\"headerClasses()\" [style.text-align]=\"titleAlign()\">\n @if (titleTemplate(); as tpl) {\n <div data-mona-chart-export-role=\"title-template\">\n <ng-container\n [ngTemplateOutlet]=\"tpl.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: title(), title: title() }\" />\n </div>\n } @else if (title()) {\n <div [class]=\"titleClasses()\" data-mona-chart-export-role=\"title\">{{ title() }}</div>\n }\n @if (subtitleTemplate(); as subTpl) {\n <div data-mona-chart-export-role=\"subtitle-template\">\n <ng-container\n [ngTemplateOutlet]=\"subTpl.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: subtitle(), subtitle: subtitle() }\" />\n </div>\n } @else if (subtitle()) {\n <div [class]=\"subtitleClasses()\" data-mona-chart-export-role=\"subtitle\">{{ subtitle() }}</div>\n }\n </div>\n}\n<div [class]=\"layoutClasses()\">\n <div\n #plotSurface\n class=\"relative flex-1 min-h-0 min-w-0 w-full h-full overflow-hidden\"\n [style.order]=\"plotOrder()\"\n [style.touch-action]=\"touchActionStyle()\"\n [style.cursor]=\"viewportCursor() ?? 'default'\"\n (pointerdown)=\"onPointerDown($event)\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n (pointercancel)=\"onPointerCancel($event)\"\n (lostpointercapture)=\"onLostPointerCapture($event)\"\n (pointerleave)=\"onPointerLeave($event)\"\n (wheel)=\"onWheel($event)\"\n (click)=\"onCanvasClick($event)\">\n @if (renderer() === \"canvas\") {\n <canvas #canvas class=\"absolute inset-0 block h-full w-full pointer-events-none\"></canvas>\n } @else {\n <svg\n #svgSurface\n aria-hidden=\"true\"\n focusable=\"false\"\n class=\"absolute inset-0 block h-full w-full pointer-events-none\"\n xmlns=\"http://www.w3.org/2000/svg\"></svg>\n }\n\n <!-- DOM Cartesian Axis Labels & Titles -->\n @if (cartesianScene(); as cart) {\n @for (axisScene of cart.axes; track axisScene.axis + \":\" + (axisScene.axisId ?? \"\")) {\n @if (axisScene.visible) {\n @if (axisScene.labels !== false) {\n @for (\n tick of axisScene.ticks;\n track tick.tickKey ? tick.tickKey + \":\" + tick.index : tick.index\n ) {\n @if (tick.labelVisible !== false) {\n <div\n [class]=\"axisLabelClasses()\"\n [monaChartLabelMeasure]=\"tick.tickKey ?? ''\"\n data-mona-chart-export-role=\"axis-label\"\n [attr.data-mona-chart-export-mode]=\"\n resolveAxisLabelTemplate(axisScene) ? 'raster' : 'vector'\n \"\n [style.left.px]=\"axisLabelLeft(cart, axisScene, tick)\"\n [style.top.px]=\"axisLabelTop(cart, axisScene, tick)\"\n [style.max-width.px]=\"axisScene.labelMaxWidth ?? null\"\n [style.transform]=\"axisLabelTransform(axisScene, tick)\"\n [style.transform-origin]=\"axisLabelTransformOrigin(axisScene)\">\n @if (resolveAxisLabelTemplate(axisScene); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: tick.value,\n axis: axisScene.axis,\n axisId: axisScene.axisId,\n index: tick.index,\n position: axisScene.position,\n scaleType: axisScene.scaleType,\n value: tick.value\n }\" />\n } @else {\n {{ tick.formattedValue }}\n }\n </div>\n }\n }\n }\n\n <!-- Axis Title -->\n @if (axisScene.title) {\n <div\n class=\"mona-chart-axis-title absolute text-xs font-medium text-muted-foreground select-none pointer-events-none whitespace-nowrap\"\n data-mona-chart-export-role=\"axis-title\"\n data-mona-chart-export-mode=\"vector\"\n [style.left.px]=\"axisTitleLeft(cart, axisScene)\"\n [style.top.px]=\"axisTitleTop(cart, axisScene)\"\n [style.transform]=\"\n axisScene.axis === 'x'\n ? axisScene.position === 'top'\n ? 'translate(-50%, 0)'\n : 'translate(-50%, -100%)'\n : axisScene.position === 'right'\n ? 'translate(-50%, -50%) rotate(90deg)'\n : 'translate(-50%, -50%) rotate(-90deg)'\n \">\n {{ axisScene.title }}\n </div>\n }\n }\n }\n }\n\n <!-- DOM Sector Slice Labels and Donut Center Overlay -->\n @if (polarSectorScene(); as pol) {\n @for (seriesScene of pol.series; track seriesScene.id) {\n @for (slice of seriesScene.slices; track slice.sliceId) {\n @if (shouldShowSliceLabel(slice)) {\n @if (isOutsideLabel() && slice.label) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs text-foreground select-none whitespace-nowrap transition-opacity duration-[var(--mona-chart-animation-duration,300ms)] ease-[var(--mona-chart-animation-easing,cubic-bezier(0,0,0.2,1))]\"\n [class.opacity-0]=\"isAnimating() && isStructuralAnimation()\"\n [attr.data-mona-chart-export-animation-suppression]=\"\n isAnimating() && isStructuralAnimation() ? 'opacity' : null\n \"\n [monaChartLabelMeasure]=\"'sector:' + slice.sliceId\"\n data-mona-chart-export-role=\"sector-label\"\n [attr.data-mona-chart-export-mode]=\"\n polarSeriesRegistration()?.sliceLabelTemplate?.() ? 'raster' : 'vector'\n \"\n [style.left.px]=\"slice.label.position.x\"\n [style.top.px]=\"slice.label.position.y\"\n [style.transform]=\"\n slice.label.side === 'right' ? 'translate(0, -50%)' : 'translate(-100%, -50%)'\n \">\n @if (polarSeriesRegistration()?.sliceLabelTemplate?.(); as labelTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate.templateRef\"\n [ngTemplateOutletContext]=\"sliceLabelContext(slice)\" />\n } @else {\n {{ sliceLabelText(slice) }}\n }\n </div>\n } @else {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs font-semibold select-none whitespace-nowrap flex items-center justify-center transition-opacity duration-[var(--mona-chart-animation-duration,300ms)] ease-[var(--mona-chart-animation-easing,cubic-bezier(0,0,0.2,1))]\"\n [class.opacity-0]=\"isAnimating() && isStructuralAnimation()\"\n [attr.data-mona-chart-export-animation-suppression]=\"\n isAnimating() && isStructuralAnimation() ? 'opacity' : null\n \"\n data-mona-chart-export-role=\"sector-label\"\n [attr.data-mona-chart-export-mode]=\"\n polarSeriesRegistration()?.sliceLabelTemplate?.() ? 'raster' : 'vector'\n \"\n [style.left.px]=\"slice.insideLabelPoint.x\"\n [style.top.px]=\"slice.insideLabelPoint.y\"\n [style.transform]=\"'translate(-50%, -50%)'\"\n [style.color]=\"sliceContrastColor(slice)\">\n @if (polarSeriesRegistration()?.sliceLabelTemplate?.(); as labelTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate.templateRef\"\n [ngTemplateOutletContext]=\"sliceLabelContext(slice)\" />\n } @else {\n {{ sliceLabelText(slice) }}\n }\n </div>\n }\n }\n }\n }\n\n @for (seriesScene of pol.series; track seriesScene.id) {\n <!-- Donut Center Template -->\n @if (\n seriesScene.type === \"donut\" &&\n pol.hasRenderableData &&\n seriesScene.slices.length > 0 &&\n donutSeriesRegistration()?.centerTemplate?.();\n as centerTemplate\n ) {\n <div\n class=\"absolute pointer-events-none flex flex-col items-center justify-center text-center overflow-hidden\"\n data-mona-chart-export-role=\"donut-center\"\n data-mona-chart-export-mode=\"raster\"\n [style.left.px]=\"pol.center.x\"\n [style.top.px]=\"pol.center.y\"\n [style.transform]=\"'translate(-50%, -50%)'\"\n [style.max-width.px]=\"seriesScene.innerRadius * 1.6\"\n [style.max-height.px]=\"seriesScene.innerRadius * 1.6\">\n <ng-container\n [ngTemplateOutlet]=\"centerTemplate.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: seriesScene.total,\n total: seriesScene.total,\n formattedTotal: seriesScene.formattedTotal,\n visibleSliceCount: seriesScene.slices.length,\n seriesId: seriesScene.id,\n seriesName: seriesScene.name\n }\" />\n </div>\n }\n }\n }\n\n <!-- DOM Gauge Center Overlay -->\n @if (polarArcScene(); as arcScene) {\n @if (gaugeScene(); as gaugeSeries) {\n @if (gaugeSeriesRegistration()?.centerTemplate?.(); as centerTemplate) {\n <div\n class=\"absolute pointer-events-none flex flex-col items-center justify-center text-center overflow-hidden\"\n data-mona-chart-export-role=\"gauge-center\"\n data-mona-chart-export-mode=\"raster\"\n [style.left.px]=\"arcScene.center.x\"\n [style.top.px]=\"arcScene.center.y\"\n [style.transform]=\"'translate(-50%, -50%)'\"\n [style.max-width.px]=\"gaugeSeries.value.innerRadius * 1.6\"\n [style.max-height.px]=\"gaugeSeries.value.innerRadius * 1.6\">\n <ng-container\n [ngTemplateOutlet]=\"centerTemplate.templateRef\"\n [ngTemplateOutletContext]=\"gaugeCenterContext(gaugeSeries)\" />\n </div>\n } @else if (gaugeSeries.showValue) {\n <div\n class=\"absolute pointer-events-none flex flex-col items-center justify-center text-center font-bold text-foreground select-none\"\n data-mona-chart-export-role=\"gauge-value\"\n data-mona-chart-export-mode=\"vector\"\n [style.left.px]=\"arcScene.center.x\"\n [style.top.px]=\"arcScene.center.y\"\n [style.transform]=\"'translate(-50%, -50%)'\"\n [style.font-size.px]=\"gaugeFontSize(gaugeSeries)\">\n <span>{{ gaugeSeries.value.formattedValue }}</span>\n </div>\n }\n }\n }\n\n <!-- DOM Radial Axis Labels (Angular Categories/Degrees and Radial Values) -->\n @if (polarAxisScene(); as radScene) {\n <!-- Angular Spoke Labels -->\n @if (radScene.angularAxis?.visible && radScene.angularAxis?.labels) {\n @for (tick of radScene.angularAxis.ticks; track tick.index) {\n @if (tick.visible) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs text-foreground select-none whitespace-nowrap\"\n [monaChartLabelMeasure]=\"'angular:' + tick.tickKey\"\n data-mona-chart-export-role=\"polar-angular-label\"\n [attr.data-mona-chart-export-mode]=\"\n angularAxisRegistration()?.labelTemplate?.() ? 'raster' : 'vector'\n \"\n [style.left.px]=\"tick.labelPoint.x\"\n [style.top.px]=\"tick.labelPoint.y\"\n [style.transform]=\"angularLabelTransform(tick)\">\n @if (angularAxisRegistration()?.labelTemplate?.(); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: tick.value,\n axis: 'angular',\n index: tick.index,\n value: tick.value\n }\" />\n } @else {\n {{ tick.formattedValue }}\n }\n </div>\n }\n }\n }\n\n <!-- Radial Numeric Tick Labels -->\n @if (radScene.radialAxis?.visible && radScene.radialAxis?.labels) {\n @for (tick of radScene.radialAxis.ticks; track tick.index) {\n @if (tick.visible) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs text-muted-foreground select-none whitespace-nowrap\"\n [monaChartLabelMeasure]=\"'radial:' + tick.tickKey\"\n data-mona-chart-export-role=\"polar-radial-label\"\n [attr.data-mona-chart-export-mode]=\"\n radialAxisRegistration()?.labelTemplate?.() ? 'raster' : 'vector'\n \"\n [style.left.px]=\"tick.labelPoint.x\"\n [style.top.px]=\"tick.labelPoint.y\"\n [style.transform]=\"radialLabelTransform(tick, radScene.radialAxis.labelAngle)\">\n @if (radialAxisRegistration()?.labelTemplate?.(); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: tick.value,\n axis: 'radial',\n index: tick.index,\n value: tick.value\n }\" />\n } @else {\n {{ tick.formattedValue }}\n }\n </div>\n }\n }\n }\n }\n\n <!-- DOM Treemap Labels -->\n @if (treemapScene(); as tm) {\n @for (seriesScene of tm.series; track seriesScene.id) {\n @for (lbl of seriesScene.labels; track lbl.nodeId) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs select-none overflow-hidden text-ellipsis whitespace-nowrap px-1.5 py-0.5 flex flex-col justify-center transition-opacity duration-[var(--mona-chart-animation-duration,300ms)] ease-[var(--mona-chart-animation-easing,cubic-bezier(0,0,0.2,1))]\"\n [class.opacity-0]=\"isAnimating()\"\n [attr.data-mona-chart-export-animation-suppression]=\"isAnimating() ? 'opacity' : null\"\n data-mona-chart-export-role=\"treemap-label\"\n data-mona-chart-export-mode=\"raster\"\n [style.left.px]=\"lbl.bounds.x\"\n [style.top.px]=\"lbl.bounds.y\"\n [style.width.px]=\"lbl.bounds.width\"\n [style.height.px]=\"lbl.bounds.height\"\n [style.color]=\"lbl.textColor\">\n @if (treemapSeriesRegistration()?.labelTemplate?.(); as labelTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate.templateRef\"\n [ngTemplateOutletContext]=\"treemapLabelContext(lbl, seriesScene)\" />\n } @else {\n <span class=\"font-medium truncate\">{{ lbl.formattedLabel }}</span>\n @if (lbl.showValue) {\n <span class=\"text-[11px] opacity-80 truncate\">{{ lbl.formattedValue }}</span>\n }\n }\n </div>\n }\n }\n }\n\n <!-- DOM Funnel Labels -->\n @if (funnelScene(); as fn) {\n @for (seriesScene of fn.series; track seriesScene.id) {\n @for (lbl of seriesScene.labels; track lbl.stageId) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs select-none overflow-hidden text-ellipsis whitespace-nowrap flex flex-col items-center justify-center transition-opacity duration-[var(--mona-chart-animation-duration,300ms)] ease-[var(--mona-chart-animation-easing,cubic-bezier(0,0,0.2,1))]\"\n [class.opacity-0]=\"isAnimating()\"\n [attr.data-mona-chart-export-animation-suppression]=\"isAnimating() ? 'opacity' : null\"\n data-mona-chart-export-role=\"funnel-label\"\n data-mona-chart-export-mode=\"raster\"\n [style.left.px]=\"lbl.bounds.x\"\n [style.top.px]=\"lbl.bounds.y\"\n [style.width.px]=\"lbl.bounds.width\"\n [style.height.px]=\"lbl.bounds.height\"\n [style.color]=\"lbl.textColor\">\n @if (funnelSeriesRegistration()?.labelTemplate?.(); as labelTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate.templateRef\"\n [ngTemplateOutletContext]=\"funnelLabelContext(lbl, seriesScene)\" />\n } @else {\n <span class=\"font-medium truncate\">{{ lbl.text }}</span>\n }\n </div>\n }\n }\n }\n\n <!-- DOM Waterfall Labels -->\n @if (waterfallScene(); as wf) {\n @for (seriesScene of wf.series; track seriesScene.id) {\n @for (lbl of seriesScene.labels; track lbl.itemId) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs select-none overflow-hidden text-ellipsis whitespace-nowrap flex items-center justify-center transition-opacity duration-[var(--mona-chart-animation-duration,300ms)] ease-[var(--mona-chart-animation-easing,cubic-bezier(0,0,0.2,1))]\"\n [class.opacity-0]=\"isAnimating()\"\n [attr.data-mona-chart-export-animation-suppression]=\"isAnimating() ? 'opacity' : null\"\n data-mona-chart-export-role=\"waterfall-label\"\n data-mona-chart-export-mode=\"raster\"\n [style.left.px]=\"lbl.bounds.x\"\n [style.top.px]=\"lbl.bounds.y\"\n [style.width.px]=\"lbl.bounds.width\"\n [style.height.px]=\"lbl.bounds.height\"\n [style.color]=\"lbl.textColor\">\n @if (waterfallSeriesRegistration()?.labelTemplate?.(); as labelTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate.templateRef\"\n [ngTemplateOutletContext]=\"waterfallLabelContext(lbl, seriesScene)\" />\n } @else {\n <span class=\"font-medium truncate\">{{ lbl.text }}</span>\n }\n </div>\n }\n }\n }\n\n <!-- DOM Cartesian Overlays (Reference Lines, Reference Bands, Point Annotations) -->\n @if (cartesianOverlayScene(); as overlays) {\n <!-- Reference Lines -->\n @for (line of overlays.referenceLines; track line.id) {\n @if (line.label) {\n <div\n aria-hidden=\"true\"\n [class]=\"referenceLabelClasses() + (line.label.labelClass ? ' ' + line.label.labelClass : '')\"\n [class.hidden]=\"!line.label.formattedText && !resolveReferenceLineTemplate(line.id)\"\n [monaChartOverlayLabelMeasure]=\"'overlay:line:' + line.id\"\n data-mona-chart-export-role=\"reference-label\"\n [attr.data-mona-chart-export-mode]=\"resolveReferenceLineTemplate(line.id) ? 'raster' : 'vector'\"\n [style.left.px]=\"referenceLineLabelLeft(line)\"\n [style.top.px]=\"referenceLineLabelTop(line)\"\n [style.transform]=\"referenceLineLabelTransform(line)\">\n @if (resolveReferenceLineTemplate(line.id); as template) {\n @if (resolveReferenceLineRegistration(line.id); as reg) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: reg.value(),\n axis: line.axis,\n axisId: line.axisId,\n coordinate: line.coordinate,\n formattedValue: line.formattedValue,\n kind: 'line',\n value: reg.value()\n }\" />\n }\n } @else {\n {{ line.label.formattedText }}\n }\n </div>\n }\n }\n\n <!-- Reference Bands -->\n @for (band of overlays.referenceBands; track band.id) {\n @if (band.label) {\n <div\n aria-hidden=\"true\"\n [class]=\"referenceLabelClasses() + (band.label.labelClass ? ' ' + band.label.labelClass : '')\"\n [class.hidden]=\"!band.label.formattedText && !resolveReferenceBandTemplate(band.id)\"\n [monaChartOverlayLabelMeasure]=\"'overlay:band:' + band.id\"\n data-mona-chart-export-role=\"reference-label\"\n [attr.data-mona-chart-export-mode]=\"resolveReferenceBandTemplate(band.id) ? 'raster' : 'vector'\"\n [style.left.px]=\"referenceBandLabelLeft(band)\"\n [style.top.px]=\"referenceBandLabelTop(band)\"\n [style.transform]=\"referenceBandLabelTransform(band)\">\n @if (resolveReferenceBandTemplate(band.id); as template) {\n @if (resolveReferenceBandRegistration(band.id); as reg) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: { from: reg.from(), to: reg.to() },\n axis: band.axis,\n axisId: band.axisId,\n bounds: band.bounds,\n formattedFrom: band.formattedFrom,\n formattedTo: band.formattedTo,\n from: reg.from(),\n kind: 'band',\n to: reg.to()\n }\" />\n }\n } @else {\n {{ band.label.formattedText }}\n }\n </div>\n }\n }\n\n <!-- Point Annotations -->\n @for (ann of overlays.annotations; track ann.id) {\n @if (ann.label) {\n <div\n aria-hidden=\"true\"\n [class]=\"annotationLabelClasses() + (ann.label.labelClass ? ' ' + ann.label.labelClass : '')\"\n [class.hidden]=\"!ann.label.formattedText && !resolveAnnotationTemplate(ann.id)\"\n [monaChartOverlayLabelMeasure]=\"'overlay:ann:' + ann.id\"\n data-mona-chart-export-role=\"annotation-label\"\n [attr.data-mona-chart-export-mode]=\"resolveAnnotationTemplate(ann.id) ? 'raster' : 'vector'\"\n [style.left.px]=\"annotationLabelLeft(ann)\"\n [style.top.px]=\"annotationLabelTop(ann)\"\n [style.transform]=\"annotationLabelTransform(ann)\">\n @if (resolveAnnotationTemplate(ann.id); as template) {\n @if (resolveAnnotationRegistration(ann.id); as reg) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: ann.data,\n data: ann.data,\n formattedX: ann.formattedX,\n formattedY: ann.formattedY,\n point: ann.point,\n x: reg.x(),\n xAxisId: ann.xAxisId,\n y: reg.y(),\n yAxisId: ann.yAxisId\n }\" />\n }\n } @else {\n {{ ann.label.formattedText }}\n }\n </div>\n }\n }\n }\n\n <!-- DOM Cartesian Data Labels (Template Layer) -->\n @if (cartesianDataLabelScene(); as labelScene) {\n @for (label of labelScene.templateLabels; track label.seriesId + \":\" + label.markId) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none select-none whitespace-nowrap transition-opacity duration-[var(--mona-chart-animation-duration,300ms)] ease-[var(--mona-chart-animation-easing,cubic-bezier(0,0,0.2,1))]\"\n [class.opacity-0]=\"isAnimating()\"\n [attr.data-mona-chart-export-animation-suppression]=\"isAnimating() ? 'opacity' : null\"\n [monaChartDataLabelMeasure]=\"label.seriesId + ':' + label.markId\"\n data-mona-chart-export-role=\"data-label-template\"\n data-mona-chart-export-mode=\"raster\"\n [style.left.px]=\"label.bounds.x\"\n [style.top.px]=\"label.bounds.y\">\n <ng-container\n [ngTemplateOutlet]=\"label.template.templateRef\"\n [ngTemplateOutletContext]=\"label.context\" />\n </div>\n }\n }\n\n <!-- Crosshair DOM Axis Labels -->\n @if (crosshairState(); as chState) {\n @if (cartesianXYScene(); as cart) {\n @if (resolveCrosshairRegistration(); as chReg) {\n @if (chReg.enabled() !== false) {\n @if (chState.x && chReg.showAxisLabels() !== false && chReg.showXLabel() !== false) {\n <div\n aria-hidden=\"true\"\n [class]=\"crosshairLabelClasses()\"\n [monaChartOverlayLabelMeasure]=\"'crosshair:x'\"\n data-mona-chart-export-role=\"crosshair-label\"\n [attr.data-mona-chart-export-mode]=\"chReg.template?.() ? 'raster' : 'vector'\"\n [style.left.px]=\"crosshairXLabelLeft(cart, chState)\"\n [style.top.px]=\"crosshairXLabelTop(cart, chState)\"\n [style.transform]=\"crosshairXLabelTransform(cart, chState)\">\n @if (chReg.template?.(); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: chState.x.value,\n axis: 'x',\n axisId: chState.x.axisId,\n coordinate: chState.x.coordinate,\n formattedValue: chState.x.formattedValue,\n snapped: chState.snapped,\n source: chState.source,\n value: chState.x.value\n }\" />\n } @else {\n {{ chState.x.formattedValue }}\n }\n </div>\n }\n\n @if (chState.y && chReg.showAxisLabels() !== false && chReg.showYLabel() !== false) {\n <div\n aria-hidden=\"true\"\n [class]=\"crosshairLabelClasses()\"\n [monaChartOverlayLabelMeasure]=\"'crosshair:y'\"\n data-mona-chart-export-role=\"crosshair-label\"\n [attr.data-mona-chart-export-mode]=\"chReg.template?.() ? 'raster' : 'vector'\"\n [style.left.px]=\"crosshairYLabelLeft(cart, chState)\"\n [style.top.px]=\"crosshairYLabelTop(cart, chState)\"\n [style.transform]=\"crosshairYLabelTransform(cart, chState)\">\n @if (chReg.template?.(); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: chState.y.value,\n axis: 'y',\n axisId: chState.y.axisId,\n coordinate: chState.y.coordinate,\n formattedValue: chState.y.formattedValue,\n snapped: chState.snapped,\n source: chState.source,\n value: chState.y.value\n }\" />\n } @else {\n {{ chState.y.formattedValue }}\n }\n </div>\n }\n }\n }\n }\n }\n\n <!-- Tooltip overlay in plot-local coordinates -->\n <ng-content select=\"mona-chart-tooltip\"></ng-content>\n\n <!-- No Data Placeholder -->\n @if (hasNoData()) {\n <div\n [class]=\"noDataClasses()\"\n data-mona-chart-export-role=\"no-data\"\n [attr.data-mona-chart-export-mode]=\"noDataTemplate() ? 'raster' : 'vector'\">\n @if (noDataTemplate(); as template) {\n <ng-container [ngTemplateOutlet]=\"template.templateRef\" />\n } @else {\n <span>No data available</span>\n }\n </div>\n }\n\n <!-- Off-screen Accessible Live Region for Keyboard/Screen-reader Exploration -->\n <div class=\"sr-only\" aria-live=\"polite\" aria-atomic=\"true\">\n {{ activeAccessibilityText() }}\n </div>\n </div>\n\n <!-- Projected Legend Outside Plot Container -->\n <ng-content select=\"mona-chart-legend\"></ng-content>\n\n <!-- Other Projected Content (Series, Axes, Templates) -->\n <ng-content></ng-content>\n</div>\n" }]
57005
+ }, template: "@if (hasHeader()) {\n <div [class]=\"headerClasses()\" [style.text-align]=\"titleAlign()\">\n @if (titleTemplate(); as tpl) {\n <div data-mona-chart-export-role=\"title-template\">\n <ng-container\n [ngTemplateOutlet]=\"tpl.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: title(), title: title() }\" />\n </div>\n } @else if (title()) {\n <div [class]=\"titleClasses()\" data-mona-chart-export-role=\"title\">{{ title() }}</div>\n }\n @if (subtitleTemplate(); as subTpl) {\n <div data-mona-chart-export-role=\"subtitle-template\">\n <ng-container\n [ngTemplateOutlet]=\"subTpl.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: subtitle(), subtitle: subtitle() }\" />\n </div>\n } @else if (subtitle()) {\n <div [class]=\"subtitleClasses()\" data-mona-chart-export-role=\"subtitle\">{{ subtitle() }}</div>\n }\n </div>\n}\n<div [class]=\"layoutClasses()\">\n <div\n #plotSurface\n class=\"relative flex-1 min-h-0 min-w-0 w-full h-full overflow-hidden\"\n [style.order]=\"plotOrder()\"\n [style.touch-action]=\"touchActionStyle()\"\n [style.cursor]=\"viewportCursor() ?? 'default'\"\n (pointerdown)=\"onPointerDown($event)\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n (pointercancel)=\"onPointerCancel($event)\"\n (lostpointercapture)=\"onLostPointerCapture($event)\"\n (pointerleave)=\"onPointerLeave($event)\"\n (wheel)=\"onWheel($event)\"\n (click)=\"onCanvasClick($event)\">\n @if (renderer() === \"canvas\") {\n <canvas #canvas class=\"absolute inset-0 block h-full w-full pointer-events-none\"></canvas>\n } @else {\n <svg\n #svgSurface\n aria-hidden=\"true\"\n focusable=\"false\"\n class=\"absolute inset-0 block h-full w-full pointer-events-none\"\n xmlns=\"http://www.w3.org/2000/svg\"></svg>\n }\n\n <!-- DOM Cartesian Axis Labels & Titles -->\n @if (cartesianScene(); as cart) {\n @for (axisScene of cart.axes; track axisScene.axis + \":\" + (axisScene.axisId ?? \"\")) {\n @if (axisScene.visible) {\n @if (axisScene.labels !== false) {\n @for (\n tick of axisScene.ticks;\n track tick.tickKey ? tick.tickKey + \":\" + tick.index : tick.index\n ) {\n @if (tick.labelVisible !== false) {\n <div\n [class]=\"axisLabelClasses()\"\n [monaChartLabelMeasure]=\"tick.tickKey ?? ''\"\n data-mona-chart-export-role=\"axis-label\"\n [attr.data-mona-chart-export-mode]=\"\n resolveAxisLabelTemplate(axisScene) ? 'raster' : 'vector'\n \"\n [style.left.px]=\"axisLabelLeft(cart, axisScene, tick)\"\n [style.top.px]=\"axisLabelTop(cart, axisScene, tick)\"\n [style.max-width.px]=\"axisScene.labelMaxWidth ?? null\"\n [style.transform]=\"axisLabelTransform(axisScene, tick)\"\n [style.transform-origin]=\"axisLabelTransformOrigin(axisScene)\">\n @if (resolveAxisLabelTemplate(axisScene); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: tick.value,\n axis: axisScene.axis,\n axisId: axisScene.axisId,\n index: tick.index,\n position: axisScene.position,\n scaleType: axisScene.scaleType,\n value: tick.value\n }\" />\n } @else {\n {{ tick.formattedValue }}\n }\n </div>\n }\n }\n }\n\n <!-- Axis Title -->\n @if (axisScene.title) {\n <div\n class=\"mona-chart-axis-title absolute text-xs font-medium text-muted-foreground select-none pointer-events-none whitespace-nowrap\"\n data-mona-chart-export-role=\"axis-title\"\n data-mona-chart-export-mode=\"vector\"\n [style.left.px]=\"axisTitleLeft(cart, axisScene)\"\n [style.top.px]=\"axisTitleTop(cart, axisScene)\"\n [style.transform]=\"\n axisScene.axis === 'x'\n ? axisScene.position === 'top'\n ? 'translate(-50%, 0)'\n : 'translate(-50%, -100%)'\n : axisScene.position === 'right'\n ? 'translate(-50%, -50%) rotate(90deg)'\n : 'translate(-50%, -50%) rotate(-90deg)'\n \">\n {{ axisScene.title }}\n </div>\n }\n }\n }\n }\n\n <!-- DOM Sector Slice Labels and Donut Center Overlay -->\n @if (polarSectorScene(); as pol) {\n @for (seriesScene of pol.series; track seriesScene.id) {\n @for (slice of seriesScene.slices; track slice.sliceId) {\n @if (shouldShowSliceLabel(slice)) {\n @if (isOutsideLabel() && slice.label) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs text-foreground select-none whitespace-nowrap transition-opacity duration-[var(--mona-chart-animation-duration,300ms)] ease-[var(--mona-chart-animation-easing,cubic-bezier(0,0,0.2,1))]\"\n [class.opacity-0]=\"isAnimating() && isStructuralAnimation()\"\n [attr.data-mona-chart-export-animation-suppression]=\"\n isAnimating() && isStructuralAnimation() ? 'opacity' : null\n \"\n [monaChartLabelMeasure]=\"'sector:' + slice.sliceId\"\n data-mona-chart-export-role=\"sector-label\"\n [attr.data-mona-chart-export-mode]=\"\n polarSeriesRegistration()?.sliceLabelTemplate?.() ? 'raster' : 'vector'\n \"\n [style.left.px]=\"slice.label.position.x\"\n [style.top.px]=\"slice.label.position.y\"\n [style.transform]=\"\n slice.label.side === 'right' ? 'translate(0, -50%)' : 'translate(-100%, -50%)'\n \">\n @if (polarSeriesRegistration()?.sliceLabelTemplate?.(); as labelTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate.templateRef\"\n [ngTemplateOutletContext]=\"sliceLabelContext(slice)\" />\n } @else {\n {{ sliceLabelText(slice) }}\n }\n </div>\n } @else {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs font-semibold select-none whitespace-nowrap flex items-center justify-center transition-opacity duration-[var(--mona-chart-animation-duration,300ms)] ease-[var(--mona-chart-animation-easing,cubic-bezier(0,0,0.2,1))]\"\n [class.opacity-0]=\"isAnimating() && isStructuralAnimation()\"\n [attr.data-mona-chart-export-animation-suppression]=\"\n isAnimating() && isStructuralAnimation() ? 'opacity' : null\n \"\n data-mona-chart-export-role=\"sector-label\"\n [attr.data-mona-chart-export-mode]=\"\n polarSeriesRegistration()?.sliceLabelTemplate?.() ? 'raster' : 'vector'\n \"\n [style.left.px]=\"slice.insideLabelPoint.x\"\n [style.top.px]=\"slice.insideLabelPoint.y\"\n [style.transform]=\"'translate(-50%, -50%)'\"\n [style.color]=\"sliceContrastColor(slice)\">\n @if (polarSeriesRegistration()?.sliceLabelTemplate?.(); as labelTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate.templateRef\"\n [ngTemplateOutletContext]=\"sliceLabelContext(slice)\" />\n } @else {\n {{ sliceLabelText(slice) }}\n }\n </div>\n }\n }\n }\n }\n\n @for (seriesScene of pol.series; track seriesScene.id) {\n <!-- Donut Center Template -->\n @if (\n seriesScene.type === \"donut\" &&\n pol.hasRenderableData &&\n seriesScene.slices.length > 0 &&\n donutSeriesRegistration()?.centerTemplate?.();\n as centerTemplate\n ) {\n <div\n class=\"absolute pointer-events-none flex flex-col items-center justify-center text-center overflow-hidden\"\n data-mona-chart-export-role=\"donut-center\"\n data-mona-chart-export-mode=\"raster\"\n [style.left.px]=\"pol.center.x\"\n [style.top.px]=\"pol.center.y\"\n [style.transform]=\"'translate(-50%, -50%)'\"\n [style.max-width.px]=\"seriesScene.innerRadius * 1.6\"\n [style.max-height.px]=\"seriesScene.innerRadius * 1.6\">\n <ng-container\n [ngTemplateOutlet]=\"centerTemplate.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: seriesScene.total,\n total: seriesScene.total,\n formattedTotal: seriesScene.formattedTotal,\n visibleSliceCount: seriesScene.slices.length,\n seriesId: seriesScene.id,\n seriesName: seriesScene.name\n }\" />\n </div>\n }\n }\n }\n\n <!-- DOM Gauge Center Overlay -->\n @if (polarArcScene(); as arcScene) {\n @if (gaugeScene(); as gaugeSeries) {\n @if (gaugeSeriesRegistration()?.centerTemplate?.(); as centerTemplate) {\n <div\n class=\"absolute pointer-events-none flex flex-col items-center justify-center text-center overflow-hidden\"\n data-mona-chart-export-role=\"gauge-center\"\n data-mona-chart-export-mode=\"raster\"\n [style.left.px]=\"arcScene.center.x\"\n [style.top.px]=\"arcScene.center.y\"\n [style.transform]=\"'translate(-50%, -50%)'\"\n [style.max-width.px]=\"gaugeSeries.value.innerRadius * 1.6\"\n [style.max-height.px]=\"gaugeSeries.value.innerRadius * 1.6\">\n <ng-container\n [ngTemplateOutlet]=\"centerTemplate.templateRef\"\n [ngTemplateOutletContext]=\"gaugeCenterContext(gaugeSeries)\" />\n </div>\n } @else if (gaugeSeries.showValue) {\n <div\n class=\"absolute pointer-events-none flex flex-col items-center justify-center text-center font-bold text-foreground select-none\"\n data-mona-chart-export-role=\"gauge-value\"\n data-mona-chart-export-mode=\"vector\"\n [style.left.px]=\"arcScene.center.x\"\n [style.top.px]=\"arcScene.center.y\"\n [style.transform]=\"'translate(-50%, -50%)'\"\n [style.font-size.px]=\"gaugeFontSize(gaugeSeries)\">\n <span>{{ gaugeSeries.value.formattedValue }}</span>\n </div>\n }\n }\n }\n\n <!-- DOM Radial Axis Labels (Angular Categories/Degrees and Radial Values) -->\n @if (polarAxisScene(); as radScene) {\n <!-- Angular Spoke Labels -->\n @if (radScene.angularAxis?.visible && radScene.angularAxis?.labels) {\n @for (tick of radScene.angularAxis.ticks; track tick.index) {\n @if (tick.visible) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs text-foreground select-none whitespace-nowrap\"\n [monaChartLabelMeasure]=\"'angular:' + tick.tickKey\"\n data-mona-chart-export-role=\"polar-angular-label\"\n [attr.data-mona-chart-export-mode]=\"\n angularAxisRegistration()?.labelTemplate?.() ? 'raster' : 'vector'\n \"\n [style.left.px]=\"tick.labelPoint.x\"\n [style.top.px]=\"tick.labelPoint.y\"\n [style.transform]=\"angularLabelTransform(tick)\">\n @if (angularAxisRegistration()?.labelTemplate?.(); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: tick.value,\n axis: 'angular',\n index: tick.index,\n value: tick.value\n }\" />\n } @else {\n {{ tick.formattedValue }}\n }\n </div>\n }\n }\n }\n\n <!-- Radial Numeric Tick Labels -->\n @if (radScene.radialAxis?.visible && radScene.radialAxis?.labels) {\n @for (tick of radScene.radialAxis.ticks; track tick.index) {\n @if (tick.visible) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs text-muted-foreground select-none whitespace-nowrap\"\n [monaChartLabelMeasure]=\"'radial:' + tick.tickKey\"\n data-mona-chart-export-role=\"polar-radial-label\"\n [attr.data-mona-chart-export-mode]=\"\n radialAxisRegistration()?.labelTemplate?.() ? 'raster' : 'vector'\n \"\n [style.left.px]=\"tick.labelPoint.x\"\n [style.top.px]=\"tick.labelPoint.y\"\n [style.transform]=\"radialLabelTransform(tick, radScene.radialAxis.labelAngle)\">\n @if (radialAxisRegistration()?.labelTemplate?.(); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: tick.value,\n axis: 'radial',\n index: tick.index,\n value: tick.value\n }\" />\n } @else {\n {{ tick.formattedValue }}\n }\n </div>\n }\n }\n }\n }\n\n <!-- DOM Treemap Labels -->\n @if (treemapScene(); as tm) {\n @for (seriesScene of tm.series; track seriesScene.id) {\n @for (lbl of seriesScene.labels; track lbl.nodeId) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs select-none overflow-hidden text-ellipsis whitespace-nowrap px-1.5 py-0.5 flex flex-col justify-center transition-opacity duration-[var(--mona-chart-animation-duration,300ms)] ease-[var(--mona-chart-animation-easing,cubic-bezier(0,0,0.2,1))]\"\n [class.opacity-0]=\"isAnimating()\"\n [attr.data-mona-chart-export-animation-suppression]=\"isAnimating() ? 'opacity' : null\"\n data-mona-chart-export-role=\"treemap-label\"\n data-mona-chart-export-mode=\"raster\"\n [style.left.px]=\"lbl.bounds.x\"\n [style.top.px]=\"lbl.bounds.y\"\n [style.width.px]=\"lbl.bounds.width\"\n [style.height.px]=\"lbl.bounds.height\"\n [style.color]=\"lbl.textColor\">\n @if (treemapSeriesRegistration()?.labelTemplate?.(); as labelTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate.templateRef\"\n [ngTemplateOutletContext]=\"treemapLabelContext(lbl, seriesScene)\" />\n } @else {\n <span class=\"font-medium truncate\">{{ lbl.formattedLabel }}</span>\n @if (lbl.showValue) {\n <span class=\"text-[11px] opacity-80 truncate\">{{ lbl.formattedValue }}</span>\n }\n }\n </div>\n }\n }\n }\n\n <!-- DOM Funnel Labels -->\n @if (funnelScene(); as fn) {\n @for (seriesScene of fn.series; track seriesScene.id) {\n @for (lbl of seriesScene.labels; track lbl.stageId) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs select-none overflow-hidden text-ellipsis whitespace-nowrap flex flex-col items-center justify-center transition-opacity duration-[var(--mona-chart-animation-duration,300ms)] ease-[var(--mona-chart-animation-easing,cubic-bezier(0,0,0.2,1))]\"\n [class.opacity-0]=\"isAnimating()\"\n [attr.data-mona-chart-export-animation-suppression]=\"isAnimating() ? 'opacity' : null\"\n data-mona-chart-export-role=\"funnel-label\"\n data-mona-chart-export-mode=\"raster\"\n [style.left.px]=\"lbl.bounds.x\"\n [style.top.px]=\"lbl.bounds.y\"\n [style.width.px]=\"lbl.bounds.width\"\n [style.height.px]=\"lbl.bounds.height\"\n [style.color]=\"lbl.textColor\">\n @if (funnelSeriesRegistration()?.labelTemplate?.(); as labelTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate.templateRef\"\n [ngTemplateOutletContext]=\"funnelLabelContext(lbl, seriesScene)\" />\n } @else {\n <span class=\"font-medium truncate\">{{ lbl.text }}</span>\n }\n </div>\n }\n }\n }\n\n <!-- DOM Waterfall Labels -->\n @if (waterfallScene(); as wf) {\n @for (seriesScene of wf.series; track seriesScene.id) {\n @for (lbl of seriesScene.labels; track lbl.itemId) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none text-xs select-none overflow-hidden text-ellipsis whitespace-nowrap flex items-center justify-center transition-opacity duration-[var(--mona-chart-animation-duration,300ms)] ease-[var(--mona-chart-animation-easing,cubic-bezier(0,0,0.2,1))]\"\n [class.opacity-0]=\"isAnimating()\"\n [attr.data-mona-chart-export-animation-suppression]=\"isAnimating() ? 'opacity' : null\"\n data-mona-chart-export-role=\"waterfall-label\"\n data-mona-chart-export-mode=\"raster\"\n [style.left.px]=\"lbl.bounds.x\"\n [style.top.px]=\"lbl.bounds.y\"\n [style.width.px]=\"lbl.bounds.width\"\n [style.height.px]=\"lbl.bounds.height\"\n [style.color]=\"lbl.textColor\">\n @if (waterfallSeriesRegistration()?.labelTemplate?.(); as labelTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate.templateRef\"\n [ngTemplateOutletContext]=\"waterfallLabelContext(lbl, seriesScene)\" />\n } @else {\n <span class=\"font-medium truncate\">{{ lbl.text }}</span>\n }\n </div>\n }\n }\n }\n\n <!-- DOM Cartesian Overlays (Reference Lines, Reference Bands, Point Annotations) -->\n @if (cartesianOverlayScene(); as overlays) {\n <!-- Reference Lines -->\n @for (line of overlays.referenceLines; track line.id) {\n @if (line.label) {\n <div\n aria-hidden=\"true\"\n [class]=\"referenceLabelClasses() + (line.label.labelClass ? ' ' + line.label.labelClass : '')\"\n [class.hidden]=\"!line.label.formattedText && !resolveReferenceLineTemplate(line.id)\"\n [monaChartOverlayLabelMeasure]=\"'overlay:line:' + line.id\"\n data-mona-chart-export-role=\"reference-label\"\n [attr.data-mona-chart-export-mode]=\"resolveReferenceLineTemplate(line.id) ? 'raster' : 'vector'\"\n [style.left.px]=\"referenceLineLabelLeft(line)\"\n [style.top.px]=\"referenceLineLabelTop(line)\"\n [style.transform]=\"referenceLineLabelTransform(line)\">\n @if (resolveReferenceLineTemplate(line.id); as template) {\n @if (resolveReferenceLineRegistration(line.id); as reg) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: reg.value(),\n axis: line.axis,\n axisId: line.axisId,\n coordinate: line.coordinate,\n formattedValue: line.formattedValue,\n kind: 'line',\n value: reg.value()\n }\" />\n }\n } @else {\n {{ line.label.formattedText }}\n }\n </div>\n }\n }\n\n <!-- Reference Bands -->\n @for (band of overlays.referenceBands; track band.id) {\n @if (band.label) {\n <div\n aria-hidden=\"true\"\n [class]=\"referenceLabelClasses() + (band.label.labelClass ? ' ' + band.label.labelClass : '')\"\n [class.hidden]=\"!band.label.formattedText && !resolveReferenceBandTemplate(band.id)\"\n [monaChartOverlayLabelMeasure]=\"'overlay:band:' + band.id\"\n data-mona-chart-export-role=\"reference-label\"\n [attr.data-mona-chart-export-mode]=\"resolveReferenceBandTemplate(band.id) ? 'raster' : 'vector'\"\n [style.left.px]=\"referenceBandLabelLeft(band)\"\n [style.top.px]=\"referenceBandLabelTop(band)\"\n [style.transform]=\"referenceBandLabelTransform(band)\">\n @if (resolveReferenceBandTemplate(band.id); as template) {\n @if (resolveReferenceBandRegistration(band.id); as reg) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: { from: reg.from(), to: reg.to() },\n axis: band.axis,\n axisId: band.axisId,\n bounds: band.bounds,\n formattedFrom: band.formattedFrom,\n formattedTo: band.formattedTo,\n from: reg.from(),\n kind: 'band',\n to: reg.to()\n }\" />\n }\n } @else {\n {{ band.label.formattedText }}\n }\n </div>\n }\n }\n\n <!-- Point Annotations -->\n @for (ann of overlays.annotations; track ann.id) {\n @if (ann.label) {\n <div\n aria-hidden=\"true\"\n [class]=\"annotationLabelClasses() + (ann.label.labelClass ? ' ' + ann.label.labelClass : '')\"\n [class.hidden]=\"!ann.label.formattedText && !resolveAnnotationTemplate(ann.id)\"\n [monaChartOverlayLabelMeasure]=\"'overlay:ann:' + ann.id\"\n data-mona-chart-export-role=\"annotation-label\"\n [attr.data-mona-chart-export-mode]=\"resolveAnnotationTemplate(ann.id) ? 'raster' : 'vector'\"\n [style.left.px]=\"annotationLabelLeft(ann)\"\n [style.top.px]=\"annotationLabelTop(ann)\"\n [style.transform]=\"annotationLabelTransform(ann)\">\n @if (resolveAnnotationTemplate(ann.id); as template) {\n @if (resolveAnnotationRegistration(ann.id); as reg) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: ann.data,\n data: ann.data,\n formattedX: ann.formattedX,\n formattedY: ann.formattedY,\n point: ann.point,\n x: reg.x(),\n xAxisId: ann.xAxisId,\n y: reg.y(),\n yAxisId: ann.yAxisId\n }\" />\n }\n } @else {\n {{ ann.label.formattedText }}\n }\n </div>\n }\n }\n }\n\n <!-- DOM Cartesian Data Labels (Template Layer) -->\n @if (cartesianDataLabelScene(); as labelScene) {\n @for (label of labelScene.templateLabels; track label.seriesId + \":\" + label.markId) {\n <div\n aria-hidden=\"true\"\n class=\"absolute pointer-events-none select-none whitespace-nowrap transition-opacity duration-[var(--mona-chart-animation-duration,300ms)] ease-[var(--mona-chart-animation-easing,cubic-bezier(0,0,0.2,1))]\"\n [class.opacity-0]=\"isAnimating()\"\n [attr.data-mona-chart-export-animation-suppression]=\"isAnimating() ? 'opacity' : null\"\n [monaChartDataLabelMeasure]=\"label.seriesId + ':' + label.markId\"\n data-mona-chart-export-role=\"data-label-template\"\n data-mona-chart-export-mode=\"raster\"\n [style.left.px]=\"label.bounds.x\"\n [style.top.px]=\"label.bounds.y\">\n <ng-container\n [ngTemplateOutlet]=\"label.template.templateRef\"\n [ngTemplateOutletContext]=\"label.context\" />\n </div>\n }\n }\n\n <!-- Crosshair DOM Axis Labels -->\n @if (crosshairState(); as chState) {\n @if (cartesianXYScene(); as cart) {\n @if (resolveCrosshairRegistration(); as chReg) {\n @if (chReg.enabled() !== false) {\n @if (chState.x && chReg.showAxisLabels() !== false && chReg.showXLabel() !== false) {\n <div\n aria-hidden=\"true\"\n [class]=\"crosshairLabelClasses()\"\n [monaChartOverlayLabelMeasure]=\"'crosshair:x'\"\n data-mona-chart-export-role=\"crosshair-label\"\n [attr.data-mona-chart-export-mode]=\"chReg.template?.() ? 'raster' : 'vector'\"\n [style.left.px]=\"crosshairXLabelLeft(cart, chState)\"\n [style.top.px]=\"crosshairXLabelTop(cart, chState)\"\n [style.transform]=\"crosshairXLabelTransform(cart, chState)\">\n @if (chReg.template?.(); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: chState.x.value,\n axis: 'x',\n axisId: chState.x.axisId,\n coordinate: chState.x.coordinate,\n formattedValue: chState.x.formattedValue,\n snapped: chState.snapped,\n source: chState.source,\n value: chState.x.value\n }\" />\n } @else {\n {{ chState.x.formattedValue }}\n }\n </div>\n }\n\n @if (chState.y && chReg.showAxisLabels() !== false && chReg.showYLabel() !== false) {\n <div\n aria-hidden=\"true\"\n [class]=\"crosshairLabelClasses()\"\n [monaChartOverlayLabelMeasure]=\"'crosshair:y'\"\n data-mona-chart-export-role=\"crosshair-label\"\n [attr.data-mona-chart-export-mode]=\"chReg.template?.() ? 'raster' : 'vector'\"\n [style.left.px]=\"crosshairYLabelLeft(cart, chState)\"\n [style.top.px]=\"crosshairYLabelTop(cart, chState)\"\n [style.transform]=\"crosshairYLabelTransform(cart, chState)\">\n @if (chReg.template?.(); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: chState.y.value,\n axis: 'y',\n axisId: chState.y.axisId,\n coordinate: chState.y.coordinate,\n formattedValue: chState.y.formattedValue,\n snapped: chState.snapped,\n source: chState.source,\n value: chState.y.value\n }\" />\n } @else {\n {{ chState.y.formattedValue }}\n }\n </div>\n }\n }\n }\n }\n }\n\n <!-- Tooltip overlay in plot-local coordinates -->\n <ng-content select=\"mona-chart-tooltip\"></ng-content>\n\n <!-- No Data Placeholder -->\n @if (hasNoData()) {\n <div\n [class]=\"noDataClasses()\"\n data-mona-chart-export-role=\"no-data\"\n [attr.data-mona-chart-export-mode]=\"noDataTemplate() ? 'raster' : 'vector'\">\n @if (noDataTemplate(); as template) {\n <ng-container [ngTemplateOutlet]=\"template.templateRef\" />\n } @else {\n <span>{{ messages().noData }}</span>\n }\n </div>\n }\n\n <!-- Off-screen Accessible Live Region for Keyboard/Screen-reader Exploration -->\n <div class=\"sr-only\" aria-live=\"polite\" aria-atomic=\"true\">\n {{ activeAccessibilityText() }}\n </div>\n </div>\n\n <!-- Projected Legend Outside Plot Container -->\n <ng-content select=\"mona-chart-legend\"></ng-content>\n\n <!-- Other Projected Content (Series, Axes, Templates) -->\n <ng-content></ng-content>\n</div>\n" }]
56971
57006
  }], ctorParameters: () => [], propDecorators: { canvasElement: [{ type: i0.ViewChild, args: ["canvas", { isSignal: true }] }], noDataTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ChartNoDataTemplateDirective), { isSignal: true }] }], plotSurfaceElement: [{ type: i0.ViewChild, args: ["plotSurface", { isSignal: true }] }], subtitleTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ChartSubtitleTemplateDirective), { isSignal: true }] }], svgElement: [{ type: i0.ViewChild, args: ["svgSurface", { isSignal: true }] }], titleTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ChartTitleTemplateDirective), { isSignal: true }] }], animation: [{ type: i0.Input, args: [{ isSignal: true, alias: "animation", required: false }] }], ariaDescription: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-description", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], defaultViewport: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultViewport", required: false }] }], downsampling: [{ type: i0.Input, args: [{ isSignal: true, alias: "downsampling", required: false }] }], navigation: [{ type: i0.Input, args: [{ isSignal: true, alias: "navigation", required: false }] }], pointClick: [{ type: i0.Output, args: ["pointClick"] }], pointFocusChange: [{ type: i0.Output, args: ["pointFocusChange"] }], renderer: [{ type: i0.Input, args: [{ isSignal: true, alias: "renderer", required: false }] }], seriesVisibilityChange: [{ type: i0.Output, args: ["seriesVisibilityChange"] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], synchronization: [{ type: i0.Input, args: [{ isSignal: true, alias: "synchronization", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], titleAlign: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleAlign", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], viewport: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewport", required: false }] }], viewportChange: [{ type: i0.Output, args: ["viewportChange"] }], xField: [{ type: i0.Input, args: [{ isSignal: true, alias: "xField", required: false }] }] } });
56972
57007
 
56973
57008
  class ChartAxisLabelTemplateDirective {
@@ -59498,9 +59533,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
59498
59533
  class ChartLegendComponent {
59499
59534
  #chartContext;
59500
59535
  #destroyRef;
59536
+ #direction;
59537
+ #i18n;
59501
59538
  constructor() {
59502
59539
  this.#chartContext = inject(CHART_CONTEXT, { optional: true });
59503
59540
  this.#destroyRef = inject(DestroyRef);
59541
+ this.#direction = injectComponentDirection();
59542
+ this.#i18n = inject(MonaI18nService);
59543
+ this.messages = this.#i18n.componentMessages("chart", CHART_DEFAULT_MESSAGES);
59504
59544
  this.containerClasses = computed(() => twMerge(chartLegendBaseThemeVariants({ position: this.position() }), this.userClass()), /* @ts-ignore */
59505
59545
  ...(ngDevMode ? [{ debugName: "containerClasses" }] : /* istanbul ignore next */ []));
59506
59546
  this.gradientCss = computed(() => {
@@ -59508,7 +59548,7 @@ class ChartLegendComponent {
59508
59548
  if (!scale || !scale.stops || scale.stops.length === 0)
59509
59549
  return "";
59510
59550
  const isVertical = this.position() === "left" || this.position() === "right";
59511
- const dir = isVertical ? "to top" : "to right";
59551
+ const dir = isVertical ? "to top" : this.#direction() === "rtl" ? "to left" : "to right";
59512
59552
  const stopStrs = scale.stops.map(s => `${s.color} ${Math.round(s.offset * 100)}%`).join(", ");
59513
59553
  return `linear-gradient(${dir}, ${stopStrs})`;
59514
59554
  }, /* @ts-ignore */
@@ -59540,13 +59580,14 @@ class ChartLegendComponent {
59540
59580
  ...(ngDevMode ? [{ debugName: "itemTemplate" }] : /* istanbul ignore next */ []));
59541
59581
  this.legendAriaLabel = computed(() => {
59542
59582
  const scale = this.legendScale();
59583
+ const msgs = this.messages();
59543
59584
  if (!scale)
59544
- return "Chart legend";
59545
- const title = scale.title || "Color scale";
59585
+ return msgs.chartLegend;
59586
+ const title = scale.title || msgs.colorScale;
59546
59587
  if (scale.mode === "diverging" && scale.formattedMidpoint) {
59547
- return `${title}, ${scale.formattedMin} to ${scale.formattedMidpoint} to ${scale.formattedMax}`;
59588
+ return msgs.divergingRangeDescription(title, scale.formattedMin, scale.formattedMidpoint, scale.formattedMax);
59548
59589
  }
59549
- return `${title}, ${scale.formattedMin} to ${scale.formattedMax}`;
59590
+ return msgs.rangeDescription(title, scale.formattedMin, scale.formattedMax);
59550
59591
  }, /* @ts-ignore */
59551
59592
  ...(ngDevMode ? [{ debugName: "legendAriaLabel" }] : /* istanbul ignore next */ []));
59552
59593
  this.legendItems = computed(() => this.#chartContext?.legendItems() ?? [], /* @ts-ignore */
@@ -59609,14 +59650,14 @@ class ChartLegendComponent {
59609
59650
  this.#chartContext.toggleLegendItem(item);
59610
59651
  }
59611
59652
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ChartLegendComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
59612
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: ChartLegendComponent, isStandalone: true, selector: "mona-chart-legend", inputs: { interactive: { classPropertyName: "interactive", publicName: "interactive", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClasses()", "style.order": "hostOrder()" } }, queries: [{ propertyName: "itemTemplate", first: true, predicate: ChartLegendItemTemplateDirective, descendants: true, isSignal: true }], ngImport: i0, template: "@if (isColorScaleMode() && legendScale(); as scale) {\n <div\n [class]=\"containerClasses()\"\n [attr.aria-label]=\"legendAriaLabel()\"\n role=\"region\"\n data-mona-chart-export-role=\"legend-color-scale\"\n data-mona-chart-export-mode=\"raster\">\n @if (position() === \"left\" || position() === \"right\") {\n <div class=\"flex flex-col items-center gap-1.5 px-1 py-2\">\n @if (scale.title) {\n <div class=\"text-xs font-semibold text-foreground text-center\">{{ scale.title }}</div>\n }\n <div class=\"flex items-center gap-2\">\n <div\n class=\"w-2.5 h-32 rounded-full border border-border/50 flex-shrink-0\"\n [style.background]=\"gradientCss()\"\n aria-hidden=\"true\"></div>\n <div class=\"flex flex-col justify-between h-32 text-[11px] font-medium text-muted-foreground\">\n <span class=\"text-left\">{{ scale.formattedMax }}</span>\n @if (scale.formattedMidpoint) {\n <span class=\"text-left\">{{ scale.formattedMidpoint }}</span>\n }\n <span class=\"text-left\">{{ scale.formattedMin }}</span>\n </div>\n </div>\n </div>\n } @else {\n <div class=\"flex flex-col items-center gap-1.5 py-1\">\n @if (scale.title) {\n <div class=\"text-xs font-semibold text-foreground\">{{ scale.title }}</div>\n }\n <div class=\"flex flex-col items-center gap-1 w-48 sm:w-60\">\n <div\n class=\"h-2.5 w-full rounded-full border border-border/50 flex-shrink-0\"\n [style.background]=\"gradientCss()\"\n aria-hidden=\"true\"></div>\n <div class=\"flex justify-between w-full text-[11px] font-medium text-muted-foreground\">\n @if (scale.ticks && scale.ticks.length > 0) {\n @for (tick of scale.ticks; track tick.value) {\n <span\n [style.text-align]=\"\n tick.offset === 0 ? 'left' : tick.offset === 1 ? 'right' : 'center'\n \">\n {{ tick.formattedValue }}\n </span>\n }\n } @else {\n <span class=\"text-left\">{{ scale.formattedMin }}</span>\n @if (scale.formattedMidpoint) {\n <span class=\"text-center\">{{ scale.formattedMidpoint }}</span>\n }\n <span class=\"text-right\">{{ scale.formattedMax }}</span>\n }\n </div>\n </div>\n </div>\n }\n </div>\n} @else {\n <div [class]=\"containerClasses()\">\n @for (item of legendItems(); track item.itemId) {\n @if (itemTemplate(); as template) {\n <div\n (click)=\"onItemClick(item)\"\n (keydown.enter)=\"onItemClick(item)\"\n (keydown.space)=\"onItemClick(item); $event.preventDefault()\"\n [class]=\"itemClasses(item)\"\n [attr.role]=\"isItemInteractive(item) ? 'button' : null\"\n [attr.tabindex]=\"isItemInteractive(item) ? 0 : null\"\n [attr.aria-pressed]=\"isItemInteractive(item) ? item.visible : null\"\n data-mona-chart-export-role=\"legend-item-template\"\n data-mona-chart-export-mode=\"raster\">\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: item,\n color: item.color,\n dataIndex: item.dataIndex,\n datum: item.datum,\n interactive: isItemInteractive(item),\n itemId: item.itemId,\n kind: item.kind,\n name: item.name,\n percentage: item.percentage,\n secondaryColor: item.secondaryColor,\n series: item,\n seriesId: item.seriesId,\n seriesType: item.seriesType,\n value: item.value,\n visible: item.visible\n }\" />\n </div>\n } @else {\n @if (isItemInteractive(item)) {\n <button\n type=\"button\"\n (click)=\"onItemClick(item)\"\n [class]=\"itemClasses(item)\"\n [attr.aria-pressed]=\"item.visible\">\n <span\n class=\"inline-block h-2.5 w-2.5 rounded-full flex-shrink-0\"\n [style.background]=\"\n item.secondaryColor\n ? 'linear-gradient(135deg, ' + item.color + ' 50%, ' + item.secondaryColor + ' 50%)'\n : item.color\n \"\n [style.backgroundColor]=\"item.color\"\n data-mona-chart-export-role=\"legend-bullet\"></span>\n <span class=\"text-xs font-medium\" data-mona-chart-export-role=\"legend-text\">{{\n item.name\n }}</span>\n </button>\n } @else {\n <div [class]=\"itemClasses(item)\">\n <span\n class=\"inline-block h-2.5 w-2.5 rounded-full flex-shrink-0\"\n [style.background]=\"\n item.secondaryColor\n ? 'linear-gradient(135deg, ' + item.color + ' 50%, ' + item.secondaryColor + ' 50%)'\n : item.color\n \"\n [style.backgroundColor]=\"item.color\"\n data-mona-chart-export-role=\"legend-bullet\"></span>\n <span class=\"text-xs font-medium\" data-mona-chart-export-role=\"legend-text\">{{\n item.name\n }}</span>\n </div>\n }\n }\n }\n </div>\n}\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] }); }
59653
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: ChartLegendComponent, isStandalone: true, selector: "mona-chart-legend", inputs: { interactive: { classPropertyName: "interactive", publicName: "interactive", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClasses()", "style.order": "hostOrder()" } }, queries: [{ propertyName: "itemTemplate", first: true, predicate: ChartLegendItemTemplateDirective, descendants: true, isSignal: true }], ngImport: i0, template: "@if (isColorScaleMode() && legendScale(); as scale) {\n <div\n [class]=\"containerClasses()\"\n [attr.aria-label]=\"legendAriaLabel()\"\n role=\"region\"\n data-mona-chart-export-role=\"legend-color-scale\"\n data-mona-chart-export-mode=\"raster\">\n @if (position() === \"left\" || position() === \"right\") {\n <div class=\"flex flex-col items-center gap-1.5 px-1 py-2\">\n @if (scale.title) {\n <div class=\"text-xs font-semibold text-foreground text-center\">{{ scale.title }}</div>\n }\n <div class=\"flex items-center gap-2\">\n <div\n class=\"w-2.5 h-32 rounded-full border border-border/50 flex-shrink-0\"\n [style.background]=\"gradientCss()\"\n aria-hidden=\"true\"></div>\n <div class=\"flex flex-col justify-between h-32 text-[11px] font-medium text-muted-foreground\">\n <span class=\"text-start\">{{ scale.formattedMax }}</span>\n @if (scale.formattedMidpoint) {\n <span class=\"text-start\">{{ scale.formattedMidpoint }}</span>\n }\n <span class=\"text-start\">{{ scale.formattedMin }}</span>\n </div>\n </div>\n </div>\n } @else {\n <div class=\"flex flex-col items-center gap-1.5 py-1\">\n @if (scale.title) {\n <div class=\"text-xs font-semibold text-foreground\">{{ scale.title }}</div>\n }\n <div class=\"flex flex-col items-center gap-1 w-48 sm:w-60\">\n <div\n class=\"h-2.5 w-full rounded-full border border-border/50 flex-shrink-0\"\n [style.background]=\"gradientCss()\"\n aria-hidden=\"true\"></div>\n <div class=\"flex justify-between w-full text-[11px] font-medium text-muted-foreground\">\n @if (scale.ticks && scale.ticks.length > 0) {\n @for (tick of scale.ticks; track tick.value) {\n <span\n [style.text-align]=\"\n tick.offset === 0 ? 'start' : tick.offset === 1 ? 'end' : 'center'\n \">\n {{ tick.formattedValue }}\n </span>\n }\n } @else {\n <span class=\"text-start\">{{ scale.formattedMin }}</span>\n @if (scale.formattedMidpoint) {\n <span class=\"text-center\">{{ scale.formattedMidpoint }}</span>\n }\n <span class=\"text-end\">{{ scale.formattedMax }}</span>\n }\n </div>\n </div>\n </div>\n }\n </div>\n} @else {\n <div [class]=\"containerClasses()\">\n @for (item of legendItems(); track item.itemId) {\n @if (itemTemplate(); as template) {\n <div\n (click)=\"onItemClick(item)\"\n (keydown.enter)=\"onItemClick(item)\"\n (keydown.space)=\"onItemClick(item); $event.preventDefault()\"\n [class]=\"itemClasses(item)\"\n [attr.role]=\"isItemInteractive(item) ? 'button' : null\"\n [attr.tabindex]=\"isItemInteractive(item) ? 0 : null\"\n [attr.aria-pressed]=\"isItemInteractive(item) ? item.visible : null\"\n data-mona-chart-export-role=\"legend-item-template\"\n data-mona-chart-export-mode=\"raster\">\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: item,\n color: item.color,\n dataIndex: item.dataIndex,\n datum: item.datum,\n interactive: isItemInteractive(item),\n itemId: item.itemId,\n kind: item.kind,\n name: item.name,\n percentage: item.percentage,\n secondaryColor: item.secondaryColor,\n series: item,\n seriesId: item.seriesId,\n seriesType: item.seriesType,\n value: item.value,\n visible: item.visible\n }\" />\n </div>\n } @else {\n @if (isItemInteractive(item)) {\n <button\n type=\"button\"\n (click)=\"onItemClick(item)\"\n [class]=\"itemClasses(item)\"\n [attr.aria-pressed]=\"item.visible\">\n <span\n class=\"inline-block h-2.5 w-2.5 rounded-full flex-shrink-0\"\n [style.background]=\"\n item.secondaryColor\n ? 'linear-gradient(135deg, ' + item.color + ' 50%, ' + item.secondaryColor + ' 50%)'\n : item.color\n \"\n [style.backgroundColor]=\"item.color\"\n data-mona-chart-export-role=\"legend-bullet\"></span>\n <span class=\"text-xs font-medium\" data-mona-chart-export-role=\"legend-text\">{{\n item.name\n }}</span>\n </button>\n } @else {\n <div [class]=\"itemClasses(item)\">\n <span\n class=\"inline-block h-2.5 w-2.5 rounded-full flex-shrink-0\"\n [style.background]=\"\n item.secondaryColor\n ? 'linear-gradient(135deg, ' + item.color + ' 50%, ' + item.secondaryColor + ' 50%)'\n : item.color\n \"\n [style.backgroundColor]=\"item.color\"\n data-mona-chart-export-role=\"legend-bullet\"></span>\n <span class=\"text-xs font-medium\" data-mona-chart-export-role=\"legend-text\">{{\n item.name\n }}</span>\n </div>\n }\n }\n }\n </div>\n}\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] }); }
59613
59654
  }
59614
59655
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ChartLegendComponent, decorators: [{
59615
59656
  type: Component,
59616
59657
  args: [{ selector: "mona-chart-legend", imports: [NgTemplateOutlet], host: {
59617
59658
  "[class]": "hostClasses()",
59618
59659
  "[style.order]": "hostOrder()"
59619
- }, template: "@if (isColorScaleMode() && legendScale(); as scale) {\n <div\n [class]=\"containerClasses()\"\n [attr.aria-label]=\"legendAriaLabel()\"\n role=\"region\"\n data-mona-chart-export-role=\"legend-color-scale\"\n data-mona-chart-export-mode=\"raster\">\n @if (position() === \"left\" || position() === \"right\") {\n <div class=\"flex flex-col items-center gap-1.5 px-1 py-2\">\n @if (scale.title) {\n <div class=\"text-xs font-semibold text-foreground text-center\">{{ scale.title }}</div>\n }\n <div class=\"flex items-center gap-2\">\n <div\n class=\"w-2.5 h-32 rounded-full border border-border/50 flex-shrink-0\"\n [style.background]=\"gradientCss()\"\n aria-hidden=\"true\"></div>\n <div class=\"flex flex-col justify-between h-32 text-[11px] font-medium text-muted-foreground\">\n <span class=\"text-left\">{{ scale.formattedMax }}</span>\n @if (scale.formattedMidpoint) {\n <span class=\"text-left\">{{ scale.formattedMidpoint }}</span>\n }\n <span class=\"text-left\">{{ scale.formattedMin }}</span>\n </div>\n </div>\n </div>\n } @else {\n <div class=\"flex flex-col items-center gap-1.5 py-1\">\n @if (scale.title) {\n <div class=\"text-xs font-semibold text-foreground\">{{ scale.title }}</div>\n }\n <div class=\"flex flex-col items-center gap-1 w-48 sm:w-60\">\n <div\n class=\"h-2.5 w-full rounded-full border border-border/50 flex-shrink-0\"\n [style.background]=\"gradientCss()\"\n aria-hidden=\"true\"></div>\n <div class=\"flex justify-between w-full text-[11px] font-medium text-muted-foreground\">\n @if (scale.ticks && scale.ticks.length > 0) {\n @for (tick of scale.ticks; track tick.value) {\n <span\n [style.text-align]=\"\n tick.offset === 0 ? 'left' : tick.offset === 1 ? 'right' : 'center'\n \">\n {{ tick.formattedValue }}\n </span>\n }\n } @else {\n <span class=\"text-left\">{{ scale.formattedMin }}</span>\n @if (scale.formattedMidpoint) {\n <span class=\"text-center\">{{ scale.formattedMidpoint }}</span>\n }\n <span class=\"text-right\">{{ scale.formattedMax }}</span>\n }\n </div>\n </div>\n </div>\n }\n </div>\n} @else {\n <div [class]=\"containerClasses()\">\n @for (item of legendItems(); track item.itemId) {\n @if (itemTemplate(); as template) {\n <div\n (click)=\"onItemClick(item)\"\n (keydown.enter)=\"onItemClick(item)\"\n (keydown.space)=\"onItemClick(item); $event.preventDefault()\"\n [class]=\"itemClasses(item)\"\n [attr.role]=\"isItemInteractive(item) ? 'button' : null\"\n [attr.tabindex]=\"isItemInteractive(item) ? 0 : null\"\n [attr.aria-pressed]=\"isItemInteractive(item) ? item.visible : null\"\n data-mona-chart-export-role=\"legend-item-template\"\n data-mona-chart-export-mode=\"raster\">\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: item,\n color: item.color,\n dataIndex: item.dataIndex,\n datum: item.datum,\n interactive: isItemInteractive(item),\n itemId: item.itemId,\n kind: item.kind,\n name: item.name,\n percentage: item.percentage,\n secondaryColor: item.secondaryColor,\n series: item,\n seriesId: item.seriesId,\n seriesType: item.seriesType,\n value: item.value,\n visible: item.visible\n }\" />\n </div>\n } @else {\n @if (isItemInteractive(item)) {\n <button\n type=\"button\"\n (click)=\"onItemClick(item)\"\n [class]=\"itemClasses(item)\"\n [attr.aria-pressed]=\"item.visible\">\n <span\n class=\"inline-block h-2.5 w-2.5 rounded-full flex-shrink-0\"\n [style.background]=\"\n item.secondaryColor\n ? 'linear-gradient(135deg, ' + item.color + ' 50%, ' + item.secondaryColor + ' 50%)'\n : item.color\n \"\n [style.backgroundColor]=\"item.color\"\n data-mona-chart-export-role=\"legend-bullet\"></span>\n <span class=\"text-xs font-medium\" data-mona-chart-export-role=\"legend-text\">{{\n item.name\n }}</span>\n </button>\n } @else {\n <div [class]=\"itemClasses(item)\">\n <span\n class=\"inline-block h-2.5 w-2.5 rounded-full flex-shrink-0\"\n [style.background]=\"\n item.secondaryColor\n ? 'linear-gradient(135deg, ' + item.color + ' 50%, ' + item.secondaryColor + ' 50%)'\n : item.color\n \"\n [style.backgroundColor]=\"item.color\"\n data-mona-chart-export-role=\"legend-bullet\"></span>\n <span class=\"text-xs font-medium\" data-mona-chart-export-role=\"legend-text\">{{\n item.name\n }}</span>\n </div>\n }\n }\n }\n </div>\n}\n" }]
59660
+ }, template: "@if (isColorScaleMode() && legendScale(); as scale) {\n <div\n [class]=\"containerClasses()\"\n [attr.aria-label]=\"legendAriaLabel()\"\n role=\"region\"\n data-mona-chart-export-role=\"legend-color-scale\"\n data-mona-chart-export-mode=\"raster\">\n @if (position() === \"left\" || position() === \"right\") {\n <div class=\"flex flex-col items-center gap-1.5 px-1 py-2\">\n @if (scale.title) {\n <div class=\"text-xs font-semibold text-foreground text-center\">{{ scale.title }}</div>\n }\n <div class=\"flex items-center gap-2\">\n <div\n class=\"w-2.5 h-32 rounded-full border border-border/50 flex-shrink-0\"\n [style.background]=\"gradientCss()\"\n aria-hidden=\"true\"></div>\n <div class=\"flex flex-col justify-between h-32 text-[11px] font-medium text-muted-foreground\">\n <span class=\"text-start\">{{ scale.formattedMax }}</span>\n @if (scale.formattedMidpoint) {\n <span class=\"text-start\">{{ scale.formattedMidpoint }}</span>\n }\n <span class=\"text-start\">{{ scale.formattedMin }}</span>\n </div>\n </div>\n </div>\n } @else {\n <div class=\"flex flex-col items-center gap-1.5 py-1\">\n @if (scale.title) {\n <div class=\"text-xs font-semibold text-foreground\">{{ scale.title }}</div>\n }\n <div class=\"flex flex-col items-center gap-1 w-48 sm:w-60\">\n <div\n class=\"h-2.5 w-full rounded-full border border-border/50 flex-shrink-0\"\n [style.background]=\"gradientCss()\"\n aria-hidden=\"true\"></div>\n <div class=\"flex justify-between w-full text-[11px] font-medium text-muted-foreground\">\n @if (scale.ticks && scale.ticks.length > 0) {\n @for (tick of scale.ticks; track tick.value) {\n <span\n [style.text-align]=\"\n tick.offset === 0 ? 'start' : tick.offset === 1 ? 'end' : 'center'\n \">\n {{ tick.formattedValue }}\n </span>\n }\n } @else {\n <span class=\"text-start\">{{ scale.formattedMin }}</span>\n @if (scale.formattedMidpoint) {\n <span class=\"text-center\">{{ scale.formattedMidpoint }}</span>\n }\n <span class=\"text-end\">{{ scale.formattedMax }}</span>\n }\n </div>\n </div>\n </div>\n }\n </div>\n} @else {\n <div [class]=\"containerClasses()\">\n @for (item of legendItems(); track item.itemId) {\n @if (itemTemplate(); as template) {\n <div\n (click)=\"onItemClick(item)\"\n (keydown.enter)=\"onItemClick(item)\"\n (keydown.space)=\"onItemClick(item); $event.preventDefault()\"\n [class]=\"itemClasses(item)\"\n [attr.role]=\"isItemInteractive(item) ? 'button' : null\"\n [attr.tabindex]=\"isItemInteractive(item) ? 0 : null\"\n [attr.aria-pressed]=\"isItemInteractive(item) ? item.visible : null\"\n data-mona-chart-export-role=\"legend-item-template\"\n data-mona-chart-export-mode=\"raster\">\n <ng-container\n [ngTemplateOutlet]=\"template.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: item,\n color: item.color,\n dataIndex: item.dataIndex,\n datum: item.datum,\n interactive: isItemInteractive(item),\n itemId: item.itemId,\n kind: item.kind,\n name: item.name,\n percentage: item.percentage,\n secondaryColor: item.secondaryColor,\n series: item,\n seriesId: item.seriesId,\n seriesType: item.seriesType,\n value: item.value,\n visible: item.visible\n }\" />\n </div>\n } @else {\n @if (isItemInteractive(item)) {\n <button\n type=\"button\"\n (click)=\"onItemClick(item)\"\n [class]=\"itemClasses(item)\"\n [attr.aria-pressed]=\"item.visible\">\n <span\n class=\"inline-block h-2.5 w-2.5 rounded-full flex-shrink-0\"\n [style.background]=\"\n item.secondaryColor\n ? 'linear-gradient(135deg, ' + item.color + ' 50%, ' + item.secondaryColor + ' 50%)'\n : item.color\n \"\n [style.backgroundColor]=\"item.color\"\n data-mona-chart-export-role=\"legend-bullet\"></span>\n <span class=\"text-xs font-medium\" data-mona-chart-export-role=\"legend-text\">{{\n item.name\n }}</span>\n </button>\n } @else {\n <div [class]=\"itemClasses(item)\">\n <span\n class=\"inline-block h-2.5 w-2.5 rounded-full flex-shrink-0\"\n [style.background]=\"\n item.secondaryColor\n ? 'linear-gradient(135deg, ' + item.color + ' 50%, ' + item.secondaryColor + ' 50%)'\n : item.color\n \"\n [style.backgroundColor]=\"item.color\"\n data-mona-chart-export-role=\"legend-bullet\"></span>\n <span class=\"text-xs font-medium\" data-mona-chart-export-role=\"legend-text\">{{\n item.name\n }}</span>\n </div>\n }\n }\n }\n </div>\n}\n" }]
59620
59661
  }], ctorParameters: () => [], propDecorators: { itemTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ChartLegendItemTemplateDirective), { isSignal: true }] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
59621
59662
 
59622
59663
  class ChartTooltipTemplateDirective {
@@ -59636,17 +59677,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
59636
59677
  class ChartTooltipComponent {
59637
59678
  #chartContext;
59638
59679
  #destroyRef;
59680
+ #i18n;
59639
59681
  #measuredHeight;
59640
59682
  #measuredWidth;
59641
59683
  #tooltipResizeObserver;
59642
59684
  constructor() {
59643
59685
  this.#chartContext = inject(CHART_CONTEXT, { optional: true });
59644
59686
  this.#destroyRef = inject(DestroyRef);
59687
+ this.#i18n = inject(MonaI18nService);
59645
59688
  this.#measuredHeight = signal(60, /* @ts-ignore */
59646
59689
  ...(ngDevMode ? [{ debugName: "#measuredHeight" }] : /* istanbul ignore next */ []));
59647
59690
  this.#measuredWidth = signal(180, /* @ts-ignore */
59648
59691
  ...(ngDevMode ? [{ debugName: "#measuredWidth" }] : /* istanbul ignore next */ []));
59649
59692
  this.#tooltipResizeObserver = null;
59693
+ this.messages = this.#i18n.componentMessages("chart", CHART_DEFAULT_MESSAGES);
59650
59694
  this.customTemplate = contentChild(ChartTooltipTemplateDirective, /* @ts-ignore */
59651
59695
  ...(ngDevMode ? [{ debugName: "customTemplate" }] : /* istanbul ignore next */ []));
59652
59696
  this.placement = computed(() => {
@@ -59768,14 +59812,30 @@ class ChartTooltipComponent {
59768
59812
  });
59769
59813
  this.#destroyRef.onDestroy(unregister);
59770
59814
  }
59815
+ financialDirectionLabel(dir) {
59816
+ if (dir === "rising") {
59817
+ return this.messages().rising;
59818
+ }
59819
+ if (dir === "falling") {
59820
+ return this.messages().falling;
59821
+ }
59822
+ return this.messages().unchanged;
59823
+ }
59824
+ formatPercent(value) {
59825
+ return formatNumber(value, this.#i18n.localeId(), {
59826
+ style: "percent",
59827
+ minimumFractionDigits: 1,
59828
+ maximumFractionDigits: 1
59829
+ });
59830
+ }
59771
59831
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ChartTooltipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
59772
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: ChartTooltipComponent, isStandalone: true, selector: "mona-chart-tooltip", inputs: { enabled: { classPropertyName: "enabled", publicName: "enabled", isSignal: true, isRequired: false, transformFunction: null }, shared: { classPropertyName: "shared", publicName: "shared", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "contents" }, queries: [{ propertyName: "customTemplate", first: true, predicate: ChartTooltipTemplateDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "tooltipContainer", first: true, predicate: ["tooltipContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (enabled() && tooltipContext(); as context) {\n <div\n #tooltipContainer\n [class]=\"tooltipClasses()\"\n [style.left.px]=\"placement().left\"\n [style.top.px]=\"placement().top\"\n [attr.data-placement]=\"placement().placement\">\n @if (customTemplate(); as template) {\n <ng-container [ngTemplateOutlet]=\"template.templateRef\" [ngTemplateOutletContext]=\"context\" />\n } @else if (context.point.seriesType === \"heatmap\") {\n <div class=\"flex items-center gap-1.5 mb-1\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{ context.point.seriesName }}</span>\n </div>\n <div class=\"flex flex-col gap-0.5 text-xs text-muted-foreground\">\n <div>\n <span class=\"font-medium text-foreground\">{{ context.point.formattedX }}</span\n >,\n <span class=\"font-medium text-foreground\">{{\n context.point.formattedYCategory || context.point.categoryY\n }}</span>\n </div>\n <div>\n Value: <span class=\"font-medium text-foreground\">{{ context.point.formattedY }}</span>\n </div>\n </div>\n } @else if (context.point.seriesType === \"pie\" || context.point.seriesType === \"donut\") {\n <div class=\"flex items-center gap-1.5 mb-1\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{\n context.point.formattedCategory || context.point.seriesName\n }}</span>\n </div>\n <div class=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span class=\"font-medium text-foreground\">{{ context.point.formattedY }}</span>\n @if (context.point.formattedPercentage) {\n <span>\u00B7</span>\n <span>{{ context.point.formattedPercentage }}</span>\n }\n </div>\n } @else if (context.point.seriesType === \"gauge\") {\n <div class=\"flex items-center gap-1.5 mb-1\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{ context.point.seriesName }}</span>\n </div>\n <div class=\"flex flex-col gap-0.5 text-xs text-muted-foreground\">\n <div>\n Value: <span class=\"font-medium text-foreground\">{{ context.point.formattedY }}</span>\n </div>\n @if (context.point.formattedRadialMin && context.point.formattedRadialMax) {\n <div>\n Range:\n <span class=\"font-medium text-foreground\"\n >{{ context.point.formattedRadialMin }} \u2013 {{ context.point.formattedRadialMax }}</span\n >\n </div>\n }\n @if (context.point.isClamped) {\n <div class=\"text-[11px] text-amber-500 font-medium\">Visual indicator clamped</div>\n }\n </div>\n } @else if (context.point.seriesType === \"treemap\") {\n <div class=\"flex items-center gap-1.5 mb-1\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{\n context.point.hierarchy?.formattedLabel || context.point.formattedX || context.point.seriesName\n }}</span>\n </div>\n <div class=\"flex flex-col gap-0.5 text-xs text-muted-foreground\">\n @if (context.point.hierarchy?.formattedPath && context.point.hierarchy!.formattedPath.length > 1) {\n <div class=\"text-[11px] truncate max-w-[220px]\">\n {{ context.point.hierarchy!.formattedPath.join(\" / \") }}\n </div>\n }\n <div class=\"flex items-center gap-2\">\n <span\n >Value: <span class=\"font-medium text-foreground\">{{ context.point.formattedY }}</span></span\n >\n @if (\n context.point.hierarchy?.percentageOfRoot !== undefined &&\n context.point.hierarchy!.percentageOfRoot > 0\n ) {\n <span>\u00B7</span>\n <span>{{ (context.point.hierarchy!.percentageOfRoot * 100).toFixed(1) }}%</span>\n }\n </div>\n </div>\n } @else if (context.point.seriesType === \"funnel\") {\n <div class=\"flex items-center gap-1.5 mb-1\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{\n context.point.formattedCategory || context.point.formattedX || context.point.seriesName\n }}</span>\n </div>\n <div class=\"flex flex-col gap-0.5 text-xs text-muted-foreground\">\n <div>\n Value:\n <span class=\"font-medium text-foreground\">{{\n context.point.funnel?.formattedValue || context.point.formattedY\n }}</span>\n </div>\n @if (context.point.funnel?.formattedConversionRate) {\n <div>\n Conversion:\n <span class=\"font-medium text-foreground\">{{\n context.point.funnel!.formattedConversionRate\n }}</span>\n </div>\n }\n @if (context.point.funnel?.formattedOverallConversionRate) {\n <div>\n Overall:\n <span class=\"font-medium text-foreground\">{{\n context.point.funnel!.formattedOverallConversionRate\n }}</span>\n </div>\n }\n @if (context.point.funnel?.dropOff !== undefined && context.point.funnel!.dropOff > 0) {\n <div>\n Drop-off: <span class=\"font-medium text-foreground\">{{ context.point.funnel!.dropOff }}</span>\n </div>\n }\n </div>\n } @else if (context.point.seriesType === \"waterfall\") {\n <div class=\"flex items-center gap-1.5 mb-1\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{\n context.point.formattedCategory || context.point.formattedX || context.point.seriesName\n }}</span>\n </div>\n <div class=\"flex flex-col gap-0.5 text-xs text-muted-foreground\">\n @if (context.point.waterfall?.kind === \"change\") {\n <div>\n Change:\n <span class=\"font-medium text-foreground\">{{\n context.point.waterfall?.formattedDelta || context.point.formattedY\n }}</span>\n </div>\n @if (\n context.point.waterfall?.formattedCumulativeBefore &&\n context.point.waterfall?.formattedCumulativeAfter\n ) {\n <div>\n Running Total:\n <span class=\"font-medium text-foreground\"\n >{{ context.point.waterfall!.formattedCumulativeBefore }} \u2192\n {{ context.point.waterfall!.formattedCumulativeAfter }}</span\n >\n </div>\n } @else if (context.point.waterfall?.formattedCumulativeAfter) {\n <div>\n Running Total:\n <span class=\"font-medium text-foreground\">{{\n context.point.waterfall!.formattedCumulativeAfter\n }}</span>\n </div>\n }\n } @else {\n <div>\n Value: <span class=\"font-medium text-foreground\">{{ context.point.formattedY }}</span>\n </div>\n }\n </div>\n } @else if (context.shared) {\n <div class=\"mb-1 font-semibold text-foreground\">{{ context.point.formattedX }}</div>\n <div class=\"flex flex-col gap-1.5\">\n @for (pt of context.points; track pt.markId) {\n @if (pt.valueKind === \"ohlc\" || pt.seriesType === \"candlestick\" || pt.seriesType === \"ohlc\") {\n <div class=\"flex flex-col gap-0.5\">\n <div class=\"flex items-center justify-between gap-3\">\n <div class=\"flex items-center gap-1.5\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"pt.color\"></span>\n <span class=\"text-xs text-muted-foreground font-medium\">{{ pt.seriesName }}</span>\n </div>\n @if (pt.financialDirection; as dir) {\n <span\n class=\"text-[10px] font-medium px-1 py-0.2 rounded capitalize\"\n [style.background-color]=\"\n dir === 'rising'\n ? 'rgba(34, 197, 94, 0.15)'\n : dir === 'falling'\n ? 'rgba(239, 68, 68, 0.15)'\n : 'rgba(107, 114, 128, 0.15)'\n \"\n [style.color]=\"pt.color\">\n {{ dir }}\n </span>\n }\n </div>\n <div class=\"text-[11px] text-muted-foreground pl-3.5 flex items-center gap-1 flex-wrap\">\n <span\n >O:\n <span class=\"font-medium text-foreground\">{{\n pt.formattedOpen || pt.open\n }}</span></span\n >\n <span\n >H:\n <span class=\"font-medium text-foreground\">{{\n pt.formattedHigh || pt.high\n }}</span></span\n >\n <span\n >L:\n <span class=\"font-medium text-foreground\">{{\n pt.formattedLow || pt.low\n }}</span></span\n >\n <span\n >C:\n <span class=\"font-medium text-foreground\">{{\n pt.formattedClose || pt.close\n }}</span></span\n >\n @if (pt.formattedChange) {\n <span class=\"font-medium text-foreground\">({{ pt.formattedChange }})</span>\n }\n </div>\n </div>\n } @else if (pt.valueKind === \"range\") {\n <div class=\"flex items-center justify-between gap-3\">\n <div class=\"flex items-center gap-1.5\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"pt.color\"></span>\n <span class=\"text-muted-foreground\">{{ pt.seriesName }}</span>\n </div>\n <div class=\"flex items-center gap-1\">\n <span class=\"font-medium text-foreground\"\n >{{ pt.formattedFrom }} \u2013 {{ pt.formattedTo }}</span\n >\n </div>\n </div>\n } @else {\n <div class=\"flex items-center justify-between gap-3\">\n <div class=\"flex items-center gap-1.5\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"pt.color\"></span>\n <span class=\"text-muted-foreground\">{{ pt.seriesName }}</span>\n </div>\n <div class=\"flex items-center gap-1\">\n <span class=\"font-medium text-foreground\">{{ pt.formattedY }}</span>\n @if (pt.formattedStackPercentage) {\n <span class=\"text-xs text-muted-foreground\"\n >({{ pt.formattedStackPercentage }})</span\n >\n }\n @if (pt.formattedSize) {\n <span class=\"text-xs text-muted-foreground\">({{ pt.formattedSize }})</span>\n }\n </div>\n </div>\n }\n }\n </div>\n } @else if (\n context.point.seriesType === \"candlestick\" ||\n context.point.seriesType === \"ohlc\" ||\n context.point.valueKind === \"ohlc\"\n ) {\n <div class=\"flex items-center justify-between gap-2 mb-1\">\n <div class=\"flex items-center gap-1.5\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{ context.point.seriesName }}</span>\n </div>\n @if (context.point.financialDirection; as dir) {\n <span\n class=\"text-[10px] font-medium px-1 py-0.5 rounded capitalize\"\n [style.background-color]=\"\n dir === 'rising'\n ? 'rgba(34, 197, 94, 0.15)'\n : dir === 'falling'\n ? 'rgba(239, 68, 68, 0.15)'\n : 'rgba(107, 114, 128, 0.15)'\n \"\n [style.color]=\"context.point.color\">\n {{ dir }}\n </span>\n }\n </div>\n <div class=\"text-xs text-muted-foreground mb-1.5\">\n <span class=\"font-medium text-foreground\">{{ context.point.formattedX }}</span>\n </div>\n <div class=\"grid grid-cols-2 gap-x-3 gap-y-0.5 text-xs\">\n <div class=\"flex items-center justify-between gap-1.5\">\n <span class=\"text-muted-foreground\">Open:</span>\n <span class=\"font-medium text-foreground\">{{\n context.point.formattedOpen || context.point.open\n }}</span>\n </div>\n <div class=\"flex items-center justify-between gap-1.5\">\n <span class=\"text-muted-foreground\">High:</span>\n <span class=\"font-medium text-foreground\">{{\n context.point.formattedHigh || context.point.high\n }}</span>\n </div>\n <div class=\"flex items-center justify-between gap-1.5\">\n <span class=\"text-muted-foreground\">Low:</span>\n <span class=\"font-medium text-foreground\">{{\n context.point.formattedLow || context.point.low\n }}</span>\n </div>\n <div class=\"flex items-center justify-between gap-1.5\">\n <span class=\"text-muted-foreground\">Close:</span>\n <span class=\"font-medium text-foreground\">{{\n context.point.formattedClose || context.point.close\n }}</span>\n </div>\n </div>\n @if (context.point.formattedChange || context.point.change !== undefined) {\n <div class=\"mt-1 pt-1 border-t border-border/50 flex items-center justify-between text-xs\">\n <span class=\"text-muted-foreground\">Change:</span>\n <span class=\"font-medium text-foreground\">\n {{ context.point.formattedChange || context.point.change }}\n @if (context.point.formattedChangePercentage) {\n <span>({{ context.point.formattedChangePercentage }})</span>\n }\n </span>\n </div>\n }\n } @else {\n <div class=\"flex items-center gap-1.5 mb-0.5\">\n <span class=\"inline-block h-2 w-2 rounded-full\" [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{ context.point.seriesName }}</span>\n </div>\n <div class=\"text-muted-foreground\">\n {{ context.point.formattedX }}:\n <span class=\"font-medium text-foreground\">{{ context.point.formattedY }}</span>\n @if (context.point.formattedStackPercentage) {\n <span>\u00B7</span>\n <span class=\"font-medium text-foreground\">{{ context.point.formattedStackPercentage }}</span>\n }\n @if (context.point.formattedSize) {\n <span class=\"ml-1.5\"\n >(size: <span class=\"font-medium text-foreground\">{{ context.point.formattedSize }}</span\n >)</span\n >\n }\n </div>\n }\n </div>\n}\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] }); }
59832
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: ChartTooltipComponent, isStandalone: true, selector: "mona-chart-tooltip", inputs: { enabled: { classPropertyName: "enabled", publicName: "enabled", isSignal: true, isRequired: false, transformFunction: null }, shared: { classPropertyName: "shared", publicName: "shared", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "contents" }, queries: [{ propertyName: "customTemplate", first: true, predicate: ChartTooltipTemplateDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "tooltipContainer", first: true, predicate: ["tooltipContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (enabled() && tooltipContext(); as context) {\n <div\n #tooltipContainer\n [class]=\"tooltipClasses()\"\n [style.left.px]=\"placement().left\"\n [style.top.px]=\"placement().top\"\n [attr.data-placement]=\"placement().placement\">\n @if (customTemplate(); as template) {\n <ng-container [ngTemplateOutlet]=\"template.templateRef\" [ngTemplateOutletContext]=\"context\" />\n } @else if (context.point.seriesType === \"heatmap\") {\n <div class=\"flex items-center gap-1.5 mb-1\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{ context.point.seriesName }}</span>\n </div>\n <div class=\"flex flex-col gap-0.5 text-xs text-muted-foreground\">\n <div>\n <span class=\"font-medium text-foreground\">{{ context.point.formattedX }}</span\n >,\n <span class=\"font-medium text-foreground\">{{\n context.point.formattedYCategory || context.point.categoryY\n }}</span>\n </div>\n <div>\n {{ messages().value }}{{ messages().labelValueSeparator }} <span class=\"font-medium text-foreground\">{{ context.point.formattedY }}</span>\n </div>\n </div>\n } @else if (context.point.seriesType === \"pie\" || context.point.seriesType === \"donut\") {\n <div class=\"flex items-center gap-1.5 mb-1\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{\n context.point.formattedCategory || context.point.seriesName\n }}</span>\n </div>\n <div class=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span class=\"font-medium text-foreground\">{{ context.point.formattedY }}</span>\n @if (context.point.formattedPercentage) {\n <span>\u00B7</span>\n <span>{{ context.point.formattedPercentage }}</span>\n }\n </div>\n } @else if (context.point.seriesType === \"gauge\") {\n <div class=\"flex items-center gap-1.5 mb-1\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{ context.point.seriesName }}</span>\n </div>\n <div class=\"flex flex-col gap-0.5 text-xs text-muted-foreground\">\n <div>\n {{ messages().value }}{{ messages().labelValueSeparator }} <span class=\"font-medium text-foreground\">{{ context.point.formattedY }}</span>\n </div>\n @if (context.point.formattedRadialMin && context.point.formattedRadialMax) {\n <div>\n {{ messages().range }}{{ messages().labelValueSeparator }}\n <span class=\"font-medium text-foreground\"\n >{{ context.point.formattedRadialMin }} \u2013 {{ context.point.formattedRadialMax }}</span\n >\n </div>\n }\n @if (context.point.isClamped) {\n <div class=\"text-[11px] text-amber-500 font-medium\">{{ messages().visualIndicatorClamped }}</div>\n }\n </div>\n } @else if (context.point.seriesType === \"treemap\") {\n <div class=\"flex items-center gap-1.5 mb-1\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{\n context.point.hierarchy?.formattedLabel || context.point.formattedX || context.point.seriesName\n }}</span>\n </div>\n <div class=\"flex flex-col gap-0.5 text-xs text-muted-foreground\">\n @if (context.point.hierarchy?.formattedPath && context.point.hierarchy!.formattedPath.length > 1) {\n <div class=\"text-[11px] truncate max-w-[220px]\">\n {{ context.point.hierarchy!.formattedPath.join(\" / \") }}\n </div>\n }\n <div class=\"flex items-center gap-2\">\n <span\n >{{ messages().value }}{{ messages().labelValueSeparator }} <span class=\"font-medium text-foreground\">{{ context.point.formattedY }}</span></span\n >\n @if (\n context.point.hierarchy?.percentageOfRoot !== undefined &&\n context.point.hierarchy!.percentageOfRoot > 0\n ) {\n <span>\u00B7</span>\n <span>{{ formatPercent(context.point.hierarchy!.percentageOfRoot) }}</span>\n }\n </div>\n </div>\n } @else if (context.point.seriesType === \"funnel\") {\n <div class=\"flex items-center gap-1.5 mb-1\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{\n context.point.formattedCategory || context.point.formattedX || context.point.seriesName\n }}</span>\n </div>\n <div class=\"flex flex-col gap-0.5 text-xs text-muted-foreground\">\n <div>\n {{ messages().value }}{{ messages().labelValueSeparator }}\n <span class=\"font-medium text-foreground\">{{\n context.point.funnel?.formattedValue || context.point.formattedY\n }}</span>\n </div>\n @if (context.point.funnel?.formattedConversionRate) {\n <div>\n {{ messages().conversion }}{{ messages().labelValueSeparator }}\n <span class=\"font-medium text-foreground\">{{\n context.point.funnel!.formattedConversionRate\n }}</span>\n </div>\n }\n @if (context.point.funnel?.formattedOverallConversionRate) {\n <div>\n {{ messages().overall }}{{ messages().labelValueSeparator }}\n <span class=\"font-medium text-foreground\">{{\n context.point.funnel!.formattedOverallConversionRate\n }}</span>\n </div>\n }\n @if (context.point.funnel?.dropOff !== undefined && context.point.funnel!.dropOff > 0) {\n <div>\n {{ messages().dropOff }}{{ messages().labelValueSeparator }} <span class=\"font-medium text-foreground\">{{ context.point.funnel!.dropOff }}</span>\n </div>\n }\n </div>\n } @else if (context.point.seriesType === \"waterfall\") {\n <div class=\"flex items-center gap-1.5 mb-1\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{\n context.point.formattedCategory || context.point.formattedX || context.point.seriesName\n }}</span>\n </div>\n <div class=\"flex flex-col gap-0.5 text-xs text-muted-foreground\">\n @if (context.point.waterfall?.kind === \"change\") {\n <div>\n {{ messages().change }}{{ messages().labelValueSeparator }}\n <span class=\"font-medium text-foreground\">{{\n context.point.waterfall?.formattedDelta || context.point.formattedY\n }}</span>\n </div>\n @if (\n context.point.waterfall?.formattedCumulativeBefore &&\n context.point.waterfall?.formattedCumulativeAfter\n ) {\n <div>\n {{ messages().runningTotal }}{{ messages().labelValueSeparator }}\n <span class=\"font-medium text-foreground\"\n >{{ context.point.waterfall!.formattedCumulativeBefore }} \u2192\n {{ context.point.waterfall!.formattedCumulativeAfter }}</span\n >\n </div>\n } @else if (context.point.waterfall?.formattedCumulativeAfter) {\n <div>\n {{ messages().runningTotal }}{{ messages().labelValueSeparator }}\n <span class=\"font-medium text-foreground\">{{\n context.point.waterfall!.formattedCumulativeAfter\n }}</span>\n </div>\n }\n } @else {\n <div>\n {{ messages().value }}{{ messages().labelValueSeparator }} <span class=\"font-medium text-foreground\">{{ context.point.formattedY }}</span>\n </div>\n }\n </div>\n } @else if (context.shared) {\n <div class=\"mb-1 font-semibold text-foreground\">{{ context.point.formattedX }}</div>\n <div class=\"flex flex-col gap-1.5\">\n @for (pt of context.points; track pt.markId) {\n @if (pt.valueKind === \"ohlc\" || pt.seriesType === \"candlestick\" || pt.seriesType === \"ohlc\") {\n <div class=\"flex flex-col gap-0.5\">\n <div class=\"flex items-center justify-between gap-3\">\n <div class=\"flex items-center gap-1.5\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"pt.color\"></span>\n <span class=\"text-xs text-muted-foreground font-medium\">{{ pt.seriesName }}</span>\n </div>\n @if (pt.financialDirection; as dir) {\n <span\n class=\"text-[10px] font-medium px-1 py-0.2 rounded\"\n [style.background-color]=\"\n dir === 'rising'\n ? 'rgba(34, 197, 94, 0.15)'\n : dir === 'falling'\n ? 'rgba(239, 68, 68, 0.15)'\n : 'rgba(107, 114, 128, 0.15)'\n \"\n [style.color]=\"pt.color\">\n {{ financialDirectionLabel(dir) }}\n </span>\n }\n </div>\n <div class=\"text-[11px] text-muted-foreground ps-3.5 flex items-center gap-1 flex-wrap\">\n <span\n >{{ messages().openAbbreviation }}{{ messages().labelValueSeparator }}\n <span class=\"font-medium text-foreground\">{{\n pt.formattedOpen || pt.open\n }}</span></span\n >\n <span\n >{{ messages().highAbbreviation }}{{ messages().labelValueSeparator }}\n <span class=\"font-medium text-foreground\">{{\n pt.formattedHigh || pt.high\n }}</span></span\n >\n <span\n >{{ messages().lowAbbreviation }}{{ messages().labelValueSeparator }}\n <span class=\"font-medium text-foreground\">{{\n pt.formattedLow || pt.low\n }}</span></span\n >\n <span\n >{{ messages().closeAbbreviation }}{{ messages().labelValueSeparator }}\n <span class=\"font-medium text-foreground\">{{\n pt.formattedClose || pt.close\n }}</span></span\n >\n @if (pt.formattedChange) {\n <span class=\"font-medium text-foreground\">({{ pt.formattedChange }})</span>\n }\n </div>\n </div>\n } @else if (pt.valueKind === \"range\") {\n <div class=\"flex items-center justify-between gap-3\">\n <div class=\"flex items-center gap-1.5\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"pt.color\"></span>\n <span class=\"text-muted-foreground\">{{ pt.seriesName }}</span>\n </div>\n <div class=\"flex items-center gap-1\">\n <span class=\"font-medium text-foreground\"\n >{{ pt.formattedFrom }} \u2013 {{ pt.formattedTo }}</span\n >\n </div>\n </div>\n } @else {\n <div class=\"flex items-center justify-between gap-3\">\n <div class=\"flex items-center gap-1.5\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"pt.color\"></span>\n <span class=\"text-muted-foreground\">{{ pt.seriesName }}</span>\n </div>\n <div class=\"flex items-center gap-1\">\n <span class=\"font-medium text-foreground\">{{ pt.formattedY }}</span>\n @if (pt.formattedStackPercentage) {\n <span class=\"text-xs text-muted-foreground\"\n >({{ pt.formattedStackPercentage }})</span\n >\n }\n @if (pt.formattedSize) {\n <span class=\"text-xs text-muted-foreground\">({{ pt.formattedSize }})</span>\n }\n </div>\n </div>\n }\n }\n </div>\n } @else if (\n context.point.seriesType === \"candlestick\" ||\n context.point.seriesType === \"ohlc\" ||\n context.point.valueKind === \"ohlc\"\n ) {\n <div class=\"flex items-center justify-between gap-2 mb-1\">\n <div class=\"flex items-center gap-1.5\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{ context.point.seriesName }}</span>\n </div>\n @if (context.point.financialDirection; as dir) {\n <span\n class=\"text-[10px] font-medium px-1 py-0.5 rounded\"\n [style.background-color]=\"\n dir === 'rising'\n ? 'rgba(34, 197, 94, 0.15)'\n : dir === 'falling'\n ? 'rgba(239, 68, 68, 0.15)'\n : 'rgba(107, 114, 128, 0.15)'\n \"\n [style.color]=\"context.point.color\">\n {{ financialDirectionLabel(dir) }}\n </span>\n }\n </div>\n <div class=\"text-xs text-muted-foreground mb-1.5\">\n <span class=\"font-medium text-foreground\">{{ context.point.formattedX }}</span>\n </div>\n <div class=\"grid grid-cols-2 gap-x-3 gap-y-0.5 text-xs\">\n <div class=\"flex items-center justify-between gap-1.5\">\n <span class=\"text-muted-foreground\">{{ messages().open }}{{ messages().labelValueSeparator }}</span>\n <span class=\"font-medium text-foreground\">{{\n context.point.formattedOpen || context.point.open\n }}</span>\n </div>\n <div class=\"flex items-center justify-between gap-1.5\">\n <span class=\"text-muted-foreground\">{{ messages().high }}{{ messages().labelValueSeparator }}</span>\n <span class=\"font-medium text-foreground\">{{\n context.point.formattedHigh || context.point.high\n }}</span>\n </div>\n <div class=\"flex items-center justify-between gap-1.5\">\n <span class=\"text-muted-foreground\">{{ messages().low }}{{ messages().labelValueSeparator }}</span>\n <span class=\"font-medium text-foreground\">{{\n context.point.formattedLow || context.point.low\n }}</span>\n </div>\n <div class=\"flex items-center justify-between gap-1.5\">\n <span class=\"text-muted-foreground\">{{ messages().close }}{{ messages().labelValueSeparator }}</span>\n <span class=\"font-medium text-foreground\">{{\n context.point.formattedClose || context.point.close\n }}</span>\n </div>\n </div>\n @if (context.point.formattedChange || context.point.change !== undefined) {\n <div class=\"mt-1 pt-1 border-t border-border/50 flex items-center justify-between text-xs\">\n <span class=\"text-muted-foreground\">{{ messages().change }}{{ messages().labelValueSeparator }}</span>\n <span class=\"font-medium text-foreground\">\n {{ context.point.formattedChange || context.point.change }}\n @if (context.point.formattedChangePercentage) {\n <span>({{ context.point.formattedChangePercentage }})</span>\n }\n </span>\n </div>\n }\n } @else {\n <div class=\"flex items-center gap-1.5 mb-0.5\">\n <span class=\"inline-block h-2 w-2 rounded-full\" [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{ context.point.seriesName }}</span>\n </div>\n <div class=\"text-muted-foreground\">\n {{ context.point.formattedX }}{{ messages().labelValueSeparator }}\n <span class=\"font-medium text-foreground\">{{ context.point.formattedY }}</span>\n @if (context.point.formattedStackPercentage) {\n <span>\u00B7</span>\n <span class=\"font-medium text-foreground\">{{ context.point.formattedStackPercentage }}</span>\n }\n @if (context.point.formattedSize) {\n <span class=\"ms-1.5\"\n >({{ messages().size }}{{ messages().labelValueSeparator }} <span class=\"font-medium text-foreground\">{{ context.point.formattedSize }}</span>)</span>\n }\n </div>\n }\n </div>\n}\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] }); }
59773
59833
  }
59774
59834
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ChartTooltipComponent, decorators: [{
59775
59835
  type: Component,
59776
59836
  args: [{ selector: "mona-chart-tooltip", imports: [NgTemplateOutlet], host: {
59777
59837
  class: "contents"
59778
- }, template: "@if (enabled() && tooltipContext(); as context) {\n <div\n #tooltipContainer\n [class]=\"tooltipClasses()\"\n [style.left.px]=\"placement().left\"\n [style.top.px]=\"placement().top\"\n [attr.data-placement]=\"placement().placement\">\n @if (customTemplate(); as template) {\n <ng-container [ngTemplateOutlet]=\"template.templateRef\" [ngTemplateOutletContext]=\"context\" />\n } @else if (context.point.seriesType === \"heatmap\") {\n <div class=\"flex items-center gap-1.5 mb-1\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{ context.point.seriesName }}</span>\n </div>\n <div class=\"flex flex-col gap-0.5 text-xs text-muted-foreground\">\n <div>\n <span class=\"font-medium text-foreground\">{{ context.point.formattedX }}</span\n >,\n <span class=\"font-medium text-foreground\">{{\n context.point.formattedYCategory || context.point.categoryY\n }}</span>\n </div>\n <div>\n Value: <span class=\"font-medium text-foreground\">{{ context.point.formattedY }}</span>\n </div>\n </div>\n } @else if (context.point.seriesType === \"pie\" || context.point.seriesType === \"donut\") {\n <div class=\"flex items-center gap-1.5 mb-1\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{\n context.point.formattedCategory || context.point.seriesName\n }}</span>\n </div>\n <div class=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span class=\"font-medium text-foreground\">{{ context.point.formattedY }}</span>\n @if (context.point.formattedPercentage) {\n <span>\u00B7</span>\n <span>{{ context.point.formattedPercentage }}</span>\n }\n </div>\n } @else if (context.point.seriesType === \"gauge\") {\n <div class=\"flex items-center gap-1.5 mb-1\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{ context.point.seriesName }}</span>\n </div>\n <div class=\"flex flex-col gap-0.5 text-xs text-muted-foreground\">\n <div>\n Value: <span class=\"font-medium text-foreground\">{{ context.point.formattedY }}</span>\n </div>\n @if (context.point.formattedRadialMin && context.point.formattedRadialMax) {\n <div>\n Range:\n <span class=\"font-medium text-foreground\"\n >{{ context.point.formattedRadialMin }} \u2013 {{ context.point.formattedRadialMax }}</span\n >\n </div>\n }\n @if (context.point.isClamped) {\n <div class=\"text-[11px] text-amber-500 font-medium\">Visual indicator clamped</div>\n }\n </div>\n } @else if (context.point.seriesType === \"treemap\") {\n <div class=\"flex items-center gap-1.5 mb-1\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{\n context.point.hierarchy?.formattedLabel || context.point.formattedX || context.point.seriesName\n }}</span>\n </div>\n <div class=\"flex flex-col gap-0.5 text-xs text-muted-foreground\">\n @if (context.point.hierarchy?.formattedPath && context.point.hierarchy!.formattedPath.length > 1) {\n <div class=\"text-[11px] truncate max-w-[220px]\">\n {{ context.point.hierarchy!.formattedPath.join(\" / \") }}\n </div>\n }\n <div class=\"flex items-center gap-2\">\n <span\n >Value: <span class=\"font-medium text-foreground\">{{ context.point.formattedY }}</span></span\n >\n @if (\n context.point.hierarchy?.percentageOfRoot !== undefined &&\n context.point.hierarchy!.percentageOfRoot > 0\n ) {\n <span>\u00B7</span>\n <span>{{ (context.point.hierarchy!.percentageOfRoot * 100).toFixed(1) }}%</span>\n }\n </div>\n </div>\n } @else if (context.point.seriesType === \"funnel\") {\n <div class=\"flex items-center gap-1.5 mb-1\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{\n context.point.formattedCategory || context.point.formattedX || context.point.seriesName\n }}</span>\n </div>\n <div class=\"flex flex-col gap-0.5 text-xs text-muted-foreground\">\n <div>\n Value:\n <span class=\"font-medium text-foreground\">{{\n context.point.funnel?.formattedValue || context.point.formattedY\n }}</span>\n </div>\n @if (context.point.funnel?.formattedConversionRate) {\n <div>\n Conversion:\n <span class=\"font-medium text-foreground\">{{\n context.point.funnel!.formattedConversionRate\n }}</span>\n </div>\n }\n @if (context.point.funnel?.formattedOverallConversionRate) {\n <div>\n Overall:\n <span class=\"font-medium text-foreground\">{{\n context.point.funnel!.formattedOverallConversionRate\n }}</span>\n </div>\n }\n @if (context.point.funnel?.dropOff !== undefined && context.point.funnel!.dropOff > 0) {\n <div>\n Drop-off: <span class=\"font-medium text-foreground\">{{ context.point.funnel!.dropOff }}</span>\n </div>\n }\n </div>\n } @else if (context.point.seriesType === \"waterfall\") {\n <div class=\"flex items-center gap-1.5 mb-1\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{\n context.point.formattedCategory || context.point.formattedX || context.point.seriesName\n }}</span>\n </div>\n <div class=\"flex flex-col gap-0.5 text-xs text-muted-foreground\">\n @if (context.point.waterfall?.kind === \"change\") {\n <div>\n Change:\n <span class=\"font-medium text-foreground\">{{\n context.point.waterfall?.formattedDelta || context.point.formattedY\n }}</span>\n </div>\n @if (\n context.point.waterfall?.formattedCumulativeBefore &&\n context.point.waterfall?.formattedCumulativeAfter\n ) {\n <div>\n Running Total:\n <span class=\"font-medium text-foreground\"\n >{{ context.point.waterfall!.formattedCumulativeBefore }} \u2192\n {{ context.point.waterfall!.formattedCumulativeAfter }}</span\n >\n </div>\n } @else if (context.point.waterfall?.formattedCumulativeAfter) {\n <div>\n Running Total:\n <span class=\"font-medium text-foreground\">{{\n context.point.waterfall!.formattedCumulativeAfter\n }}</span>\n </div>\n }\n } @else {\n <div>\n Value: <span class=\"font-medium text-foreground\">{{ context.point.formattedY }}</span>\n </div>\n }\n </div>\n } @else if (context.shared) {\n <div class=\"mb-1 font-semibold text-foreground\">{{ context.point.formattedX }}</div>\n <div class=\"flex flex-col gap-1.5\">\n @for (pt of context.points; track pt.markId) {\n @if (pt.valueKind === \"ohlc\" || pt.seriesType === \"candlestick\" || pt.seriesType === \"ohlc\") {\n <div class=\"flex flex-col gap-0.5\">\n <div class=\"flex items-center justify-between gap-3\">\n <div class=\"flex items-center gap-1.5\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"pt.color\"></span>\n <span class=\"text-xs text-muted-foreground font-medium\">{{ pt.seriesName }}</span>\n </div>\n @if (pt.financialDirection; as dir) {\n <span\n class=\"text-[10px] font-medium px-1 py-0.2 rounded capitalize\"\n [style.background-color]=\"\n dir === 'rising'\n ? 'rgba(34, 197, 94, 0.15)'\n : dir === 'falling'\n ? 'rgba(239, 68, 68, 0.15)'\n : 'rgba(107, 114, 128, 0.15)'\n \"\n [style.color]=\"pt.color\">\n {{ dir }}\n </span>\n }\n </div>\n <div class=\"text-[11px] text-muted-foreground pl-3.5 flex items-center gap-1 flex-wrap\">\n <span\n >O:\n <span class=\"font-medium text-foreground\">{{\n pt.formattedOpen || pt.open\n }}</span></span\n >\n <span\n >H:\n <span class=\"font-medium text-foreground\">{{\n pt.formattedHigh || pt.high\n }}</span></span\n >\n <span\n >L:\n <span class=\"font-medium text-foreground\">{{\n pt.formattedLow || pt.low\n }}</span></span\n >\n <span\n >C:\n <span class=\"font-medium text-foreground\">{{\n pt.formattedClose || pt.close\n }}</span></span\n >\n @if (pt.formattedChange) {\n <span class=\"font-medium text-foreground\">({{ pt.formattedChange }})</span>\n }\n </div>\n </div>\n } @else if (pt.valueKind === \"range\") {\n <div class=\"flex items-center justify-between gap-3\">\n <div class=\"flex items-center gap-1.5\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"pt.color\"></span>\n <span class=\"text-muted-foreground\">{{ pt.seriesName }}</span>\n </div>\n <div class=\"flex items-center gap-1\">\n <span class=\"font-medium text-foreground\"\n >{{ pt.formattedFrom }} \u2013 {{ pt.formattedTo }}</span\n >\n </div>\n </div>\n } @else {\n <div class=\"flex items-center justify-between gap-3\">\n <div class=\"flex items-center gap-1.5\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"pt.color\"></span>\n <span class=\"text-muted-foreground\">{{ pt.seriesName }}</span>\n </div>\n <div class=\"flex items-center gap-1\">\n <span class=\"font-medium text-foreground\">{{ pt.formattedY }}</span>\n @if (pt.formattedStackPercentage) {\n <span class=\"text-xs text-muted-foreground\"\n >({{ pt.formattedStackPercentage }})</span\n >\n }\n @if (pt.formattedSize) {\n <span class=\"text-xs text-muted-foreground\">({{ pt.formattedSize }})</span>\n }\n </div>\n </div>\n }\n }\n </div>\n } @else if (\n context.point.seriesType === \"candlestick\" ||\n context.point.seriesType === \"ohlc\" ||\n context.point.valueKind === \"ohlc\"\n ) {\n <div class=\"flex items-center justify-between gap-2 mb-1\">\n <div class=\"flex items-center gap-1.5\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{ context.point.seriesName }}</span>\n </div>\n @if (context.point.financialDirection; as dir) {\n <span\n class=\"text-[10px] font-medium px-1 py-0.5 rounded capitalize\"\n [style.background-color]=\"\n dir === 'rising'\n ? 'rgba(34, 197, 94, 0.15)'\n : dir === 'falling'\n ? 'rgba(239, 68, 68, 0.15)'\n : 'rgba(107, 114, 128, 0.15)'\n \"\n [style.color]=\"context.point.color\">\n {{ dir }}\n </span>\n }\n </div>\n <div class=\"text-xs text-muted-foreground mb-1.5\">\n <span class=\"font-medium text-foreground\">{{ context.point.formattedX }}</span>\n </div>\n <div class=\"grid grid-cols-2 gap-x-3 gap-y-0.5 text-xs\">\n <div class=\"flex items-center justify-between gap-1.5\">\n <span class=\"text-muted-foreground\">Open:</span>\n <span class=\"font-medium text-foreground\">{{\n context.point.formattedOpen || context.point.open\n }}</span>\n </div>\n <div class=\"flex items-center justify-between gap-1.5\">\n <span class=\"text-muted-foreground\">High:</span>\n <span class=\"font-medium text-foreground\">{{\n context.point.formattedHigh || context.point.high\n }}</span>\n </div>\n <div class=\"flex items-center justify-between gap-1.5\">\n <span class=\"text-muted-foreground\">Low:</span>\n <span class=\"font-medium text-foreground\">{{\n context.point.formattedLow || context.point.low\n }}</span>\n </div>\n <div class=\"flex items-center justify-between gap-1.5\">\n <span class=\"text-muted-foreground\">Close:</span>\n <span class=\"font-medium text-foreground\">{{\n context.point.formattedClose || context.point.close\n }}</span>\n </div>\n </div>\n @if (context.point.formattedChange || context.point.change !== undefined) {\n <div class=\"mt-1 pt-1 border-t border-border/50 flex items-center justify-between text-xs\">\n <span class=\"text-muted-foreground\">Change:</span>\n <span class=\"font-medium text-foreground\">\n {{ context.point.formattedChange || context.point.change }}\n @if (context.point.formattedChangePercentage) {\n <span>({{ context.point.formattedChangePercentage }})</span>\n }\n </span>\n </div>\n }\n } @else {\n <div class=\"flex items-center gap-1.5 mb-0.5\">\n <span class=\"inline-block h-2 w-2 rounded-full\" [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{ context.point.seriesName }}</span>\n </div>\n <div class=\"text-muted-foreground\">\n {{ context.point.formattedX }}:\n <span class=\"font-medium text-foreground\">{{ context.point.formattedY }}</span>\n @if (context.point.formattedStackPercentage) {\n <span>\u00B7</span>\n <span class=\"font-medium text-foreground\">{{ context.point.formattedStackPercentage }}</span>\n }\n @if (context.point.formattedSize) {\n <span class=\"ml-1.5\"\n >(size: <span class=\"font-medium text-foreground\">{{ context.point.formattedSize }}</span\n >)</span\n >\n }\n </div>\n }\n </div>\n}\n" }]
59838
+ }, template: "@if (enabled() && tooltipContext(); as context) {\n <div\n #tooltipContainer\n [class]=\"tooltipClasses()\"\n [style.left.px]=\"placement().left\"\n [style.top.px]=\"placement().top\"\n [attr.data-placement]=\"placement().placement\">\n @if (customTemplate(); as template) {\n <ng-container [ngTemplateOutlet]=\"template.templateRef\" [ngTemplateOutletContext]=\"context\" />\n } @else if (context.point.seriesType === \"heatmap\") {\n <div class=\"flex items-center gap-1.5 mb-1\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{ context.point.seriesName }}</span>\n </div>\n <div class=\"flex flex-col gap-0.5 text-xs text-muted-foreground\">\n <div>\n <span class=\"font-medium text-foreground\">{{ context.point.formattedX }}</span\n >,\n <span class=\"font-medium text-foreground\">{{\n context.point.formattedYCategory || context.point.categoryY\n }}</span>\n </div>\n <div>\n {{ messages().value }}{{ messages().labelValueSeparator }} <span class=\"font-medium text-foreground\">{{ context.point.formattedY }}</span>\n </div>\n </div>\n } @else if (context.point.seriesType === \"pie\" || context.point.seriesType === \"donut\") {\n <div class=\"flex items-center gap-1.5 mb-1\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{\n context.point.formattedCategory || context.point.seriesName\n }}</span>\n </div>\n <div class=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span class=\"font-medium text-foreground\">{{ context.point.formattedY }}</span>\n @if (context.point.formattedPercentage) {\n <span>\u00B7</span>\n <span>{{ context.point.formattedPercentage }}</span>\n }\n </div>\n } @else if (context.point.seriesType === \"gauge\") {\n <div class=\"flex items-center gap-1.5 mb-1\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{ context.point.seriesName }}</span>\n </div>\n <div class=\"flex flex-col gap-0.5 text-xs text-muted-foreground\">\n <div>\n {{ messages().value }}{{ messages().labelValueSeparator }} <span class=\"font-medium text-foreground\">{{ context.point.formattedY }}</span>\n </div>\n @if (context.point.formattedRadialMin && context.point.formattedRadialMax) {\n <div>\n {{ messages().range }}{{ messages().labelValueSeparator }}\n <span class=\"font-medium text-foreground\"\n >{{ context.point.formattedRadialMin }} \u2013 {{ context.point.formattedRadialMax }}</span\n >\n </div>\n }\n @if (context.point.isClamped) {\n <div class=\"text-[11px] text-amber-500 font-medium\">{{ messages().visualIndicatorClamped }}</div>\n }\n </div>\n } @else if (context.point.seriesType === \"treemap\") {\n <div class=\"flex items-center gap-1.5 mb-1\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{\n context.point.hierarchy?.formattedLabel || context.point.formattedX || context.point.seriesName\n }}</span>\n </div>\n <div class=\"flex flex-col gap-0.5 text-xs text-muted-foreground\">\n @if (context.point.hierarchy?.formattedPath && context.point.hierarchy!.formattedPath.length > 1) {\n <div class=\"text-[11px] truncate max-w-[220px]\">\n {{ context.point.hierarchy!.formattedPath.join(\" / \") }}\n </div>\n }\n <div class=\"flex items-center gap-2\">\n <span\n >{{ messages().value }}{{ messages().labelValueSeparator }} <span class=\"font-medium text-foreground\">{{ context.point.formattedY }}</span></span\n >\n @if (\n context.point.hierarchy?.percentageOfRoot !== undefined &&\n context.point.hierarchy!.percentageOfRoot > 0\n ) {\n <span>\u00B7</span>\n <span>{{ formatPercent(context.point.hierarchy!.percentageOfRoot) }}</span>\n }\n </div>\n </div>\n } @else if (context.point.seriesType === \"funnel\") {\n <div class=\"flex items-center gap-1.5 mb-1\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{\n context.point.formattedCategory || context.point.formattedX || context.point.seriesName\n }}</span>\n </div>\n <div class=\"flex flex-col gap-0.5 text-xs text-muted-foreground\">\n <div>\n {{ messages().value }}{{ messages().labelValueSeparator }}\n <span class=\"font-medium text-foreground\">{{\n context.point.funnel?.formattedValue || context.point.formattedY\n }}</span>\n </div>\n @if (context.point.funnel?.formattedConversionRate) {\n <div>\n {{ messages().conversion }}{{ messages().labelValueSeparator }}\n <span class=\"font-medium text-foreground\">{{\n context.point.funnel!.formattedConversionRate\n }}</span>\n </div>\n }\n @if (context.point.funnel?.formattedOverallConversionRate) {\n <div>\n {{ messages().overall }}{{ messages().labelValueSeparator }}\n <span class=\"font-medium text-foreground\">{{\n context.point.funnel!.formattedOverallConversionRate\n }}</span>\n </div>\n }\n @if (context.point.funnel?.dropOff !== undefined && context.point.funnel!.dropOff > 0) {\n <div>\n {{ messages().dropOff }}{{ messages().labelValueSeparator }} <span class=\"font-medium text-foreground\">{{ context.point.funnel!.dropOff }}</span>\n </div>\n }\n </div>\n } @else if (context.point.seriesType === \"waterfall\") {\n <div class=\"flex items-center gap-1.5 mb-1\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{\n context.point.formattedCategory || context.point.formattedX || context.point.seriesName\n }}</span>\n </div>\n <div class=\"flex flex-col gap-0.5 text-xs text-muted-foreground\">\n @if (context.point.waterfall?.kind === \"change\") {\n <div>\n {{ messages().change }}{{ messages().labelValueSeparator }}\n <span class=\"font-medium text-foreground\">{{\n context.point.waterfall?.formattedDelta || context.point.formattedY\n }}</span>\n </div>\n @if (\n context.point.waterfall?.formattedCumulativeBefore &&\n context.point.waterfall?.formattedCumulativeAfter\n ) {\n <div>\n {{ messages().runningTotal }}{{ messages().labelValueSeparator }}\n <span class=\"font-medium text-foreground\"\n >{{ context.point.waterfall!.formattedCumulativeBefore }} \u2192\n {{ context.point.waterfall!.formattedCumulativeAfter }}</span\n >\n </div>\n } @else if (context.point.waterfall?.formattedCumulativeAfter) {\n <div>\n {{ messages().runningTotal }}{{ messages().labelValueSeparator }}\n <span class=\"font-medium text-foreground\">{{\n context.point.waterfall!.formattedCumulativeAfter\n }}</span>\n </div>\n }\n } @else {\n <div>\n {{ messages().value }}{{ messages().labelValueSeparator }} <span class=\"font-medium text-foreground\">{{ context.point.formattedY }}</span>\n </div>\n }\n </div>\n } @else if (context.shared) {\n <div class=\"mb-1 font-semibold text-foreground\">{{ context.point.formattedX }}</div>\n <div class=\"flex flex-col gap-1.5\">\n @for (pt of context.points; track pt.markId) {\n @if (pt.valueKind === \"ohlc\" || pt.seriesType === \"candlestick\" || pt.seriesType === \"ohlc\") {\n <div class=\"flex flex-col gap-0.5\">\n <div class=\"flex items-center justify-between gap-3\">\n <div class=\"flex items-center gap-1.5\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"pt.color\"></span>\n <span class=\"text-xs text-muted-foreground font-medium\">{{ pt.seriesName }}</span>\n </div>\n @if (pt.financialDirection; as dir) {\n <span\n class=\"text-[10px] font-medium px-1 py-0.2 rounded\"\n [style.background-color]=\"\n dir === 'rising'\n ? 'rgba(34, 197, 94, 0.15)'\n : dir === 'falling'\n ? 'rgba(239, 68, 68, 0.15)'\n : 'rgba(107, 114, 128, 0.15)'\n \"\n [style.color]=\"pt.color\">\n {{ financialDirectionLabel(dir) }}\n </span>\n }\n </div>\n <div class=\"text-[11px] text-muted-foreground ps-3.5 flex items-center gap-1 flex-wrap\">\n <span\n >{{ messages().openAbbreviation }}{{ messages().labelValueSeparator }}\n <span class=\"font-medium text-foreground\">{{\n pt.formattedOpen || pt.open\n }}</span></span\n >\n <span\n >{{ messages().highAbbreviation }}{{ messages().labelValueSeparator }}\n <span class=\"font-medium text-foreground\">{{\n pt.formattedHigh || pt.high\n }}</span></span\n >\n <span\n >{{ messages().lowAbbreviation }}{{ messages().labelValueSeparator }}\n <span class=\"font-medium text-foreground\">{{\n pt.formattedLow || pt.low\n }}</span></span\n >\n <span\n >{{ messages().closeAbbreviation }}{{ messages().labelValueSeparator }}\n <span class=\"font-medium text-foreground\">{{\n pt.formattedClose || pt.close\n }}</span></span\n >\n @if (pt.formattedChange) {\n <span class=\"font-medium text-foreground\">({{ pt.formattedChange }})</span>\n }\n </div>\n </div>\n } @else if (pt.valueKind === \"range\") {\n <div class=\"flex items-center justify-between gap-3\">\n <div class=\"flex items-center gap-1.5\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"pt.color\"></span>\n <span class=\"text-muted-foreground\">{{ pt.seriesName }}</span>\n </div>\n <div class=\"flex items-center gap-1\">\n <span class=\"font-medium text-foreground\"\n >{{ pt.formattedFrom }} \u2013 {{ pt.formattedTo }}</span\n >\n </div>\n </div>\n } @else {\n <div class=\"flex items-center justify-between gap-3\">\n <div class=\"flex items-center gap-1.5\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"pt.color\"></span>\n <span class=\"text-muted-foreground\">{{ pt.seriesName }}</span>\n </div>\n <div class=\"flex items-center gap-1\">\n <span class=\"font-medium text-foreground\">{{ pt.formattedY }}</span>\n @if (pt.formattedStackPercentage) {\n <span class=\"text-xs text-muted-foreground\"\n >({{ pt.formattedStackPercentage }})</span\n >\n }\n @if (pt.formattedSize) {\n <span class=\"text-xs text-muted-foreground\">({{ pt.formattedSize }})</span>\n }\n </div>\n </div>\n }\n }\n </div>\n } @else if (\n context.point.seriesType === \"candlestick\" ||\n context.point.seriesType === \"ohlc\" ||\n context.point.valueKind === \"ohlc\"\n ) {\n <div class=\"flex items-center justify-between gap-2 mb-1\">\n <div class=\"flex items-center gap-1.5\">\n <span\n class=\"inline-block h-2 w-2 rounded-full flex-shrink-0\"\n [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{ context.point.seriesName }}</span>\n </div>\n @if (context.point.financialDirection; as dir) {\n <span\n class=\"text-[10px] font-medium px-1 py-0.5 rounded\"\n [style.background-color]=\"\n dir === 'rising'\n ? 'rgba(34, 197, 94, 0.15)'\n : dir === 'falling'\n ? 'rgba(239, 68, 68, 0.15)'\n : 'rgba(107, 114, 128, 0.15)'\n \"\n [style.color]=\"context.point.color\">\n {{ financialDirectionLabel(dir) }}\n </span>\n }\n </div>\n <div class=\"text-xs text-muted-foreground mb-1.5\">\n <span class=\"font-medium text-foreground\">{{ context.point.formattedX }}</span>\n </div>\n <div class=\"grid grid-cols-2 gap-x-3 gap-y-0.5 text-xs\">\n <div class=\"flex items-center justify-between gap-1.5\">\n <span class=\"text-muted-foreground\">{{ messages().open }}{{ messages().labelValueSeparator }}</span>\n <span class=\"font-medium text-foreground\">{{\n context.point.formattedOpen || context.point.open\n }}</span>\n </div>\n <div class=\"flex items-center justify-between gap-1.5\">\n <span class=\"text-muted-foreground\">{{ messages().high }}{{ messages().labelValueSeparator }}</span>\n <span class=\"font-medium text-foreground\">{{\n context.point.formattedHigh || context.point.high\n }}</span>\n </div>\n <div class=\"flex items-center justify-between gap-1.5\">\n <span class=\"text-muted-foreground\">{{ messages().low }}{{ messages().labelValueSeparator }}</span>\n <span class=\"font-medium text-foreground\">{{\n context.point.formattedLow || context.point.low\n }}</span>\n </div>\n <div class=\"flex items-center justify-between gap-1.5\">\n <span class=\"text-muted-foreground\">{{ messages().close }}{{ messages().labelValueSeparator }}</span>\n <span class=\"font-medium text-foreground\">{{\n context.point.formattedClose || context.point.close\n }}</span>\n </div>\n </div>\n @if (context.point.formattedChange || context.point.change !== undefined) {\n <div class=\"mt-1 pt-1 border-t border-border/50 flex items-center justify-between text-xs\">\n <span class=\"text-muted-foreground\">{{ messages().change }}{{ messages().labelValueSeparator }}</span>\n <span class=\"font-medium text-foreground\">\n {{ context.point.formattedChange || context.point.change }}\n @if (context.point.formattedChangePercentage) {\n <span>({{ context.point.formattedChangePercentage }})</span>\n }\n </span>\n </div>\n }\n } @else {\n <div class=\"flex items-center gap-1.5 mb-0.5\">\n <span class=\"inline-block h-2 w-2 rounded-full\" [style.background-color]=\"context.point.color\"></span>\n <span class=\"font-semibold text-foreground\">{{ context.point.seriesName }}</span>\n </div>\n <div class=\"text-muted-foreground\">\n {{ context.point.formattedX }}{{ messages().labelValueSeparator }}\n <span class=\"font-medium text-foreground\">{{ context.point.formattedY }}</span>\n @if (context.point.formattedStackPercentage) {\n <span>\u00B7</span>\n <span class=\"font-medium text-foreground\">{{ context.point.formattedStackPercentage }}</span>\n }\n @if (context.point.formattedSize) {\n <span class=\"ms-1.5\"\n >({{ messages().size }}{{ messages().labelValueSeparator }} <span class=\"font-medium text-foreground\">{{ context.point.formattedSize }}</span>)</span>\n }\n </div>\n }\n </div>\n}\n" }]
59779
59839
  }], ctorParameters: () => [], propDecorators: { customTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ChartTooltipTemplateDirective), { isSignal: true }] }], tooltipContainer: [{ type: i0.ViewChild, args: ["tooltipContainer", { isSignal: true }] }], enabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "enabled", required: false }] }], shared: [{ type: i0.Input, args: [{ isSignal: true, alias: "shared", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
59780
59840
 
59781
59841
  let nextSeriesId$6 = 0;
@@ -64420,5 +64480,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
64420
64480
  * Generated bundle index. Do not edit.
64421
64481
  */
64422
64482
 
64423
- export { AreaSeriesComponent, BarSeriesComponent, BubbleSeriesComponent, CandlestickSeriesComponent, ChartAngularAxisComponent, ChartAnnotationComponent, ChartAnnotationLabelTemplateDirective, ChartAxisLabelTemplateDirective, ChartBrushComponent, ChartCenterTemplateDirective, ChartComponent, ChartCrosshairComponent, ChartCrosshairLabelTemplateDirective, ChartDataLabelTemplateDirective, ChartExportError, ChartFunnelLabelTemplateDirective, ChartGaugeCenterTemplateDirective, ChartLegendComponent, ChartLegendItemTemplateDirective, ChartNoDataTemplateDirective, ChartRadialAxisComponent, ChartReferenceBandComponent, ChartReferenceLabelTemplateDirective, ChartReferenceLineComponent, ChartSelectionComponent, ChartSliceLabelTemplateDirective, ChartSubtitleTemplateDirective, ChartTitleTemplateDirective, ChartTooltipComponent, ChartTooltipTemplateDirective, ChartTreemapLabelTemplateDirective, ChartWaterfallLabelTemplateDirective, ChartXAxisComponent, ChartYAxisComponent, DonutSeriesComponent, FunnelSeriesComponent, GaugeSeriesComponent, HeatmapSeriesComponent, LineSeriesComponent, OhlcSeriesComponent, PieSeriesComponent, PolarSeriesComponent, RadarSeriesComponent, RadialBarSeriesComponent, RangeAreaSeriesComponent, RangeBarSeriesComponent, RoseSeriesComponent, ScatterSeriesComponent, TreemapSeriesComponent, WaterfallSeriesComponent, getChartSeriesFamily, isCartesianCoordinateFamily, isHierarchicalCoordinateFamily, isPolarCoordinateFamily };
64483
+ export { AreaSeriesComponent, BarSeriesComponent, BubbleSeriesComponent, CHART_DEFAULT_MESSAGES, CandlestickSeriesComponent, ChartAngularAxisComponent, ChartAnnotationComponent, ChartAnnotationLabelTemplateDirective, ChartAxisLabelTemplateDirective, ChartBrushComponent, ChartCenterTemplateDirective, ChartComponent, ChartCrosshairComponent, ChartCrosshairLabelTemplateDirective, ChartDataLabelTemplateDirective, ChartExportError, ChartFunnelLabelTemplateDirective, ChartGaugeCenterTemplateDirective, ChartLegendComponent, ChartLegendItemTemplateDirective, ChartNoDataTemplateDirective, ChartRadialAxisComponent, ChartReferenceBandComponent, ChartReferenceLabelTemplateDirective, ChartReferenceLineComponent, ChartSelectionComponent, ChartSliceLabelTemplateDirective, ChartSubtitleTemplateDirective, ChartTitleTemplateDirective, ChartTooltipComponent, ChartTooltipTemplateDirective, ChartTreemapLabelTemplateDirective, ChartWaterfallLabelTemplateDirective, ChartXAxisComponent, ChartYAxisComponent, DonutSeriesComponent, FunnelSeriesComponent, GaugeSeriesComponent, HeatmapSeriesComponent, LineSeriesComponent, OhlcSeriesComponent, PieSeriesComponent, PolarSeriesComponent, RadarSeriesComponent, RadialBarSeriesComponent, RangeAreaSeriesComponent, RangeBarSeriesComponent, RoseSeriesComponent, ScatterSeriesComponent, TreemapSeriesComponent, WaterfallSeriesComponent, getChartSeriesFamily, isCartesianCoordinateFamily, isHierarchicalCoordinateFamily, isPolarCoordinateFamily };
64424
64484
  //# sourceMappingURL=nanahoshi-mona-ui-chart.mjs.map