cats-charts 0.0.85 → 0.0.87

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.
@@ -446,11 +446,11 @@ class ChartLegendComponent {
446
446
  return typeof this.config.maxWidth === 'string' && this.config.maxWidth.trim().length > 0;
447
447
  }
448
448
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ChartLegendComponent, deps: [{ token: ChartLegendAdapter }, { token: i0.ChangeDetectorRef }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component });
449
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: ChartLegendComponent, isStandalone: true, selector: "lib-chart-legend", inputs: { chart: "chart", series: "series", colors: "colors", config: "config", itemTemplate: "itemTemplate" }, outputs: { legendEvent: "legendEvent" }, viewQueries: [{ propertyName: "itemsScroller", first: true, predicate: ["itemsScroller"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "@if (config.enabled !== false) {\r\n <nav\r\n class=\"chart-legend\"\r\n [class.chart-legend--vertical]=\"isVerticalLegend\"\r\n [class.chart-legend--scrollable]=\"isScrollableLegend\"\r\n [class.chart-legend--wrap]=\"!isScrollableLegend\"\r\n [class.chart-legend--limited-wrap]=\"isLimitedWrapLegend\"\r\n [ngClass]=\"config.className || null\"\r\n [style.max-height]=\"config.maxHeight || null\"\r\n [style.padding]=\"config.padding || '1rem'\"\r\n [attr.aria-label]=\"config.ariaLabel || 'Chart legend'\"\r\n >\r\n <div class=\"chart-legend__viewport\">\r\n @if (config.title) {\r\n <p\r\n class=\"chart-legend-title\"\r\n [class.chart-legend-title--uppercase]=\"config.legendTitleTransform === 'uppercase'\"\r\n [class.chart-legend-title--lowercase]=\"config.legendTitleTransform === 'lowercase'\"\r\n [class.chart-legend-title--capitalize]=\"config.legendTitleTransform === 'capitalize'\"\r\n [style.--legend-title-color]=\"config.legendTitleTextColor || null\"\r\n [style.--legend-title-font-size]=\"\r\n config.legendTitleFontSize ? config.legendTitleFontSize + 'px' : null\r\n \"\r\n [style.--legend-title-font-style]=\"config.legendTitleFontStyle || null\"\r\n [style.--legend-title-font-weight]=\"config.legendTitleFontWeight || null\"\r\n [style.--legend-title-text-decoration]=\"config.legendTitleTextDecoration || null\"\r\n [style.--legend-title-font-family]=\"config.legendTitleFontFamily || 'initial'\"\r\n >\r\n {{ config.title }}\r\n </p>\r\n }\r\n @if (usesInternalLegendScroll && canScrollLegend) {\r\n <button\r\n type=\"button\"\r\n class=\"chart-legend__scroll-button chart-legend__scroll-button--start\"\r\n [disabled]=\"!canScrollStart\"\r\n (click)=\"scrollLegend(-1, $event)\"\r\n [attr.aria-label]=\"scrollStartAriaLabel\"\r\n >\r\n <img\r\n src=\"images/legend_left.svg\"\r\n [class.chart-legend__scroll-icon--up]=\"scrollsVertically\"\r\n alt=\"left\"\r\n />\r\n </button>\r\n }\r\n\r\n <div #itemsScroller class=\"chart-legend__scroller\" (scroll)=\"updateScrollState()\">\r\n <div\r\n class=\"chart-legend__items\"\r\n role=\"list\"\r\n [class.chart-legend__items--center]=\"\r\n isLegendAlignedCenter && (!usesInternalLegendScroll || !canScrollLegend)\r\n \"\r\n [class.chart-legend__items--end]=\"isLegendAlignedEnd\"\r\n [style.--legend-text-color]=\"config.legendTextColor || null\"\r\n [style.--legend-font-size]=\"config.legendFontSize ? config.legendFontSize + 'px' : null\"\r\n [style.--legend-font-style]=\"config.legendFontStyle || null\"\r\n [style.--legend-font-weight]=\"config.legendFontWeight || null\"\r\n [style.--legend-text-decoration]=\"config.legendTextDecoration || null\"\r\n [style.--legend-font-family]=\"config.legendFontFamily || 'initial'\"\r\n >\r\n @for (group of groupedItems; track trackByGroup($index, group)) {\r\n @if (group.group) {\r\n <div class=\"chart-legend__group-label\">{{ group.group }}</div>\r\n }\r\n\r\n @for (item of group.items; track trackByItem($index, item)) {\r\n <button\r\n type=\"button\"\r\n class=\"chart-legend__item\"\r\n role=\"switch\"\r\n [class.chart-legend__item--off]=\"!item.selected\"\r\n [class.chart-legend__item--disabled]=\"item.disabled\"\r\n [class.chart-legend__item--hovered]=\"state.hoveredName === item.name\"\r\n [disabled]=\"item.disabled\"\r\n [attr.aria-checked]=\"item.selected\"\r\n [attr.aria-label]=\"item.label\"\r\n [style.--legend-item-color]=\"item.color\"\r\n [title]=\"itemTitle(item)\"\r\n (click)=\"toggle(item, $event)\"\r\n (keydown.enter)=\"toggle(item, $event)\"\r\n (keydown.space)=\"toggle(item, $event)\"\r\n (mouseenter)=\"hover(item)\"\r\n (focus)=\"hover(item)\"\r\n (mouseleave)=\"leave(item)\"\r\n (blur)=\"leave(item)\"\r\n >\r\n @if (templateFor(item); as template) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"template\"\r\n [ngTemplateOutletContext]=\"templateContext(item)\"\r\n ></ng-container>\r\n } @else {\r\n @switch (iconRenderType(item)) {\r\n @case ('image') {\r\n @if (isLineMarker(item)) {\r\n <span\r\n class=\"chart-legend__icon chart-legend__icon--line-marker\"\r\n aria-hidden=\"true\"\r\n >\r\n <span class=\"chart-legend__icon-line\"></span>\r\n <img class=\"chart-legend__icon-image\" [src]=\"iconImageSrc(item)\" alt=\"\" />\r\n <span class=\"chart-legend__icon-line\"></span>\r\n </span>\r\n } @else {\r\n <img class=\"chart-legend__icon-image\" [src]=\"iconImageSrc(item)\" alt=\"\" />\r\n }\r\n }\r\n @case ('path') {\r\n @if (isLineMarker(item)) {\r\n <span\r\n class=\"chart-legend__icon chart-legend__icon--line-marker\"\r\n aria-hidden=\"true\"\r\n >\r\n <span class=\"chart-legend__icon-line\"></span>\r\n <svg\r\n class=\"chart-legend__icon-path\"\r\n viewBox=\"-512 -512 1024 1024\"\r\n aria-hidden=\"true\"\r\n >\r\n <path [attr.d]=\"iconPathData(item)\"></path>\r\n </svg>\r\n <span class=\"chart-legend__icon-line\"></span>\r\n </span>\r\n } @else {\r\n <svg\r\n class=\"chart-legend__icon-path\"\r\n viewBox=\"-512 -512 1024 1024\"\r\n aria-hidden=\"true\"\r\n >\r\n <path [attr.d]=\"iconPathData(item)\"></path>\r\n </svg>\r\n }\r\n }\r\n @case ('shape') {\r\n @if (isLineMarker(item)) {\r\n <span\r\n class=\"chart-legend__icon chart-legend__icon--line-marker\"\r\n aria-hidden=\"true\"\r\n >\r\n <span class=\"chart-legend__icon-line\"></span>\r\n <span\r\n class=\"chart-legend__icon chart-legend__icon--marker\"\r\n [ngClass]=\"iconShapeClass(item.icon)\"\r\n ></span>\r\n <span class=\"chart-legend__icon-line\"></span>\r\n </span>\r\n } @else {\r\n <span\r\n class=\"chart-legend__icon\"\r\n [ngClass]=\"iconShapeClass(iconForRender(item))\"\r\n aria-hidden=\"true\"\r\n ></span>\r\n }\r\n }\r\n }\r\n <span class=\"chart-legend__label\"\r\n >{{ item.label\r\n }}{{ this.config.showValue && this.config.valueFormatter && ':' }}</span\r\n >\r\n @if (this.config.showValue && this.config.valueFormatter) {\r\n <span class=\"chart-legend__value\">{{ this.config.valueFormatter(item) }}</span>\r\n }\r\n @if (this.config.showActionArrow) {\r\n @if (this.config.actionArrowTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"this.config.actionArrowTemplate\"\r\n [ngTemplateOutletContext]=\"templateContext(item)\"\r\n ></ng-container>\r\n } @else {\r\n <svg\r\n class=\"chart-legend__action-arrow\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n >\r\n <polyline points=\"9 18 15 12 9 6\"></polyline>\r\n </svg>\r\n }\r\n }\r\n }\r\n </button>\r\n }\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (usesInternalLegendScroll && canScrollLegend) {\r\n <button\r\n type=\"button\"\r\n class=\"chart-legend__scroll-button chart-legend__scroll-button--end\"\r\n [disabled]=\"!canScrollEnd\"\r\n (click)=\"scrollLegend(1, $event)\"\r\n [attr.aria-label]=\"scrollEndAriaLabel\"\r\n >\r\n <img\r\n src=\"images/legend_right.svg\"\r\n [class.chart-legend__scroll-icon--down]=\"scrollsVertically\"\r\n alt=\"right\"\r\n />\r\n </button>\r\n }\r\n </div>\r\n\r\n @if (config.showPagination && pageCount > 1) {\r\n <div class=\"chart-legend__pagination\" aria-label=\"Legend pages\">\r\n <button\r\n type=\"button\"\r\n class=\"chart-legend__page\"\r\n [disabled]=\"state.pageIndex === 0\"\r\n (click)=\"page(-1)\"\r\n aria-label=\"Previous legend page\"\r\n >\r\n &lt;\r\n </button>\r\n <span class=\"chart-legend__page-count\">{{ state.pageIndex + 1 }} / {{ pageCount }}</span>\r\n <button\r\n type=\"button\"\r\n class=\"chart-legend__page\"\r\n [disabled]=\"state.pageIndex + 1 === pageCount\"\r\n (click)=\"page(1)\"\r\n aria-label=\"Next legend page\"\r\n >\r\n &gt;\r\n </button>\r\n </div>\r\n }\r\n </nav>\r\n}\r\n", styles: [":host{display:block;min-height:0;min-width:0}.chart-legend{--legend-text-color: #040d17;--legend-muted-color: #8a94a6;--legend-border-color: #eaf3fd;--legend-hover-bg: rgba(15, 23, 42, .04);--legend-font-size: 14px;--legend-item-min-height: 28px;--legend-row-gap: 8px;--legend-column-gap: 12px;--legend-font-style: normal;--legend-font-weight: 400;--legend-text-decoration: none;--legend-font-family: initial;--legend-title-color: #040d17;--legend-title-font-size: 14px;--legend-title-font-style: normal;--legend-title-font-weight: 400;--legend-title-text-decoration: none;--legend-title-font-family: initial;box-sizing:border-box;min-height:0;min-width:0;width:100%}:host-context(.dark) .chart-legend,:host-context([data-theme=dark]) .chart-legend{--legend-text-color: #e5e7eb;--legend-muted-color: #9ca3af;--legend-border-color: #374151;--legend-hover-bg: rgba(255, 255, 255, .08)}.chart-legend__viewport{align-items:center;display:flex;gap:4px;min-width:0;width:100%}.chart-legend__viewport .chart-legend-title{font-weight:var(--legend-title-font-weight);font-size:var(--legend-title-font-size);font-style:var(--legend-title-font-style);text-decoration:var(--legend-title-text-decoration);font-family:var(--legend-title-font-family);color:var(--legend-title-color);white-space:nowrap;margin:0 8px 0 0}.chart-legend__viewport .chart-legend-title--uppercase{text-transform:uppercase}.chart-legend__viewport .chart-legend-title--lowercase{text-transform:lowercase}.chart-legend__viewport .chart-legend-title--capitalize{text-transform:capitalize}.chart-legend__scroller{flex:1 1 auto;min-height:0;min-width:0;overflow-x:hidden;overflow-y:hidden;scrollbar-width:none}.chart-legend__scroller::-webkit-scrollbar{display:none}.chart-legend--scrollable .chart-legend__scroller{overflow-x:auto;overscroll-behavior-x:contain}.chart-legend--scrollable .chart-legend__scroller::-webkit-scrollbar{display:block;height:6px}.chart-legend__items{display:flex;flex-wrap:nowrap;align-items:center;gap:var(--legend-row-gap) var(--legend-column-gap);min-width:0;color:var(--legend-text-color);font-size:var(--legend-font-size);font-style:var(--legend-font-style);font-weight:var(--legend-font-weight);text-decoration:var(--legend-text-decoration);font-family:var(--legend-font-family)}.chart-legend--scrollable .chart-legend__items{min-width:max-content}.chart-legend--wrap:not(.chart-legend--vertical) .chart-legend__items{flex-wrap:wrap;width:100%}.chart-legend--limited-wrap:not(.chart-legend--vertical) .chart-legend__scroller{max-height:calc(var(--legend-item-min-height) * 2 + var(--legend-row-gap));overflow-y:auto;overscroll-behavior-y:contain}.chart-legend--vertical{height:100%}.chart-legend--vertical .chart-legend__viewport{align-items:stretch;flex-direction:column;height:100%;min-height:0}.chart-legend--vertical .chart-legend__scroller{overflow-x:hidden;overflow-y:hidden}.chart-legend--vertical.chart-legend--scrollable .chart-legend__scroller{overflow-y:auto;overscroll-behavior-y:contain}.chart-legend--vertical .chart-legend__items{align-items:stretch;flex-direction:column;min-width:0;width:100%;height:100%}.chart-legend--vertical.chart-legend--wrap .chart-legend__items{align-content:start;display:grid;grid-auto-flow:column;grid-auto-columns:max-content;grid-template-rows:repeat(auto-fit,minmax(28px,max-content));height:100%;justify-content:start;width:auto}.chart-legend--vertical.chart-legend--limited-wrap .chart-legend__viewport{flex-direction:row}.chart-legend--vertical.chart-legend--limited-wrap .chart-legend__scroller{overflow-x:auto;overflow-y:hidden;overscroll-behavior-x:contain}.chart-legend--vertical.chart-legend--limited-wrap .chart-legend__items{grid-auto-columns:minmax(1,calc((100% - var(--legend-column-gap)) / 2));width:max-content}.chart-legend__items--center{justify-content:center}.chart-legend__items--end{justify-content:flex-end}.chart-legend--vertical.chart-legend--wrap .chart-legend__items--center{align-content:center;justify-content:start}.chart-legend--vertical.chart-legend--wrap .chart-legend__items--end{align-content:end;justify-content:start}.chart-legend__group-label{flex:0 0 auto;color:var(--legend-muted-color);font-size:12px;font-weight:600;line-height:1.2;margin-top:4px}.chart-legend__item{--legend-item-color: #64748b;align-items:center;background:color-mix(in srgb,var(--legend-item-color) 4%,transparent);border:1px solid color-mix(in srgb,var(--legend-item-color) 25%,transparent);border-radius:4px;color:inherit;cursor:pointer;display:inline-flex;font:inherit;gap:8px;line-height:1.2;min-height:28px;min-width:0;padding:4px 8px;touch-action:manipulation;transition:background-color .14s ease,border-color .14s ease,opacity .14s ease}.chart-legend--vertical .chart-legend__item{justify-content:flex-start;width:100%}.chart-legend--vertical.chart-legend--wrap .chart-legend__item{width:auto}.chart-legend--vertical.chart-legend--limited-wrap .chart-legend__item{width:100%}.chart-legend__scroll-button{align-items:center;background:transparent;border:1px solid var(--legend-border-color);border-radius:6px;color:inherit;cursor:pointer;display:inline-flex;flex:0 0 auto;font:inherit;height:28px;justify-content:center;line-height:1;width:28px}.chart-legend--vertical .chart-legend__scroll-button{width:100%}.chart-legend--vertical.chart-legend--limited-wrap .chart-legend__scroll-button{height:auto;min-height:28px;width:28px}.chart-legend__scroll-button img{display:block;height:10px;width:10px}.chart-legend__scroll-icon--up,.chart-legend__scroll-icon--down{transform:rotate(90deg)}.chart-legend__scroll-button:disabled{cursor:default;opacity:.42}.chart-legend__item:hover,.chart-legend__item:focus-visible,.chart-legend__item--hovered{outline:none}.chart-legend__item--off{color:var(--legend-muted-color);filter:grayscale(1);opacity:.68}.chart-legend__item--disabled{cursor:not-allowed;opacity:.48}.chart-legend__icon,.chart-legend__icon-image,.chart-legend__icon-path{--legend-icon-size: 12px;background:var(--legend-item-color);box-sizing:border-box;display:inline-block;flex:0 0 auto;height:var(--legend-icon-size);width:var(--legend-icon-size)}.chart-legend__icon-image,.chart-legend__icon-path{background:transparent;object-fit:contain}.chart-legend__icon-path path{fill:var(--legend-item-color);stroke:var(--legend-item-color)}.chart-legend__icon--line,.chart-legend__icon--emptyLine{height:11px;border-radius:999px;background:linear-gradient(to bottom,transparent 0 4px,var(--legend-item-color) 4px 6px,transparent 6px 100%)}.chart-legend__icon--emptyLine{background:linear-gradient(to bottom,transparent 0 4px,var(--legend-item-color) 4px 6px,transparent 6px 100%)}.chart-legend__icon--area{background:linear-gradient(to bottom,var(--legend-item-color),color-mix(in srgb,var(--legend-item-color) 12%,transparent));border-top:3px solid var(--legend-item-color)}.chart-legend__icon--circle{border-radius:50%}.chart-legend__icon--emptyCircle{background:transparent;border:2px solid var(--legend-item-color);border-radius:50%}.chart-legend__icon--rect,.chart-legend__icon--emptyRect,.chart-legend__icon--square,.chart-legend__icon--emptySquare{border-radius:2px}.chart-legend__icon--emptyRect,.chart-legend__icon--emptySquare{background:transparent;border:2px solid var(--legend-item-color)}.chart-legend__icon--roundRect,.chart-legend__icon--emptyRoundRect{border-radius:6px}.chart-legend__icon--emptyRoundRect{background:transparent;border:2px solid var(--legend-item-color)}.chart-legend__icon--triangle,.chart-legend__icon--emptyTriangle{clip-path:polygon(50% 0,100% 100%,0 100%)}.chart-legend__icon--emptyTriangle{background:var(--legend-item-color)}.chart-legend__icon--diamond,.chart-legend__icon--emptyDiamond{transform:rotate(45deg)}.chart-legend__icon--emptyDiamond{background:transparent;border:2px solid var(--legend-item-color)}.chart-legend__icon--pin,.chart-legend__icon--emptyPin{border-radius:50% 50% 50% 0;transform:rotate(-45deg)}.chart-legend__icon--emptyPin{background:transparent;border:2px solid var(--legend-item-color)}.chart-legend__icon--arrow,.chart-legend__icon--emptyArrow{clip-path:polygon(0 35%,58% 35%,58% 10%,100% 50%,58% 90%,58% 65%,0 65%)}.chart-legend__icon--emptyArrow{opacity:.72}.chart-legend__icon--x,.chart-legend__icon--plus,.chart-legend__icon--thickLine{background:transparent;position:relative}.chart-legend__icon--x:before,.chart-legend__icon--x:after,.chart-legend__icon--plus:before,.chart-legend__icon--plus:after{content:\"\";position:absolute;left:50%;top:50%;width:100%;height:2px;background:var(--legend-item-color);border-radius:999px;transform:translate(-50%,-50%)}.chart-legend__icon--x:before{transform:translate(-50%,-50%) rotate(45deg)}.chart-legend__icon--x:after{transform:translate(-50%,-50%) rotate(-45deg)}.chart-legend__icon--plus:after{transform:translate(-50%,-50%) rotate(90deg)}.chart-legend__icon--thickLine{height:4px;width:var(--legend-icon-size);border-radius:999px;background:var(--legend-item-color)}.chart-legend__icon--line-marker{display:inline-flex;align-items:center;justify-content:center;padding:0 2px;background:transparent;border:none;min-width:0;width:auto}.chart-legend__icon-line{flex:1 1 1;min-width:8px;height:2px;background:var(--legend-item-color);border-radius:999px}.chart-legend__item--off .chart-legend__icon,.chart-legend__item--off .chart-legend__icon-path path{filter:grayscale(1);opacity:.68}.chart-legend__item--off .chart-legend__icon--emptyCircle,.chart-legend__item--off .chart-legend__icon--emptyRect,.chart-legend__item--off .chart-legend__icon--emptyRoundRect,.chart-legend__item--off .chart-legend__icon--emptySquare,.chart-legend__item--off .chart-legend__icon--emptyDiamond,.chart-legend__item--off .chart-legend__icon--emptyPin,.chart-legend__item--off .chart-legend__icon--emptyLine{filter:grayscale(1);opacity:.68}.chart-legend__content{display:flex;align-items:center;justify-content:space-between;gap:1rem}.chart-legend__value{font-weight:600;font-size:inherit;font-family:inherit}.chart-legend__item--off .chart-legend__icon--emptyTriangle{filter:grayscale(1);opacity:.68}.chart-legend__label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:inherit;font-family:inherit}.chart-legend__pagination{align-items:center;display:flex;gap:8px;justify-content:flex-end;margin-top:8px}.chart-legend__page{align-items:center;background:transparent;border:1px solid var(--legend-border-color);border-radius:6px;color:inherit;cursor:pointer;display:inline-flex;font:inherit;height:28px;justify-content:center;width:28px}.chart-legend__page:disabled{cursor:default;opacity:.42}.chart-legend__page-count{color:var(--legend-muted-color);font-size:12px}@media (max-width: 640px){.chart-legend__items{padding-bottom:2px}}.chart-legend__action-arrow{width:12px;height:12px;color:var(--legend-muted-color, #9ca3af);flex:0 0 auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
449
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: ChartLegendComponent, isStandalone: true, selector: "lib-chart-legend", inputs: { chart: "chart", series: "series", colors: "colors", config: "config", itemTemplate: "itemTemplate" }, outputs: { legendEvent: "legendEvent" }, viewQueries: [{ propertyName: "itemsScroller", first: true, predicate: ["itemsScroller"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "@if (config.enabled !== false) {\r\n <nav\r\n class=\"chart-legend\"\r\n [class.chart-legend--vertical]=\"isVerticalLegend\"\r\n [class.chart-legend--scrollable]=\"isScrollableLegend\"\r\n [class.chart-legend--wrap]=\"!isScrollableLegend\"\r\n [class.chart-legend--limited-wrap]=\"isLimitedWrapLegend\"\r\n [ngClass]=\"config.className || null\"\r\n [style.max-height]=\"config.maxHeight || null\"\r\n [style.padding]=\"config.padding || '1rem'\"\r\n [attr.aria-label]=\"config.ariaLabel || 'Chart legend'\"\r\n >\r\n <div class=\"chart-legend__viewport\">\r\n @if (config.title) {\r\n <p\r\n class=\"chart-legend-title\"\r\n [class.chart-legend-title--uppercase]=\"config.legendTitleTransform === 'uppercase'\"\r\n [class.chart-legend-title--lowercase]=\"config.legendTitleTransform === 'lowercase'\"\r\n [class.chart-legend-title--capitalize]=\"config.legendTitleTransform === 'capitalize'\"\r\n [style.--legend-title-color]=\"config.legendTitleTextColor || null\"\r\n [style.--legend-title-font-size]=\"\r\n config.legendTitleFontSize ? config.legendTitleFontSize + 'px' : null\r\n \"\r\n [style.--legend-title-font-style]=\"config.legendTitleFontStyle || null\"\r\n [style.--legend-title-font-weight]=\"config.legendTitleFontWeight || null\"\r\n [style.--legend-title-text-decoration]=\"config.legendTitleTextDecoration || null\"\r\n [style.--legend-title-font-family]=\"config.legendTitleFontFamily || 'initial'\"\r\n >\r\n {{ config.title }}\r\n </p>\r\n }\r\n @if (usesInternalLegendScroll && canScrollLegend) {\r\n <button\r\n type=\"button\"\r\n class=\"chart-legend__scroll-button chart-legend__scroll-button--start\"\r\n [disabled]=\"!canScrollStart\"\r\n (click)=\"scrollLegend(-1, $event)\"\r\n [attr.aria-label]=\"scrollStartAriaLabel\"\r\n >\r\n <img\r\n src=\"images/legend_left.svg\"\r\n [class.chart-legend__scroll-icon--up]=\"scrollsVertically\"\r\n alt=\"left\"\r\n />\r\n </button>\r\n }\r\n\r\n <div #itemsScroller class=\"chart-legend__scroller\" (scroll)=\"updateScrollState()\">\r\n <div\r\n class=\"chart-legend__items\"\r\n role=\"list\"\r\n [class.chart-legend__items--center]=\"\r\n isLegendAlignedCenter && (!usesInternalLegendScroll || !canScrollLegend)\r\n \"\r\n [class.chart-legend__items--end]=\"isLegendAlignedEnd\"\r\n [style.--legend-text-color]=\"config.legendTextColor || null\"\r\n [style.--legend-font-size]=\"config.legendFontSize ? config.legendFontSize + 'px' : null\"\r\n [style.--legend-font-style]=\"config.legendFontStyle || null\"\r\n [style.--legend-font-weight]=\"config.legendFontWeight || null\"\r\n [style.--legend-text-decoration]=\"config.legendTextDecoration || null\"\r\n [style.--legend-font-family]=\"config.legendFontFamily || 'initial'\"\r\n >\r\n @for (group of groupedItems; track trackByGroup($index, group)) {\r\n @if (group.group) {\r\n <div class=\"chart-legend__group-label\">{{ group.group }}</div>\r\n }\r\n\r\n @for (item of group.items; track trackByItem($index, item)) {\r\n <button\r\n type=\"button\"\r\n class=\"chart-legend__item\"\r\n role=\"switch\"\r\n [class.chart-legend__item--off]=\"!item.selected\"\r\n [class.chart-legend__item--disabled]=\"item.disabled\"\r\n [class.chart-legend__item--hovered]=\"state.hoveredName === item.name\"\r\n [disabled]=\"item.disabled\"\r\n [attr.aria-checked]=\"item.selected\"\r\n [attr.aria-label]=\"item.label\"\r\n [style.--legend-item-color]=\"item.color\"\r\n [title]=\"itemTitle(item)\"\r\n (click)=\"toggle(item, $event)\"\r\n (keydown.enter)=\"toggle(item, $event)\"\r\n (keydown.space)=\"toggle(item, $event)\"\r\n (mouseenter)=\"hover(item)\"\r\n (focus)=\"hover(item)\"\r\n (mouseleave)=\"leave(item)\"\r\n (blur)=\"leave(item)\"\r\n >\r\n @if (templateFor(item); as template) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"template\"\r\n [ngTemplateOutletContext]=\"templateContext(item)\"\r\n ></ng-container>\r\n } @else {\r\n @switch (iconRenderType(item)) {\r\n @case ('image') {\r\n @if (isLineMarker(item)) {\r\n <span\r\n class=\"chart-legend__icon chart-legend__icon--line-marker\"\r\n aria-hidden=\"true\"\r\n >\r\n <span class=\"chart-legend__icon-line\"></span>\r\n <img class=\"chart-legend__icon-image\" [src]=\"iconImageSrc(item)\" alt=\"\" />\r\n <span class=\"chart-legend__icon-line\"></span>\r\n </span>\r\n } @else {\r\n <img class=\"chart-legend__icon-image\" [src]=\"iconImageSrc(item)\" alt=\"\" />\r\n }\r\n }\r\n @case ('path') {\r\n @if (isLineMarker(item)) {\r\n <span\r\n class=\"chart-legend__icon chart-legend__icon--line-marker\"\r\n aria-hidden=\"true\"\r\n >\r\n <span class=\"chart-legend__icon-line\"></span>\r\n <svg\r\n class=\"chart-legend__icon-path\"\r\n viewBox=\"-512 -512 1024 1024\"\r\n aria-hidden=\"true\"\r\n >\r\n <path [attr.d]=\"iconPathData(item)\"></path>\r\n </svg>\r\n <span class=\"chart-legend__icon-line\"></span>\r\n </span>\r\n } @else {\r\n <svg\r\n class=\"chart-legend__icon-path\"\r\n viewBox=\"-512 -512 1024 1024\"\r\n aria-hidden=\"true\"\r\n >\r\n <path [attr.d]=\"iconPathData(item)\"></path>\r\n </svg>\r\n }\r\n }\r\n @case ('shape') {\r\n @if (isLineMarker(item)) {\r\n <span\r\n class=\"chart-legend__icon chart-legend__icon--line-marker\"\r\n aria-hidden=\"true\"\r\n >\r\n <span class=\"chart-legend__icon-line\"></span>\r\n <span\r\n class=\"chart-legend__icon chart-legend__icon--marker\"\r\n [ngClass]=\"iconShapeClass(item.icon)\"\r\n ></span>\r\n <span class=\"chart-legend__icon-line\"></span>\r\n </span>\r\n } @else {\r\n <span\r\n class=\"chart-legend__icon\"\r\n [ngClass]=\"iconShapeClass(iconForRender(item))\"\r\n aria-hidden=\"true\"\r\n ></span>\r\n }\r\n }\r\n }\r\n <span class=\"chart-legend__label\">\n {{ item.label }}@if (this.config.showValue && this.config.valueFormatter) {\n :\n }\n </span>\n @if (this.config.showValue && this.config.valueFormatter) {\r\n <span class=\"chart-legend__value\">{{ this.config.valueFormatter(item) }}</span>\r\n }\r\n @if (this.config.showActionArrow) {\r\n @if (this.config.actionArrowTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"this.config.actionArrowTemplate\"\r\n [ngTemplateOutletContext]=\"templateContext(item)\"\r\n ></ng-container>\r\n } @else {\r\n <svg\r\n class=\"chart-legend__action-arrow\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n >\r\n <polyline points=\"9 18 15 12 9 6\"></polyline>\r\n </svg>\r\n }\r\n }\r\n }\r\n </button>\r\n }\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (usesInternalLegendScroll && canScrollLegend) {\r\n <button\r\n type=\"button\"\r\n class=\"chart-legend__scroll-button chart-legend__scroll-button--end\"\r\n [disabled]=\"!canScrollEnd\"\r\n (click)=\"scrollLegend(1, $event)\"\r\n [attr.aria-label]=\"scrollEndAriaLabel\"\r\n >\r\n <img\r\n src=\"images/legend_right.svg\"\r\n [class.chart-legend__scroll-icon--down]=\"scrollsVertically\"\r\n alt=\"right\"\r\n />\r\n </button>\r\n }\r\n </div>\r\n\r\n @if (config.showPagination && pageCount > 1) {\r\n <div class=\"chart-legend__pagination\" aria-label=\"Legend pages\">\r\n <button\r\n type=\"button\"\r\n class=\"chart-legend__page\"\r\n [disabled]=\"state.pageIndex === 0\"\r\n (click)=\"page(-1)\"\r\n aria-label=\"Previous legend page\"\r\n >\r\n &lt;\r\n </button>\r\n <span class=\"chart-legend__page-count\">{{ state.pageIndex + 1 }} / {{ pageCount }}</span>\r\n <button\r\n type=\"button\"\r\n class=\"chart-legend__page\"\r\n [disabled]=\"state.pageIndex + 1 === pageCount\"\r\n (click)=\"page(1)\"\r\n aria-label=\"Next legend page\"\r\n >\r\n &gt;\r\n </button>\r\n </div>\r\n }\r\n </nav>\r\n}\r\n", styles: [":host{display:block;min-height:0;min-width:0}.chart-legend{--legend-text-color: #040d17;--legend-muted-color: #8a94a6;--legend-border-color: #eaf3fd;--legend-hover-bg: rgba(15, 23, 42, .04);--legend-font-size: 14px;--legend-item-min-height: 28px;--legend-row-gap: 8px;--legend-column-gap: 12px;--legend-font-style: normal;--legend-font-weight: 400;--legend-text-decoration: none;--legend-font-family: initial;--legend-title-color: #040d17;--legend-title-font-size: 14px;--legend-title-font-style: normal;--legend-title-font-weight: 400;--legend-title-text-decoration: none;--legend-title-font-family: initial;box-sizing:border-box;min-height:0;min-width:0;width:100%}:host-context(.dark) .chart-legend,:host-context([data-theme=dark]) .chart-legend{--legend-text-color: #e5e7eb;--legend-muted-color: #9ca3af;--legend-border-color: #374151;--legend-hover-bg: rgba(255, 255, 255, .08)}.chart-legend__viewport{align-items:center;display:flex;gap:4px;min-width:0;width:100%}.chart-legend__viewport .chart-legend-title{font-weight:var(--legend-title-font-weight);font-size:var(--legend-title-font-size);font-style:var(--legend-title-font-style);text-decoration:var(--legend-title-text-decoration);font-family:var(--legend-title-font-family);color:var(--legend-title-color);white-space:nowrap;margin:0 8px 0 0}.chart-legend__viewport .chart-legend-title--uppercase{text-transform:uppercase}.chart-legend__viewport .chart-legend-title--lowercase{text-transform:lowercase}.chart-legend__viewport .chart-legend-title--capitalize{text-transform:capitalize}.chart-legend__scroller{flex:1 1 auto;min-height:0;min-width:0;overflow-x:hidden;overflow-y:hidden;scrollbar-width:none}.chart-legend__scroller::-webkit-scrollbar{display:none}.chart-legend--scrollable .chart-legend__scroller{overflow-x:auto;overscroll-behavior-x:contain}.chart-legend--scrollable .chart-legend__scroller::-webkit-scrollbar{display:block;height:6px}.chart-legend__items{display:flex;flex-wrap:nowrap;align-items:center;gap:var(--legend-row-gap) var(--legend-column-gap);min-width:0;color:var(--legend-text-color);font-size:var(--legend-font-size);font-style:var(--legend-font-style);font-weight:var(--legend-font-weight);text-decoration:var(--legend-text-decoration);font-family:var(--legend-font-family)}.chart-legend--scrollable .chart-legend__items{min-width:max-content}.chart-legend--wrap:not(.chart-legend--vertical) .chart-legend__items{flex-wrap:wrap;width:100%}.chart-legend--limited-wrap:not(.chart-legend--vertical) .chart-legend__scroller{max-height:calc(var(--legend-item-min-height) * 2 + var(--legend-row-gap));overflow-y:auto;overscroll-behavior-y:contain}.chart-legend--vertical{height:100%}.chart-legend--vertical .chart-legend__viewport{align-items:stretch;flex-direction:column;height:100%;min-height:0}.chart-legend--vertical .chart-legend__scroller{overflow-x:hidden;overflow-y:hidden}.chart-legend--vertical.chart-legend--scrollable .chart-legend__scroller{overflow-y:auto;overscroll-behavior-y:contain}.chart-legend--vertical .chart-legend__items{align-items:stretch;flex-direction:column;min-width:0;width:100%;height:100%}.chart-legend--vertical.chart-legend--wrap .chart-legend__items{align-content:start;display:grid;grid-auto-flow:column;grid-auto-columns:max-content;grid-template-rows:repeat(auto-fit,minmax(28px,max-content));height:100%;justify-content:start;width:auto}.chart-legend--vertical.chart-legend--limited-wrap .chart-legend__viewport{flex-direction:row}.chart-legend--vertical.chart-legend--limited-wrap .chart-legend__scroller{overflow-x:auto;overflow-y:hidden;overscroll-behavior-x:contain}.chart-legend--vertical.chart-legend--limited-wrap .chart-legend__items{grid-auto-columns:minmax(1,calc((100% - var(--legend-column-gap)) / 2));width:max-content}.chart-legend__items--center{justify-content:center}.chart-legend__items--end{justify-content:flex-end}.chart-legend--vertical.chart-legend--wrap .chart-legend__items--center{align-content:center;justify-content:start}.chart-legend--vertical.chart-legend--wrap .chart-legend__items--end{align-content:end;justify-content:start}.chart-legend__group-label{flex:0 0 auto;color:var(--legend-muted-color);font-size:12px;font-weight:600;line-height:1.2;margin-top:4px}.chart-legend__item{--legend-item-color: #64748b;align-items:center;background:color-mix(in srgb,var(--legend-item-color) 4%,transparent);border:1px solid color-mix(in srgb,var(--legend-item-color) 25%,transparent);border-radius:4px;color:inherit;cursor:pointer;display:inline-flex;font:inherit;gap:8px;line-height:1.2;min-height:28px;min-width:0;padding:4px 8px;touch-action:manipulation;transition:background-color .14s ease,border-color .14s ease,opacity .14s ease}.chart-legend--vertical .chart-legend__item{justify-content:flex-start;width:100%}.chart-legend--vertical.chart-legend--wrap .chart-legend__item{width:auto}.chart-legend--vertical.chart-legend--limited-wrap .chart-legend__item{width:100%}.chart-legend__scroll-button{align-items:center;background:transparent;border:1px solid var(--legend-border-color);border-radius:6px;color:inherit;cursor:pointer;display:inline-flex;flex:0 0 auto;font:inherit;height:28px;justify-content:center;line-height:1;width:28px}.chart-legend--vertical .chart-legend__scroll-button{width:100%}.chart-legend--vertical.chart-legend--limited-wrap .chart-legend__scroll-button{height:auto;min-height:28px;width:28px}.chart-legend__scroll-button img{display:block;height:10px;width:10px}.chart-legend__scroll-icon--up,.chart-legend__scroll-icon--down{transform:rotate(90deg)}.chart-legend__scroll-button:disabled{cursor:default;opacity:.42}.chart-legend__item:hover,.chart-legend__item:focus-visible,.chart-legend__item--hovered{outline:none}.chart-legend__item--off{color:var(--legend-muted-color);filter:grayscale(1);opacity:.68}.chart-legend__item--disabled{cursor:not-allowed;opacity:.48}.chart-legend__icon,.chart-legend__icon-image,.chart-legend__icon-path{--legend-icon-size: 12px;background:var(--legend-item-color);box-sizing:border-box;display:inline-block;flex:0 0 auto;height:var(--legend-icon-size);width:var(--legend-icon-size)}.chart-legend__icon-image,.chart-legend__icon-path{background:transparent;object-fit:contain}.chart-legend__icon-path path{fill:var(--legend-item-color);stroke:var(--legend-item-color)}.chart-legend__icon--line,.chart-legend__icon--emptyLine{height:11px;border-radius:999px;background:linear-gradient(to bottom,transparent 0 4px,var(--legend-item-color) 4px 6px,transparent 6px 100%)}.chart-legend__icon--emptyLine{background:linear-gradient(to bottom,transparent 0 4px,var(--legend-item-color) 4px 6px,transparent 6px 100%)}.chart-legend__icon--area{background:linear-gradient(to bottom,var(--legend-item-color),color-mix(in srgb,var(--legend-item-color) 12%,transparent));border-top:3px solid var(--legend-item-color)}.chart-legend__icon--circle{border-radius:50%}.chart-legend__icon--emptyCircle{background:transparent;border:2px solid var(--legend-item-color);border-radius:50%}.chart-legend__icon--rect,.chart-legend__icon--emptyRect,.chart-legend__icon--square,.chart-legend__icon--emptySquare{border-radius:2px}.chart-legend__icon--emptyRect,.chart-legend__icon--emptySquare{background:transparent;border:2px solid var(--legend-item-color)}.chart-legend__icon--roundRect,.chart-legend__icon--emptyRoundRect{border-radius:6px}.chart-legend__icon--emptyRoundRect{background:transparent;border:2px solid var(--legend-item-color)}.chart-legend__icon--triangle,.chart-legend__icon--emptyTriangle{clip-path:polygon(50% 0,100% 100%,0 100%)}.chart-legend__icon--emptyTriangle{background:var(--legend-item-color)}.chart-legend__icon--diamond,.chart-legend__icon--emptyDiamond{transform:rotate(45deg)}.chart-legend__icon--emptyDiamond{background:transparent;border:2px solid var(--legend-item-color)}.chart-legend__icon--pin,.chart-legend__icon--emptyPin{border-radius:50% 50% 50% 0;transform:rotate(-45deg)}.chart-legend__icon--emptyPin{background:transparent;border:2px solid var(--legend-item-color)}.chart-legend__icon--arrow,.chart-legend__icon--emptyArrow{clip-path:polygon(0 35%,58% 35%,58% 10%,100% 50%,58% 90%,58% 65%,0 65%)}.chart-legend__icon--emptyArrow{opacity:.72}.chart-legend__icon--x,.chart-legend__icon--plus,.chart-legend__icon--thickLine{background:transparent;position:relative}.chart-legend__icon--x:before,.chart-legend__icon--x:after,.chart-legend__icon--plus:before,.chart-legend__icon--plus:after{content:\"\";position:absolute;left:50%;top:50%;width:100%;height:2px;background:var(--legend-item-color);border-radius:999px;transform:translate(-50%,-50%)}.chart-legend__icon--x:before{transform:translate(-50%,-50%) rotate(45deg)}.chart-legend__icon--x:after{transform:translate(-50%,-50%) rotate(-45deg)}.chart-legend__icon--plus:after{transform:translate(-50%,-50%) rotate(90deg)}.chart-legend__icon--thickLine{height:4px;width:var(--legend-icon-size);border-radius:999px;background:var(--legend-item-color)}.chart-legend__icon--line-marker{display:inline-flex;align-items:center;justify-content:center;padding:0 2px;background:transparent;border:none;min-width:0;width:auto}.chart-legend__icon-line{flex:1 1 1;min-width:8px;height:2px;background:var(--legend-item-color);border-radius:999px}.chart-legend__item--off .chart-legend__icon,.chart-legend__item--off .chart-legend__icon-path path{filter:grayscale(1);opacity:.68}.chart-legend__item--off .chart-legend__icon--emptyCircle,.chart-legend__item--off .chart-legend__icon--emptyRect,.chart-legend__item--off .chart-legend__icon--emptyRoundRect,.chart-legend__item--off .chart-legend__icon--emptySquare,.chart-legend__item--off .chart-legend__icon--emptyDiamond,.chart-legend__item--off .chart-legend__icon--emptyPin,.chart-legend__item--off .chart-legend__icon--emptyLine{filter:grayscale(1);opacity:.68}.chart-legend__content{display:flex;align-items:center;justify-content:space-between;gap:1rem}.chart-legend__value{font-weight:600;font-size:inherit;font-family:inherit}.chart-legend__item--off .chart-legend__icon--emptyTriangle{filter:grayscale(1);opacity:.68}.chart-legend__label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:inherit;font-family:inherit}.chart-legend__pagination{align-items:center;display:flex;gap:8px;justify-content:flex-end;margin-top:8px}.chart-legend__page{align-items:center;background:transparent;border:1px solid var(--legend-border-color);border-radius:6px;color:inherit;cursor:pointer;display:inline-flex;font:inherit;height:28px;justify-content:center;width:28px}.chart-legend__page:disabled{cursor:default;opacity:.42}.chart-legend__page-count{color:var(--legend-muted-color);font-size:12px}@media (max-width: 640px){.chart-legend__items{padding-bottom:2px}}.chart-legend__action-arrow{width:12px;height:12px;color:var(--legend-muted-color, #9ca3af);flex:0 0 auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
450
450
  }
451
451
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ChartLegendComponent, decorators: [{
452
452
  type: Component,
453
- args: [{ selector: 'lib-chart-legend', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (config.enabled !== false) {\r\n <nav\r\n class=\"chart-legend\"\r\n [class.chart-legend--vertical]=\"isVerticalLegend\"\r\n [class.chart-legend--scrollable]=\"isScrollableLegend\"\r\n [class.chart-legend--wrap]=\"!isScrollableLegend\"\r\n [class.chart-legend--limited-wrap]=\"isLimitedWrapLegend\"\r\n [ngClass]=\"config.className || null\"\r\n [style.max-height]=\"config.maxHeight || null\"\r\n [style.padding]=\"config.padding || '1rem'\"\r\n [attr.aria-label]=\"config.ariaLabel || 'Chart legend'\"\r\n >\r\n <div class=\"chart-legend__viewport\">\r\n @if (config.title) {\r\n <p\r\n class=\"chart-legend-title\"\r\n [class.chart-legend-title--uppercase]=\"config.legendTitleTransform === 'uppercase'\"\r\n [class.chart-legend-title--lowercase]=\"config.legendTitleTransform === 'lowercase'\"\r\n [class.chart-legend-title--capitalize]=\"config.legendTitleTransform === 'capitalize'\"\r\n [style.--legend-title-color]=\"config.legendTitleTextColor || null\"\r\n [style.--legend-title-font-size]=\"\r\n config.legendTitleFontSize ? config.legendTitleFontSize + 'px' : null\r\n \"\r\n [style.--legend-title-font-style]=\"config.legendTitleFontStyle || null\"\r\n [style.--legend-title-font-weight]=\"config.legendTitleFontWeight || null\"\r\n [style.--legend-title-text-decoration]=\"config.legendTitleTextDecoration || null\"\r\n [style.--legend-title-font-family]=\"config.legendTitleFontFamily || 'initial'\"\r\n >\r\n {{ config.title }}\r\n </p>\r\n }\r\n @if (usesInternalLegendScroll && canScrollLegend) {\r\n <button\r\n type=\"button\"\r\n class=\"chart-legend__scroll-button chart-legend__scroll-button--start\"\r\n [disabled]=\"!canScrollStart\"\r\n (click)=\"scrollLegend(-1, $event)\"\r\n [attr.aria-label]=\"scrollStartAriaLabel\"\r\n >\r\n <img\r\n src=\"images/legend_left.svg\"\r\n [class.chart-legend__scroll-icon--up]=\"scrollsVertically\"\r\n alt=\"left\"\r\n />\r\n </button>\r\n }\r\n\r\n <div #itemsScroller class=\"chart-legend__scroller\" (scroll)=\"updateScrollState()\">\r\n <div\r\n class=\"chart-legend__items\"\r\n role=\"list\"\r\n [class.chart-legend__items--center]=\"\r\n isLegendAlignedCenter && (!usesInternalLegendScroll || !canScrollLegend)\r\n \"\r\n [class.chart-legend__items--end]=\"isLegendAlignedEnd\"\r\n [style.--legend-text-color]=\"config.legendTextColor || null\"\r\n [style.--legend-font-size]=\"config.legendFontSize ? config.legendFontSize + 'px' : null\"\r\n [style.--legend-font-style]=\"config.legendFontStyle || null\"\r\n [style.--legend-font-weight]=\"config.legendFontWeight || null\"\r\n [style.--legend-text-decoration]=\"config.legendTextDecoration || null\"\r\n [style.--legend-font-family]=\"config.legendFontFamily || 'initial'\"\r\n >\r\n @for (group of groupedItems; track trackByGroup($index, group)) {\r\n @if (group.group) {\r\n <div class=\"chart-legend__group-label\">{{ group.group }}</div>\r\n }\r\n\r\n @for (item of group.items; track trackByItem($index, item)) {\r\n <button\r\n type=\"button\"\r\n class=\"chart-legend__item\"\r\n role=\"switch\"\r\n [class.chart-legend__item--off]=\"!item.selected\"\r\n [class.chart-legend__item--disabled]=\"item.disabled\"\r\n [class.chart-legend__item--hovered]=\"state.hoveredName === item.name\"\r\n [disabled]=\"item.disabled\"\r\n [attr.aria-checked]=\"item.selected\"\r\n [attr.aria-label]=\"item.label\"\r\n [style.--legend-item-color]=\"item.color\"\r\n [title]=\"itemTitle(item)\"\r\n (click)=\"toggle(item, $event)\"\r\n (keydown.enter)=\"toggle(item, $event)\"\r\n (keydown.space)=\"toggle(item, $event)\"\r\n (mouseenter)=\"hover(item)\"\r\n (focus)=\"hover(item)\"\r\n (mouseleave)=\"leave(item)\"\r\n (blur)=\"leave(item)\"\r\n >\r\n @if (templateFor(item); as template) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"template\"\r\n [ngTemplateOutletContext]=\"templateContext(item)\"\r\n ></ng-container>\r\n } @else {\r\n @switch (iconRenderType(item)) {\r\n @case ('image') {\r\n @if (isLineMarker(item)) {\r\n <span\r\n class=\"chart-legend__icon chart-legend__icon--line-marker\"\r\n aria-hidden=\"true\"\r\n >\r\n <span class=\"chart-legend__icon-line\"></span>\r\n <img class=\"chart-legend__icon-image\" [src]=\"iconImageSrc(item)\" alt=\"\" />\r\n <span class=\"chart-legend__icon-line\"></span>\r\n </span>\r\n } @else {\r\n <img class=\"chart-legend__icon-image\" [src]=\"iconImageSrc(item)\" alt=\"\" />\r\n }\r\n }\r\n @case ('path') {\r\n @if (isLineMarker(item)) {\r\n <span\r\n class=\"chart-legend__icon chart-legend__icon--line-marker\"\r\n aria-hidden=\"true\"\r\n >\r\n <span class=\"chart-legend__icon-line\"></span>\r\n <svg\r\n class=\"chart-legend__icon-path\"\r\n viewBox=\"-512 -512 1024 1024\"\r\n aria-hidden=\"true\"\r\n >\r\n <path [attr.d]=\"iconPathData(item)\"></path>\r\n </svg>\r\n <span class=\"chart-legend__icon-line\"></span>\r\n </span>\r\n } @else {\r\n <svg\r\n class=\"chart-legend__icon-path\"\r\n viewBox=\"-512 -512 1024 1024\"\r\n aria-hidden=\"true\"\r\n >\r\n <path [attr.d]=\"iconPathData(item)\"></path>\r\n </svg>\r\n }\r\n }\r\n @case ('shape') {\r\n @if (isLineMarker(item)) {\r\n <span\r\n class=\"chart-legend__icon chart-legend__icon--line-marker\"\r\n aria-hidden=\"true\"\r\n >\r\n <span class=\"chart-legend__icon-line\"></span>\r\n <span\r\n class=\"chart-legend__icon chart-legend__icon--marker\"\r\n [ngClass]=\"iconShapeClass(item.icon)\"\r\n ></span>\r\n <span class=\"chart-legend__icon-line\"></span>\r\n </span>\r\n } @else {\r\n <span\r\n class=\"chart-legend__icon\"\r\n [ngClass]=\"iconShapeClass(iconForRender(item))\"\r\n aria-hidden=\"true\"\r\n ></span>\r\n }\r\n }\r\n }\r\n <span class=\"chart-legend__label\"\r\n >{{ item.label\r\n }}{{ this.config.showValue && this.config.valueFormatter && ':' }}</span\r\n >\r\n @if (this.config.showValue && this.config.valueFormatter) {\r\n <span class=\"chart-legend__value\">{{ this.config.valueFormatter(item) }}</span>\r\n }\r\n @if (this.config.showActionArrow) {\r\n @if (this.config.actionArrowTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"this.config.actionArrowTemplate\"\r\n [ngTemplateOutletContext]=\"templateContext(item)\"\r\n ></ng-container>\r\n } @else {\r\n <svg\r\n class=\"chart-legend__action-arrow\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n >\r\n <polyline points=\"9 18 15 12 9 6\"></polyline>\r\n </svg>\r\n }\r\n }\r\n }\r\n </button>\r\n }\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (usesInternalLegendScroll && canScrollLegend) {\r\n <button\r\n type=\"button\"\r\n class=\"chart-legend__scroll-button chart-legend__scroll-button--end\"\r\n [disabled]=\"!canScrollEnd\"\r\n (click)=\"scrollLegend(1, $event)\"\r\n [attr.aria-label]=\"scrollEndAriaLabel\"\r\n >\r\n <img\r\n src=\"images/legend_right.svg\"\r\n [class.chart-legend__scroll-icon--down]=\"scrollsVertically\"\r\n alt=\"right\"\r\n />\r\n </button>\r\n }\r\n </div>\r\n\r\n @if (config.showPagination && pageCount > 1) {\r\n <div class=\"chart-legend__pagination\" aria-label=\"Legend pages\">\r\n <button\r\n type=\"button\"\r\n class=\"chart-legend__page\"\r\n [disabled]=\"state.pageIndex === 0\"\r\n (click)=\"page(-1)\"\r\n aria-label=\"Previous legend page\"\r\n >\r\n &lt;\r\n </button>\r\n <span class=\"chart-legend__page-count\">{{ state.pageIndex + 1 }} / {{ pageCount }}</span>\r\n <button\r\n type=\"button\"\r\n class=\"chart-legend__page\"\r\n [disabled]=\"state.pageIndex + 1 === pageCount\"\r\n (click)=\"page(1)\"\r\n aria-label=\"Next legend page\"\r\n >\r\n &gt;\r\n </button>\r\n </div>\r\n }\r\n </nav>\r\n}\r\n", styles: [":host{display:block;min-height:0;min-width:0}.chart-legend{--legend-text-color: #040d17;--legend-muted-color: #8a94a6;--legend-border-color: #eaf3fd;--legend-hover-bg: rgba(15, 23, 42, .04);--legend-font-size: 14px;--legend-item-min-height: 28px;--legend-row-gap: 8px;--legend-column-gap: 12px;--legend-font-style: normal;--legend-font-weight: 400;--legend-text-decoration: none;--legend-font-family: initial;--legend-title-color: #040d17;--legend-title-font-size: 14px;--legend-title-font-style: normal;--legend-title-font-weight: 400;--legend-title-text-decoration: none;--legend-title-font-family: initial;box-sizing:border-box;min-height:0;min-width:0;width:100%}:host-context(.dark) .chart-legend,:host-context([data-theme=dark]) .chart-legend{--legend-text-color: #e5e7eb;--legend-muted-color: #9ca3af;--legend-border-color: #374151;--legend-hover-bg: rgba(255, 255, 255, .08)}.chart-legend__viewport{align-items:center;display:flex;gap:4px;min-width:0;width:100%}.chart-legend__viewport .chart-legend-title{font-weight:var(--legend-title-font-weight);font-size:var(--legend-title-font-size);font-style:var(--legend-title-font-style);text-decoration:var(--legend-title-text-decoration);font-family:var(--legend-title-font-family);color:var(--legend-title-color);white-space:nowrap;margin:0 8px 0 0}.chart-legend__viewport .chart-legend-title--uppercase{text-transform:uppercase}.chart-legend__viewport .chart-legend-title--lowercase{text-transform:lowercase}.chart-legend__viewport .chart-legend-title--capitalize{text-transform:capitalize}.chart-legend__scroller{flex:1 1 auto;min-height:0;min-width:0;overflow-x:hidden;overflow-y:hidden;scrollbar-width:none}.chart-legend__scroller::-webkit-scrollbar{display:none}.chart-legend--scrollable .chart-legend__scroller{overflow-x:auto;overscroll-behavior-x:contain}.chart-legend--scrollable .chart-legend__scroller::-webkit-scrollbar{display:block;height:6px}.chart-legend__items{display:flex;flex-wrap:nowrap;align-items:center;gap:var(--legend-row-gap) var(--legend-column-gap);min-width:0;color:var(--legend-text-color);font-size:var(--legend-font-size);font-style:var(--legend-font-style);font-weight:var(--legend-font-weight);text-decoration:var(--legend-text-decoration);font-family:var(--legend-font-family)}.chart-legend--scrollable .chart-legend__items{min-width:max-content}.chart-legend--wrap:not(.chart-legend--vertical) .chart-legend__items{flex-wrap:wrap;width:100%}.chart-legend--limited-wrap:not(.chart-legend--vertical) .chart-legend__scroller{max-height:calc(var(--legend-item-min-height) * 2 + var(--legend-row-gap));overflow-y:auto;overscroll-behavior-y:contain}.chart-legend--vertical{height:100%}.chart-legend--vertical .chart-legend__viewport{align-items:stretch;flex-direction:column;height:100%;min-height:0}.chart-legend--vertical .chart-legend__scroller{overflow-x:hidden;overflow-y:hidden}.chart-legend--vertical.chart-legend--scrollable .chart-legend__scroller{overflow-y:auto;overscroll-behavior-y:contain}.chart-legend--vertical .chart-legend__items{align-items:stretch;flex-direction:column;min-width:0;width:100%;height:100%}.chart-legend--vertical.chart-legend--wrap .chart-legend__items{align-content:start;display:grid;grid-auto-flow:column;grid-auto-columns:max-content;grid-template-rows:repeat(auto-fit,minmax(28px,max-content));height:100%;justify-content:start;width:auto}.chart-legend--vertical.chart-legend--limited-wrap .chart-legend__viewport{flex-direction:row}.chart-legend--vertical.chart-legend--limited-wrap .chart-legend__scroller{overflow-x:auto;overflow-y:hidden;overscroll-behavior-x:contain}.chart-legend--vertical.chart-legend--limited-wrap .chart-legend__items{grid-auto-columns:minmax(1,calc((100% - var(--legend-column-gap)) / 2));width:max-content}.chart-legend__items--center{justify-content:center}.chart-legend__items--end{justify-content:flex-end}.chart-legend--vertical.chart-legend--wrap .chart-legend__items--center{align-content:center;justify-content:start}.chart-legend--vertical.chart-legend--wrap .chart-legend__items--end{align-content:end;justify-content:start}.chart-legend__group-label{flex:0 0 auto;color:var(--legend-muted-color);font-size:12px;font-weight:600;line-height:1.2;margin-top:4px}.chart-legend__item{--legend-item-color: #64748b;align-items:center;background:color-mix(in srgb,var(--legend-item-color) 4%,transparent);border:1px solid color-mix(in srgb,var(--legend-item-color) 25%,transparent);border-radius:4px;color:inherit;cursor:pointer;display:inline-flex;font:inherit;gap:8px;line-height:1.2;min-height:28px;min-width:0;padding:4px 8px;touch-action:manipulation;transition:background-color .14s ease,border-color .14s ease,opacity .14s ease}.chart-legend--vertical .chart-legend__item{justify-content:flex-start;width:100%}.chart-legend--vertical.chart-legend--wrap .chart-legend__item{width:auto}.chart-legend--vertical.chart-legend--limited-wrap .chart-legend__item{width:100%}.chart-legend__scroll-button{align-items:center;background:transparent;border:1px solid var(--legend-border-color);border-radius:6px;color:inherit;cursor:pointer;display:inline-flex;flex:0 0 auto;font:inherit;height:28px;justify-content:center;line-height:1;width:28px}.chart-legend--vertical .chart-legend__scroll-button{width:100%}.chart-legend--vertical.chart-legend--limited-wrap .chart-legend__scroll-button{height:auto;min-height:28px;width:28px}.chart-legend__scroll-button img{display:block;height:10px;width:10px}.chart-legend__scroll-icon--up,.chart-legend__scroll-icon--down{transform:rotate(90deg)}.chart-legend__scroll-button:disabled{cursor:default;opacity:.42}.chart-legend__item:hover,.chart-legend__item:focus-visible,.chart-legend__item--hovered{outline:none}.chart-legend__item--off{color:var(--legend-muted-color);filter:grayscale(1);opacity:.68}.chart-legend__item--disabled{cursor:not-allowed;opacity:.48}.chart-legend__icon,.chart-legend__icon-image,.chart-legend__icon-path{--legend-icon-size: 12px;background:var(--legend-item-color);box-sizing:border-box;display:inline-block;flex:0 0 auto;height:var(--legend-icon-size);width:var(--legend-icon-size)}.chart-legend__icon-image,.chart-legend__icon-path{background:transparent;object-fit:contain}.chart-legend__icon-path path{fill:var(--legend-item-color);stroke:var(--legend-item-color)}.chart-legend__icon--line,.chart-legend__icon--emptyLine{height:11px;border-radius:999px;background:linear-gradient(to bottom,transparent 0 4px,var(--legend-item-color) 4px 6px,transparent 6px 100%)}.chart-legend__icon--emptyLine{background:linear-gradient(to bottom,transparent 0 4px,var(--legend-item-color) 4px 6px,transparent 6px 100%)}.chart-legend__icon--area{background:linear-gradient(to bottom,var(--legend-item-color),color-mix(in srgb,var(--legend-item-color) 12%,transparent));border-top:3px solid var(--legend-item-color)}.chart-legend__icon--circle{border-radius:50%}.chart-legend__icon--emptyCircle{background:transparent;border:2px solid var(--legend-item-color);border-radius:50%}.chart-legend__icon--rect,.chart-legend__icon--emptyRect,.chart-legend__icon--square,.chart-legend__icon--emptySquare{border-radius:2px}.chart-legend__icon--emptyRect,.chart-legend__icon--emptySquare{background:transparent;border:2px solid var(--legend-item-color)}.chart-legend__icon--roundRect,.chart-legend__icon--emptyRoundRect{border-radius:6px}.chart-legend__icon--emptyRoundRect{background:transparent;border:2px solid var(--legend-item-color)}.chart-legend__icon--triangle,.chart-legend__icon--emptyTriangle{clip-path:polygon(50% 0,100% 100%,0 100%)}.chart-legend__icon--emptyTriangle{background:var(--legend-item-color)}.chart-legend__icon--diamond,.chart-legend__icon--emptyDiamond{transform:rotate(45deg)}.chart-legend__icon--emptyDiamond{background:transparent;border:2px solid var(--legend-item-color)}.chart-legend__icon--pin,.chart-legend__icon--emptyPin{border-radius:50% 50% 50% 0;transform:rotate(-45deg)}.chart-legend__icon--emptyPin{background:transparent;border:2px solid var(--legend-item-color)}.chart-legend__icon--arrow,.chart-legend__icon--emptyArrow{clip-path:polygon(0 35%,58% 35%,58% 10%,100% 50%,58% 90%,58% 65%,0 65%)}.chart-legend__icon--emptyArrow{opacity:.72}.chart-legend__icon--x,.chart-legend__icon--plus,.chart-legend__icon--thickLine{background:transparent;position:relative}.chart-legend__icon--x:before,.chart-legend__icon--x:after,.chart-legend__icon--plus:before,.chart-legend__icon--plus:after{content:\"\";position:absolute;left:50%;top:50%;width:100%;height:2px;background:var(--legend-item-color);border-radius:999px;transform:translate(-50%,-50%)}.chart-legend__icon--x:before{transform:translate(-50%,-50%) rotate(45deg)}.chart-legend__icon--x:after{transform:translate(-50%,-50%) rotate(-45deg)}.chart-legend__icon--plus:after{transform:translate(-50%,-50%) rotate(90deg)}.chart-legend__icon--thickLine{height:4px;width:var(--legend-icon-size);border-radius:999px;background:var(--legend-item-color)}.chart-legend__icon--line-marker{display:inline-flex;align-items:center;justify-content:center;padding:0 2px;background:transparent;border:none;min-width:0;width:auto}.chart-legend__icon-line{flex:1 1 1;min-width:8px;height:2px;background:var(--legend-item-color);border-radius:999px}.chart-legend__item--off .chart-legend__icon,.chart-legend__item--off .chart-legend__icon-path path{filter:grayscale(1);opacity:.68}.chart-legend__item--off .chart-legend__icon--emptyCircle,.chart-legend__item--off .chart-legend__icon--emptyRect,.chart-legend__item--off .chart-legend__icon--emptyRoundRect,.chart-legend__item--off .chart-legend__icon--emptySquare,.chart-legend__item--off .chart-legend__icon--emptyDiamond,.chart-legend__item--off .chart-legend__icon--emptyPin,.chart-legend__item--off .chart-legend__icon--emptyLine{filter:grayscale(1);opacity:.68}.chart-legend__content{display:flex;align-items:center;justify-content:space-between;gap:1rem}.chart-legend__value{font-weight:600;font-size:inherit;font-family:inherit}.chart-legend__item--off .chart-legend__icon--emptyTriangle{filter:grayscale(1);opacity:.68}.chart-legend__label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:inherit;font-family:inherit}.chart-legend__pagination{align-items:center;display:flex;gap:8px;justify-content:flex-end;margin-top:8px}.chart-legend__page{align-items:center;background:transparent;border:1px solid var(--legend-border-color);border-radius:6px;color:inherit;cursor:pointer;display:inline-flex;font:inherit;height:28px;justify-content:center;width:28px}.chart-legend__page:disabled{cursor:default;opacity:.42}.chart-legend__page-count{color:var(--legend-muted-color);font-size:12px}@media (max-width: 640px){.chart-legend__items{padding-bottom:2px}}.chart-legend__action-arrow{width:12px;height:12px;color:var(--legend-muted-color, #9ca3af);flex:0 0 auto}\n"] }]
453
+ args: [{ selector: 'lib-chart-legend', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (config.enabled !== false) {\r\n <nav\r\n class=\"chart-legend\"\r\n [class.chart-legend--vertical]=\"isVerticalLegend\"\r\n [class.chart-legend--scrollable]=\"isScrollableLegend\"\r\n [class.chart-legend--wrap]=\"!isScrollableLegend\"\r\n [class.chart-legend--limited-wrap]=\"isLimitedWrapLegend\"\r\n [ngClass]=\"config.className || null\"\r\n [style.max-height]=\"config.maxHeight || null\"\r\n [style.padding]=\"config.padding || '1rem'\"\r\n [attr.aria-label]=\"config.ariaLabel || 'Chart legend'\"\r\n >\r\n <div class=\"chart-legend__viewport\">\r\n @if (config.title) {\r\n <p\r\n class=\"chart-legend-title\"\r\n [class.chart-legend-title--uppercase]=\"config.legendTitleTransform === 'uppercase'\"\r\n [class.chart-legend-title--lowercase]=\"config.legendTitleTransform === 'lowercase'\"\r\n [class.chart-legend-title--capitalize]=\"config.legendTitleTransform === 'capitalize'\"\r\n [style.--legend-title-color]=\"config.legendTitleTextColor || null\"\r\n [style.--legend-title-font-size]=\"\r\n config.legendTitleFontSize ? config.legendTitleFontSize + 'px' : null\r\n \"\r\n [style.--legend-title-font-style]=\"config.legendTitleFontStyle || null\"\r\n [style.--legend-title-font-weight]=\"config.legendTitleFontWeight || null\"\r\n [style.--legend-title-text-decoration]=\"config.legendTitleTextDecoration || null\"\r\n [style.--legend-title-font-family]=\"config.legendTitleFontFamily || 'initial'\"\r\n >\r\n {{ config.title }}\r\n </p>\r\n }\r\n @if (usesInternalLegendScroll && canScrollLegend) {\r\n <button\r\n type=\"button\"\r\n class=\"chart-legend__scroll-button chart-legend__scroll-button--start\"\r\n [disabled]=\"!canScrollStart\"\r\n (click)=\"scrollLegend(-1, $event)\"\r\n [attr.aria-label]=\"scrollStartAriaLabel\"\r\n >\r\n <img\r\n src=\"images/legend_left.svg\"\r\n [class.chart-legend__scroll-icon--up]=\"scrollsVertically\"\r\n alt=\"left\"\r\n />\r\n </button>\r\n }\r\n\r\n <div #itemsScroller class=\"chart-legend__scroller\" (scroll)=\"updateScrollState()\">\r\n <div\r\n class=\"chart-legend__items\"\r\n role=\"list\"\r\n [class.chart-legend__items--center]=\"\r\n isLegendAlignedCenter && (!usesInternalLegendScroll || !canScrollLegend)\r\n \"\r\n [class.chart-legend__items--end]=\"isLegendAlignedEnd\"\r\n [style.--legend-text-color]=\"config.legendTextColor || null\"\r\n [style.--legend-font-size]=\"config.legendFontSize ? config.legendFontSize + 'px' : null\"\r\n [style.--legend-font-style]=\"config.legendFontStyle || null\"\r\n [style.--legend-font-weight]=\"config.legendFontWeight || null\"\r\n [style.--legend-text-decoration]=\"config.legendTextDecoration || null\"\r\n [style.--legend-font-family]=\"config.legendFontFamily || 'initial'\"\r\n >\r\n @for (group of groupedItems; track trackByGroup($index, group)) {\r\n @if (group.group) {\r\n <div class=\"chart-legend__group-label\">{{ group.group }}</div>\r\n }\r\n\r\n @for (item of group.items; track trackByItem($index, item)) {\r\n <button\r\n type=\"button\"\r\n class=\"chart-legend__item\"\r\n role=\"switch\"\r\n [class.chart-legend__item--off]=\"!item.selected\"\r\n [class.chart-legend__item--disabled]=\"item.disabled\"\r\n [class.chart-legend__item--hovered]=\"state.hoveredName === item.name\"\r\n [disabled]=\"item.disabled\"\r\n [attr.aria-checked]=\"item.selected\"\r\n [attr.aria-label]=\"item.label\"\r\n [style.--legend-item-color]=\"item.color\"\r\n [title]=\"itemTitle(item)\"\r\n (click)=\"toggle(item, $event)\"\r\n (keydown.enter)=\"toggle(item, $event)\"\r\n (keydown.space)=\"toggle(item, $event)\"\r\n (mouseenter)=\"hover(item)\"\r\n (focus)=\"hover(item)\"\r\n (mouseleave)=\"leave(item)\"\r\n (blur)=\"leave(item)\"\r\n >\r\n @if (templateFor(item); as template) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"template\"\r\n [ngTemplateOutletContext]=\"templateContext(item)\"\r\n ></ng-container>\r\n } @else {\r\n @switch (iconRenderType(item)) {\r\n @case ('image') {\r\n @if (isLineMarker(item)) {\r\n <span\r\n class=\"chart-legend__icon chart-legend__icon--line-marker\"\r\n aria-hidden=\"true\"\r\n >\r\n <span class=\"chart-legend__icon-line\"></span>\r\n <img class=\"chart-legend__icon-image\" [src]=\"iconImageSrc(item)\" alt=\"\" />\r\n <span class=\"chart-legend__icon-line\"></span>\r\n </span>\r\n } @else {\r\n <img class=\"chart-legend__icon-image\" [src]=\"iconImageSrc(item)\" alt=\"\" />\r\n }\r\n }\r\n @case ('path') {\r\n @if (isLineMarker(item)) {\r\n <span\r\n class=\"chart-legend__icon chart-legend__icon--line-marker\"\r\n aria-hidden=\"true\"\r\n >\r\n <span class=\"chart-legend__icon-line\"></span>\r\n <svg\r\n class=\"chart-legend__icon-path\"\r\n viewBox=\"-512 -512 1024 1024\"\r\n aria-hidden=\"true\"\r\n >\r\n <path [attr.d]=\"iconPathData(item)\"></path>\r\n </svg>\r\n <span class=\"chart-legend__icon-line\"></span>\r\n </span>\r\n } @else {\r\n <svg\r\n class=\"chart-legend__icon-path\"\r\n viewBox=\"-512 -512 1024 1024\"\r\n aria-hidden=\"true\"\r\n >\r\n <path [attr.d]=\"iconPathData(item)\"></path>\r\n </svg>\r\n }\r\n }\r\n @case ('shape') {\r\n @if (isLineMarker(item)) {\r\n <span\r\n class=\"chart-legend__icon chart-legend__icon--line-marker\"\r\n aria-hidden=\"true\"\r\n >\r\n <span class=\"chart-legend__icon-line\"></span>\r\n <span\r\n class=\"chart-legend__icon chart-legend__icon--marker\"\r\n [ngClass]=\"iconShapeClass(item.icon)\"\r\n ></span>\r\n <span class=\"chart-legend__icon-line\"></span>\r\n </span>\r\n } @else {\r\n <span\r\n class=\"chart-legend__icon\"\r\n [ngClass]=\"iconShapeClass(iconForRender(item))\"\r\n aria-hidden=\"true\"\r\n ></span>\r\n }\r\n }\r\n }\r\n <span class=\"chart-legend__label\">\n {{ item.label }}@if (this.config.showValue && this.config.valueFormatter) {\n :\n }\n </span>\n @if (this.config.showValue && this.config.valueFormatter) {\r\n <span class=\"chart-legend__value\">{{ this.config.valueFormatter(item) }}</span>\r\n }\r\n @if (this.config.showActionArrow) {\r\n @if (this.config.actionArrowTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"this.config.actionArrowTemplate\"\r\n [ngTemplateOutletContext]=\"templateContext(item)\"\r\n ></ng-container>\r\n } @else {\r\n <svg\r\n class=\"chart-legend__action-arrow\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n >\r\n <polyline points=\"9 18 15 12 9 6\"></polyline>\r\n </svg>\r\n }\r\n }\r\n }\r\n </button>\r\n }\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (usesInternalLegendScroll && canScrollLegend) {\r\n <button\r\n type=\"button\"\r\n class=\"chart-legend__scroll-button chart-legend__scroll-button--end\"\r\n [disabled]=\"!canScrollEnd\"\r\n (click)=\"scrollLegend(1, $event)\"\r\n [attr.aria-label]=\"scrollEndAriaLabel\"\r\n >\r\n <img\r\n src=\"images/legend_right.svg\"\r\n [class.chart-legend__scroll-icon--down]=\"scrollsVertically\"\r\n alt=\"right\"\r\n />\r\n </button>\r\n }\r\n </div>\r\n\r\n @if (config.showPagination && pageCount > 1) {\r\n <div class=\"chart-legend__pagination\" aria-label=\"Legend pages\">\r\n <button\r\n type=\"button\"\r\n class=\"chart-legend__page\"\r\n [disabled]=\"state.pageIndex === 0\"\r\n (click)=\"page(-1)\"\r\n aria-label=\"Previous legend page\"\r\n >\r\n &lt;\r\n </button>\r\n <span class=\"chart-legend__page-count\">{{ state.pageIndex + 1 }} / {{ pageCount }}</span>\r\n <button\r\n type=\"button\"\r\n class=\"chart-legend__page\"\r\n [disabled]=\"state.pageIndex + 1 === pageCount\"\r\n (click)=\"page(1)\"\r\n aria-label=\"Next legend page\"\r\n >\r\n &gt;\r\n </button>\r\n </div>\r\n }\r\n </nav>\r\n}\r\n", styles: [":host{display:block;min-height:0;min-width:0}.chart-legend{--legend-text-color: #040d17;--legend-muted-color: #8a94a6;--legend-border-color: #eaf3fd;--legend-hover-bg: rgba(15, 23, 42, .04);--legend-font-size: 14px;--legend-item-min-height: 28px;--legend-row-gap: 8px;--legend-column-gap: 12px;--legend-font-style: normal;--legend-font-weight: 400;--legend-text-decoration: none;--legend-font-family: initial;--legend-title-color: #040d17;--legend-title-font-size: 14px;--legend-title-font-style: normal;--legend-title-font-weight: 400;--legend-title-text-decoration: none;--legend-title-font-family: initial;box-sizing:border-box;min-height:0;min-width:0;width:100%}:host-context(.dark) .chart-legend,:host-context([data-theme=dark]) .chart-legend{--legend-text-color: #e5e7eb;--legend-muted-color: #9ca3af;--legend-border-color: #374151;--legend-hover-bg: rgba(255, 255, 255, .08)}.chart-legend__viewport{align-items:center;display:flex;gap:4px;min-width:0;width:100%}.chart-legend__viewport .chart-legend-title{font-weight:var(--legend-title-font-weight);font-size:var(--legend-title-font-size);font-style:var(--legend-title-font-style);text-decoration:var(--legend-title-text-decoration);font-family:var(--legend-title-font-family);color:var(--legend-title-color);white-space:nowrap;margin:0 8px 0 0}.chart-legend__viewport .chart-legend-title--uppercase{text-transform:uppercase}.chart-legend__viewport .chart-legend-title--lowercase{text-transform:lowercase}.chart-legend__viewport .chart-legend-title--capitalize{text-transform:capitalize}.chart-legend__scroller{flex:1 1 auto;min-height:0;min-width:0;overflow-x:hidden;overflow-y:hidden;scrollbar-width:none}.chart-legend__scroller::-webkit-scrollbar{display:none}.chart-legend--scrollable .chart-legend__scroller{overflow-x:auto;overscroll-behavior-x:contain}.chart-legend--scrollable .chart-legend__scroller::-webkit-scrollbar{display:block;height:6px}.chart-legend__items{display:flex;flex-wrap:nowrap;align-items:center;gap:var(--legend-row-gap) var(--legend-column-gap);min-width:0;color:var(--legend-text-color);font-size:var(--legend-font-size);font-style:var(--legend-font-style);font-weight:var(--legend-font-weight);text-decoration:var(--legend-text-decoration);font-family:var(--legend-font-family)}.chart-legend--scrollable .chart-legend__items{min-width:max-content}.chart-legend--wrap:not(.chart-legend--vertical) .chart-legend__items{flex-wrap:wrap;width:100%}.chart-legend--limited-wrap:not(.chart-legend--vertical) .chart-legend__scroller{max-height:calc(var(--legend-item-min-height) * 2 + var(--legend-row-gap));overflow-y:auto;overscroll-behavior-y:contain}.chart-legend--vertical{height:100%}.chart-legend--vertical .chart-legend__viewport{align-items:stretch;flex-direction:column;height:100%;min-height:0}.chart-legend--vertical .chart-legend__scroller{overflow-x:hidden;overflow-y:hidden}.chart-legend--vertical.chart-legend--scrollable .chart-legend__scroller{overflow-y:auto;overscroll-behavior-y:contain}.chart-legend--vertical .chart-legend__items{align-items:stretch;flex-direction:column;min-width:0;width:100%;height:100%}.chart-legend--vertical.chart-legend--wrap .chart-legend__items{align-content:start;display:grid;grid-auto-flow:column;grid-auto-columns:max-content;grid-template-rows:repeat(auto-fit,minmax(28px,max-content));height:100%;justify-content:start;width:auto}.chart-legend--vertical.chart-legend--limited-wrap .chart-legend__viewport{flex-direction:row}.chart-legend--vertical.chart-legend--limited-wrap .chart-legend__scroller{overflow-x:auto;overflow-y:hidden;overscroll-behavior-x:contain}.chart-legend--vertical.chart-legend--limited-wrap .chart-legend__items{grid-auto-columns:minmax(1,calc((100% - var(--legend-column-gap)) / 2));width:max-content}.chart-legend__items--center{justify-content:center}.chart-legend__items--end{justify-content:flex-end}.chart-legend--vertical.chart-legend--wrap .chart-legend__items--center{align-content:center;justify-content:start}.chart-legend--vertical.chart-legend--wrap .chart-legend__items--end{align-content:end;justify-content:start}.chart-legend__group-label{flex:0 0 auto;color:var(--legend-muted-color);font-size:12px;font-weight:600;line-height:1.2;margin-top:4px}.chart-legend__item{--legend-item-color: #64748b;align-items:center;background:color-mix(in srgb,var(--legend-item-color) 4%,transparent);border:1px solid color-mix(in srgb,var(--legend-item-color) 25%,transparent);border-radius:4px;color:inherit;cursor:pointer;display:inline-flex;font:inherit;gap:8px;line-height:1.2;min-height:28px;min-width:0;padding:4px 8px;touch-action:manipulation;transition:background-color .14s ease,border-color .14s ease,opacity .14s ease}.chart-legend--vertical .chart-legend__item{justify-content:flex-start;width:100%}.chart-legend--vertical.chart-legend--wrap .chart-legend__item{width:auto}.chart-legend--vertical.chart-legend--limited-wrap .chart-legend__item{width:100%}.chart-legend__scroll-button{align-items:center;background:transparent;border:1px solid var(--legend-border-color);border-radius:6px;color:inherit;cursor:pointer;display:inline-flex;flex:0 0 auto;font:inherit;height:28px;justify-content:center;line-height:1;width:28px}.chart-legend--vertical .chart-legend__scroll-button{width:100%}.chart-legend--vertical.chart-legend--limited-wrap .chart-legend__scroll-button{height:auto;min-height:28px;width:28px}.chart-legend__scroll-button img{display:block;height:10px;width:10px}.chart-legend__scroll-icon--up,.chart-legend__scroll-icon--down{transform:rotate(90deg)}.chart-legend__scroll-button:disabled{cursor:default;opacity:.42}.chart-legend__item:hover,.chart-legend__item:focus-visible,.chart-legend__item--hovered{outline:none}.chart-legend__item--off{color:var(--legend-muted-color);filter:grayscale(1);opacity:.68}.chart-legend__item--disabled{cursor:not-allowed;opacity:.48}.chart-legend__icon,.chart-legend__icon-image,.chart-legend__icon-path{--legend-icon-size: 12px;background:var(--legend-item-color);box-sizing:border-box;display:inline-block;flex:0 0 auto;height:var(--legend-icon-size);width:var(--legend-icon-size)}.chart-legend__icon-image,.chart-legend__icon-path{background:transparent;object-fit:contain}.chart-legend__icon-path path{fill:var(--legend-item-color);stroke:var(--legend-item-color)}.chart-legend__icon--line,.chart-legend__icon--emptyLine{height:11px;border-radius:999px;background:linear-gradient(to bottom,transparent 0 4px,var(--legend-item-color) 4px 6px,transparent 6px 100%)}.chart-legend__icon--emptyLine{background:linear-gradient(to bottom,transparent 0 4px,var(--legend-item-color) 4px 6px,transparent 6px 100%)}.chart-legend__icon--area{background:linear-gradient(to bottom,var(--legend-item-color),color-mix(in srgb,var(--legend-item-color) 12%,transparent));border-top:3px solid var(--legend-item-color)}.chart-legend__icon--circle{border-radius:50%}.chart-legend__icon--emptyCircle{background:transparent;border:2px solid var(--legend-item-color);border-radius:50%}.chart-legend__icon--rect,.chart-legend__icon--emptyRect,.chart-legend__icon--square,.chart-legend__icon--emptySquare{border-radius:2px}.chart-legend__icon--emptyRect,.chart-legend__icon--emptySquare{background:transparent;border:2px solid var(--legend-item-color)}.chart-legend__icon--roundRect,.chart-legend__icon--emptyRoundRect{border-radius:6px}.chart-legend__icon--emptyRoundRect{background:transparent;border:2px solid var(--legend-item-color)}.chart-legend__icon--triangle,.chart-legend__icon--emptyTriangle{clip-path:polygon(50% 0,100% 100%,0 100%)}.chart-legend__icon--emptyTriangle{background:var(--legend-item-color)}.chart-legend__icon--diamond,.chart-legend__icon--emptyDiamond{transform:rotate(45deg)}.chart-legend__icon--emptyDiamond{background:transparent;border:2px solid var(--legend-item-color)}.chart-legend__icon--pin,.chart-legend__icon--emptyPin{border-radius:50% 50% 50% 0;transform:rotate(-45deg)}.chart-legend__icon--emptyPin{background:transparent;border:2px solid var(--legend-item-color)}.chart-legend__icon--arrow,.chart-legend__icon--emptyArrow{clip-path:polygon(0 35%,58% 35%,58% 10%,100% 50%,58% 90%,58% 65%,0 65%)}.chart-legend__icon--emptyArrow{opacity:.72}.chart-legend__icon--x,.chart-legend__icon--plus,.chart-legend__icon--thickLine{background:transparent;position:relative}.chart-legend__icon--x:before,.chart-legend__icon--x:after,.chart-legend__icon--plus:before,.chart-legend__icon--plus:after{content:\"\";position:absolute;left:50%;top:50%;width:100%;height:2px;background:var(--legend-item-color);border-radius:999px;transform:translate(-50%,-50%)}.chart-legend__icon--x:before{transform:translate(-50%,-50%) rotate(45deg)}.chart-legend__icon--x:after{transform:translate(-50%,-50%) rotate(-45deg)}.chart-legend__icon--plus:after{transform:translate(-50%,-50%) rotate(90deg)}.chart-legend__icon--thickLine{height:4px;width:var(--legend-icon-size);border-radius:999px;background:var(--legend-item-color)}.chart-legend__icon--line-marker{display:inline-flex;align-items:center;justify-content:center;padding:0 2px;background:transparent;border:none;min-width:0;width:auto}.chart-legend__icon-line{flex:1 1 1;min-width:8px;height:2px;background:var(--legend-item-color);border-radius:999px}.chart-legend__item--off .chart-legend__icon,.chart-legend__item--off .chart-legend__icon-path path{filter:grayscale(1);opacity:.68}.chart-legend__item--off .chart-legend__icon--emptyCircle,.chart-legend__item--off .chart-legend__icon--emptyRect,.chart-legend__item--off .chart-legend__icon--emptyRoundRect,.chart-legend__item--off .chart-legend__icon--emptySquare,.chart-legend__item--off .chart-legend__icon--emptyDiamond,.chart-legend__item--off .chart-legend__icon--emptyPin,.chart-legend__item--off .chart-legend__icon--emptyLine{filter:grayscale(1);opacity:.68}.chart-legend__content{display:flex;align-items:center;justify-content:space-between;gap:1rem}.chart-legend__value{font-weight:600;font-size:inherit;font-family:inherit}.chart-legend__item--off .chart-legend__icon--emptyTriangle{filter:grayscale(1);opacity:.68}.chart-legend__label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:inherit;font-family:inherit}.chart-legend__pagination{align-items:center;display:flex;gap:8px;justify-content:flex-end;margin-top:8px}.chart-legend__page{align-items:center;background:transparent;border:1px solid var(--legend-border-color);border-radius:6px;color:inherit;cursor:pointer;display:inline-flex;font:inherit;height:28px;justify-content:center;width:28px}.chart-legend__page:disabled{cursor:default;opacity:.42}.chart-legend__page-count{color:var(--legend-muted-color);font-size:12px}@media (max-width: 640px){.chart-legend__items{padding-bottom:2px}}.chart-legend__action-arrow{width:12px;height:12px;color:var(--legend-muted-color, #9ca3af);flex:0 0 auto}\n"] }]
454
454
  }], ctorParameters: () => [{ type: ChartLegendAdapter }, { type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
455
455
  type: Inject,
456
456
  args: [PLATFORM_ID]
@@ -3823,20 +3823,23 @@ echarts.use([SankeyChart$1, TooltipComponent, TitleComponent, LegendComponent, C
3823
3823
  class SankeyChart {
3824
3824
  chartService;
3825
3825
  cdr;
3826
+ hostElement;
3826
3827
  config;
3827
3828
  theme;
3828
3829
  events = [];
3829
3830
  chartEvent = new EventEmitter();
3830
3831
  legendEvent = new EventEmitter();
3831
- constructor(chartService, cdr) {
3832
+ constructor(chartService, cdr, hostElement) {
3832
3833
  this.chartService = chartService;
3833
3834
  this.cdr = cdr;
3835
+ this.hostElement = hostElement;
3834
3836
  }
3835
3837
  chartOption = {};
3836
3838
  chartInstance;
3837
3839
  sourceToggleItems = [];
3838
3840
  legendSeries = [];
3839
3841
  previousReactiveSignature = '';
3842
+ resizeObserver;
3840
3843
  /* ------------------ CHANGE HANDLING ------------------ */
3841
3844
  ngOnChanges(changes) {
3842
3845
  if (!this.config)
@@ -3966,6 +3969,12 @@ class SankeyChart {
3966
3969
  },
3967
3970
  label: {
3968
3971
  show: styling?.labels?.showLabels ?? true,
3972
+ // Keep labels within the space between Sankey columns. ECharts then
3973
+ // adds an ellipsis whenever a larger font, wider node, or long name
3974
+ // does not fit.
3975
+ width: this.resolveSankeyLabelWidth(visibleNodeMeta),
3976
+ overflow: 'truncate',
3977
+ ellipsis: '...',
3969
3978
  color: fontColor,
3970
3979
  fontFamily: labelTypography?.reset ? undefined : labelTypography?.fontFamily,
3971
3980
  fontSize: this.clamp(labelTypography?.reset ? undefined : labelTypography?.fontSize, 8, 40),
@@ -4002,6 +4011,8 @@ class SankeyChart {
4002
4011
  get legendConfig() {
4003
4012
  const config = this.config?.styling?.legend;
4004
4013
  const text = config?.text;
4014
+ const titleStyle = config?.titleStyle;
4015
+ const showValueLabels = config?.showValueLabels === true;
4005
4016
  return {
4006
4017
  enabled: this.showLegend,
4007
4018
  position: config?.position ?? 'bottom',
@@ -4009,15 +4020,32 @@ class SankeyChart {
4009
4020
  layout: this.isSideLegend ? 'vertical' : 'horizontal',
4010
4021
  scrollable: true,
4011
4022
  title: config?.title,
4012
- legendType: config?.style ?? 'default',
4013
- showValue: config?.showValueLabels ?? false,
4023
+ legendTitleTextColor: titleStyle?.color,
4024
+ legendTitleFontSize: this.clamp(titleStyle?.fontSize, 8, 40),
4025
+ legendTitleFontFamily: titleStyle?.fontFamily,
4026
+ legendTitleFontWeight: titleStyle?.bold ? 'bold' : undefined,
4027
+ legendTitleFontStyle: titleStyle?.italic ? 'italic' : undefined,
4028
+ legendTitleTextDecoration: titleStyle?.underline ? 'underline' : undefined,
4029
+ legendTitleTransform: titleStyle?.case === 'none' ? undefined : titleStyle?.case,
4030
+ // Sankey legends are informational: selecting an item must not hide a flow.
4031
+ preventLegendClickDefault: true,
4032
+ hoverLink: false,
4033
+ legendType: config?.legendType ?? config?.style ?? 'marker',
4034
+ icon: config?.icon ?? 'circle',
4035
+ // Use a strict boolean check because configuration values can arrive as the
4036
+ // string "false" from form controls; that must not be rendered as a value.
4037
+ showValue: showValueLabels,
4014
4038
  legendTextColor: text?.color,
4015
4039
  legendFontSize: this.clamp(text?.fontSize, 8, 40),
4016
4040
  legendFontFamily: text?.fontFamily,
4017
4041
  legendFontWeight: text?.bold ? 'bold' : undefined,
4018
4042
  legendFontStyle: text?.italic ? 'italic' : undefined,
4019
4043
  legendTextDecoration: text?.underline ? 'underline' : undefined,
4020
- valueFormatter: (item) => this.aggregateLegendValue(item?.raw?.data ?? [], config?.aggregation),
4044
+ ...(showValueLabels
4045
+ ? {
4046
+ valueFormatter: (item) => this.aggregateLegendValue(item?.raw?.data ?? [], config?.aggregation),
4047
+ }
4048
+ : {}),
4021
4049
  };
4022
4050
  }
4023
4051
  toggleSourceNode(name, visible) {
@@ -4208,6 +4236,16 @@ class SankeyChart {
4208
4236
  return alignment;
4209
4237
  return 'left';
4210
4238
  }
4239
+ resolveSankeyLabelWidth(meta) {
4240
+ const chartWidth = this.chartInstance?.getWidth?.() ?? 0;
4241
+ const levelCount = Math.max(...[...meta.values()].map((node) => node.depth), 0) + 1;
4242
+ const nodeWidth = this.clamp(this.config.styling?.node?.thickness ?? this.config.seriesOption?.nodeWidth, 1, 50) ?? 20;
4243
+ const horizontalPadding = 32;
4244
+ const availableWidth = Math.max(chartWidth - horizontalPadding - levelCount * nodeWidth, 0);
4245
+ // A label can occupy half of each gap between adjacent Sankey columns.
4246
+ // Cap it so a simple two-column Sankey does not create excessively long labels.
4247
+ return Math.max(32, Math.min(180, Math.floor(availableWidth / Math.max(levelCount * 2, 1))));
4248
+ }
4211
4249
  totalSourceValue(links, meta) {
4212
4250
  const sourceNames = new Set([...meta.values()].filter((node) => node.role === 'source').map((node) => node.name));
4213
4251
  const total = links
@@ -4336,6 +4374,17 @@ class SankeyChart {
4336
4374
  this.buildOption();
4337
4375
  this.bindEvents();
4338
4376
  }
4377
+ ngAfterViewInit() {
4378
+ if (typeof ResizeObserver === 'undefined')
4379
+ return;
4380
+ this.resizeObserver = new ResizeObserver(() => {
4381
+ if (!this.chartInstance)
4382
+ return;
4383
+ this.chartInstance.resize();
4384
+ this.buildOption();
4385
+ });
4386
+ this.resizeObserver.observe(this.hostElement.nativeElement);
4387
+ }
4339
4388
  /* ------------------ EVENTS ------------------ */
4340
4389
  bindEvents() {
4341
4390
  if (!this.chartInstance)
@@ -4355,18 +4404,19 @@ class SankeyChart {
4355
4404
  }
4356
4405
  /* ------------------ DESTROY ------------------ */
4357
4406
  ngOnDestroy() {
4407
+ this.resizeObserver?.disconnect();
4358
4408
  if (this.chartInstance) {
4359
4409
  this.chartInstance.off();
4360
4410
  this.chartInstance.dispose();
4361
4411
  }
4362
4412
  }
4363
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: SankeyChart, deps: [{ token: Charts }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
4413
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: SankeyChart, deps: [{ token: Charts }, { token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
4364
4414
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: SankeyChart, isStandalone: true, selector: "lib-sankey-chart", inputs: { config: "config", theme: "theme", events: "events" }, outputs: { chartEvent: "chartEvent", legendEvent: "legendEvent" }, providers: [provideEchartsCore({ echarts })], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"sankey-chart-shell\"\n [class.sankey-chart-shell--legend-left]=\"legendPosition === 'left'\"\n [class.sankey-chart-shell--legend-right]=\"legendPosition === 'right'\"\n [class.sankey-chart-shell--legend-bottom]=\"legendPosition === 'bottom'\"\n [class.sankey-chart-shell--with-toggles]=\"showNodeToggles\"\n>\n @if (showNodeToggles && sourceToggleItems.length) {\n <div class=\"sankey-node-toggles\" aria-label=\"Sankey source visibility\">\n @for (item of sourceToggleItems; track item.name) {\n <label class=\"sankey-node-toggle\">\n <input\n type=\"checkbox\"\n [checked]=\"!item.hidden\"\n (change)=\"toggleSourceNode(item.name, $any($event.target).checked)\"\n />\n <span>{{ item.name }}</span>\n </label>\n }\n </div>\n }\n\n @if (showLegend && legendPosition !== 'bottom' && legendPosition !== 'right') {\n <lib-chart-legend\n class=\"sankey-chart-shell__legend\"\n [chart]=\"chartInstance\"\n [series]=\"legendSeries\"\n [colors]=\"config.colors || []\"\n [config]=\"legendConfig\"\n (legendEvent)=\"onLegendEvent($event)\"\n ></lib-chart-legend>\n }\n\n <div\n echarts\n [options]=\"chartOption\"\n [theme]=\"theme\"\n class=\"chart-container\"\n (chartInit)=\"onChartInit($event)\"\n ></div>\n\n @if (showLegend && (legendPosition === 'bottom' || legendPosition === 'right')) {\n <lib-chart-legend\n class=\"sankey-chart-shell__legend\"\n [chart]=\"chartInstance\"\n [series]=\"legendSeries\"\n [colors]=\"config.colors || []\"\n [config]=\"legendConfig\"\n (legendEvent)=\"onLegendEvent($event)\"\n ></lib-chart-legend>\n }\n</div>\n", styles: [".sankey-chart-shell{display:flex;width:100%;height:100%;min-width:0;min-height:0;flex-direction:column;gap:8px}.sankey-chart-shell--legend-left,.sankey-chart-shell--legend-right{flex-direction:row}.sankey-chart-shell--legend-bottom{flex-direction:column}.chart-container{flex:1 1 auto;min-width:0;min-height:0;width:100%;height:100%}.sankey-chart-shell__legend{flex:0 0 auto}.sankey-chart-shell--legend-left .sankey-chart-shell__legend,.sankey-chart-shell--legend-right .sankey-chart-shell__legend{max-width:min(320px,40%)}.sankey-node-toggles{display:flex;flex:0 0 auto;flex-wrap:wrap;gap:8px;align-items:center;min-width:0}.sankey-node-toggle{display:inline-flex;align-items:center;gap:6px;min-height:28px;padding:0 10px;border:1px solid #d7d9dd;border-radius:6px;box-sizing:border-box;background:#fff;color:#252a31;font-family:inherit;font-size:12px;line-height:1;cursor:pointer}.sankey-node-toggle input{width:14px;height:14px;margin:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: NgxEchartsDirective, selector: "echarts, [echarts]", inputs: ["options", "theme", "initOpts", "merge", "autoResize", "loading", "loadingType", "loadingOpts"], outputs: ["chartInit", "optionsError", "chartClick", "chartDblClick", "chartMouseDown", "chartMouseMove", "chartMouseUp", "chartMouseOver", "chartMouseOut", "chartGlobalOut", "chartContextMenu", "chartHighlight", "chartDownplay", "chartSelectChanged", "chartLegendSelectChanged", "chartLegendSelected", "chartLegendUnselected", "chartLegendLegendSelectAll", "chartLegendLegendInverseSelect", "chartLegendScroll", "chartDataZoom", "chartDataRangeSelected", "chartGraphRoam", "chartGeoRoam", "chartTreeRoam", "chartTimelineChanged", "chartTimelinePlayChanged", "chartRestore", "chartDataViewChanged", "chartMagicTypeChanged", "chartGeoSelectChanged", "chartGeoSelected", "chartGeoUnselected", "chartAxisAreaSelected", "chartBrush", "chartBrushEnd", "chartBrushSelected", "chartGlobalCursorTaken", "chartRendered", "chartFinished"], exportAs: ["echarts"] }, { kind: "component", type: ChartLegendComponent, selector: "lib-chart-legend", inputs: ["chart", "series", "colors", "config", "itemTemplate"], outputs: ["legendEvent"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4365
4415
  }
4366
4416
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: SankeyChart, decorators: [{
4367
4417
  type: Component,
4368
4418
  args: [{ selector: 'lib-sankey-chart', imports: [CommonModule, NgxEchartsDirective, ChartLegendComponent], providers: [provideEchartsCore({ echarts })], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"sankey-chart-shell\"\n [class.sankey-chart-shell--legend-left]=\"legendPosition === 'left'\"\n [class.sankey-chart-shell--legend-right]=\"legendPosition === 'right'\"\n [class.sankey-chart-shell--legend-bottom]=\"legendPosition === 'bottom'\"\n [class.sankey-chart-shell--with-toggles]=\"showNodeToggles\"\n>\n @if (showNodeToggles && sourceToggleItems.length) {\n <div class=\"sankey-node-toggles\" aria-label=\"Sankey source visibility\">\n @for (item of sourceToggleItems; track item.name) {\n <label class=\"sankey-node-toggle\">\n <input\n type=\"checkbox\"\n [checked]=\"!item.hidden\"\n (change)=\"toggleSourceNode(item.name, $any($event.target).checked)\"\n />\n <span>{{ item.name }}</span>\n </label>\n }\n </div>\n }\n\n @if (showLegend && legendPosition !== 'bottom' && legendPosition !== 'right') {\n <lib-chart-legend\n class=\"sankey-chart-shell__legend\"\n [chart]=\"chartInstance\"\n [series]=\"legendSeries\"\n [colors]=\"config.colors || []\"\n [config]=\"legendConfig\"\n (legendEvent)=\"onLegendEvent($event)\"\n ></lib-chart-legend>\n }\n\n <div\n echarts\n [options]=\"chartOption\"\n [theme]=\"theme\"\n class=\"chart-container\"\n (chartInit)=\"onChartInit($event)\"\n ></div>\n\n @if (showLegend && (legendPosition === 'bottom' || legendPosition === 'right')) {\n <lib-chart-legend\n class=\"sankey-chart-shell__legend\"\n [chart]=\"chartInstance\"\n [series]=\"legendSeries\"\n [colors]=\"config.colors || []\"\n [config]=\"legendConfig\"\n (legendEvent)=\"onLegendEvent($event)\"\n ></lib-chart-legend>\n }\n</div>\n", styles: [".sankey-chart-shell{display:flex;width:100%;height:100%;min-width:0;min-height:0;flex-direction:column;gap:8px}.sankey-chart-shell--legend-left,.sankey-chart-shell--legend-right{flex-direction:row}.sankey-chart-shell--legend-bottom{flex-direction:column}.chart-container{flex:1 1 auto;min-width:0;min-height:0;width:100%;height:100%}.sankey-chart-shell__legend{flex:0 0 auto}.sankey-chart-shell--legend-left .sankey-chart-shell__legend,.sankey-chart-shell--legend-right .sankey-chart-shell__legend{max-width:min(320px,40%)}.sankey-node-toggles{display:flex;flex:0 0 auto;flex-wrap:wrap;gap:8px;align-items:center;min-width:0}.sankey-node-toggle{display:inline-flex;align-items:center;gap:6px;min-height:28px;padding:0 10px;border:1px solid #d7d9dd;border-radius:6px;box-sizing:border-box;background:#fff;color:#252a31;font-family:inherit;font-size:12px;line-height:1;cursor:pointer}.sankey-node-toggle input{width:14px;height:14px;margin:0}\n"] }]
4369
- }], ctorParameters: () => [{ type: Charts }, { type: i0.ChangeDetectorRef }], propDecorators: { config: [{
4419
+ }], ctorParameters: () => [{ type: Charts }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }], propDecorators: { config: [{
4370
4420
  type: Input
4371
4421
  }], theme: [{
4372
4422
  type: Input
@@ -5125,7 +5175,9 @@ class GaugeChart {
5125
5175
  const range = max - min || 1;
5126
5176
  const displayMin = isPercentage ? 0 : min;
5127
5177
  const displayMax = isPercentage ? 100 : max;
5128
- const displayValue = isPercentage ? this.clamp(((rawValue - min) / range) * 100, 0, 100) : rawValue;
5178
+ const displayValue = isPercentage
5179
+ ? this.clamp(((rawValue - min) / range) * 100, 0, 100)
5180
+ : rawValue;
5129
5181
  const targetValue = this.toFiniteNumber(this.config.targetValue);
5130
5182
  const displayTarget = targetValue === undefined
5131
5183
  ? undefined
@@ -5142,9 +5194,9 @@ class GaugeChart {
5142
5194
  const showMidValue = this.config.showMidValue === true;
5143
5195
  const midValueCount = Math.max(Math.floor(this.config.midValueCount ?? 0), 0);
5144
5196
  const splitNumber = showMidValue && midValueCount > 0 ? midValueCount + 1 : 1;
5145
- const metricName = this.applyTextCase(this.config.name ?? 'Value', style?.metricNameTypography?.case);
5197
+ const metricNameWidth = this.resolveMetricNameWidth();
5198
+ const metricName = this.truncateMetricName(this.applyTextCase(this.config.name ?? 'Value', style?.metricNameTypography?.case), metricNameWidth, style?.metricNameTypography?.fontSize ?? 10);
5146
5199
  const metricValue = this.applyTextCase(this.formatNumber(rawValue, compactNumber, precision), style?.metricValueTypography?.case);
5147
- const progressShow = this.resolveProgressVisibility(echartStyleOption, conditionalFormatting?.enabled === true);
5148
5200
  const generatedGaugeSeries = {
5149
5201
  type: 'gauge',
5150
5202
  min: displayMin,
@@ -5155,11 +5207,22 @@ class GaugeChart {
5155
5207
  radius: DEFAULT_GAUGE_RADIUS,
5156
5208
  splitNumber,
5157
5209
  progress: {
5158
- show: progressShow,
5210
+ show: conditionalFormatting?.type !== 'rule',
5159
5211
  roundCap: false,
5160
5212
  width: barWidth,
5161
5213
  itemStyle: {
5162
- color: activeColor,
5214
+ color: conditionalFormatting?.enabled
5215
+ ? {
5216
+ type: 'linear',
5217
+ x: 0,
5218
+ y: 0,
5219
+ x2: 1,
5220
+ y2: 0,
5221
+ colorStops: colorStops.map((c) => {
5222
+ return { offset: c?.[0], color: c?.[1] };
5223
+ }),
5224
+ }
5225
+ : activeColor,
5163
5226
  borderWidth: borderThickness,
5164
5227
  borderColor: borderThickness ? activeColor : undefined,
5165
5228
  },
@@ -5168,7 +5231,11 @@ class GaugeChart {
5168
5231
  roundCap: false,
5169
5232
  lineStyle: {
5170
5233
  width: barWidth,
5171
- color: colorStops,
5234
+ ...(conditionalFormatting?.enabled &&
5235
+ conditionalFormatting?.type === 'rule' && {
5236
+ color: this.getGaugeAxisColors(conditionalFormatting?.rules || [], displayMin, displayMax, displayValue, style?.barColor?.color || '#4378ea', // progress color
5237
+ style?.rangeColor?.color || '#f2f3f5'),
5238
+ }),
5172
5239
  opacity: 1,
5173
5240
  },
5174
5241
  },
@@ -5228,6 +5295,13 @@ class GaugeChart {
5228
5295
  color: '#6b7280',
5229
5296
  fontSize: 10,
5230
5297
  }),
5298
+ // A metric can be a single, very long word. Give the rich-text
5299
+ // token a responsive width so ECharts truncates it instead of
5300
+ // drawing it beyond the gauge's bounds.
5301
+ width: metricNameWidth,
5302
+ overflow: 'truncate',
5303
+ ellipsis: '...',
5304
+ align: 'center',
5231
5305
  lineHeight: 16,
5232
5306
  },
5233
5307
  value: {
@@ -5246,6 +5320,10 @@ class GaugeChart {
5246
5320
  gaugeSeries['min'] = displayMin;
5247
5321
  gaugeSeries['max'] = displayMax;
5248
5322
  gaugeSeries['data'] = [{ value: displayValue, name: this.config.name ?? 'Value' }];
5323
+ // Typography set through `style` is the public, dynamic API. Preserve any
5324
+ // other detail options from `seriesOption`, but do not let its rich-text
5325
+ // defaults override the metric name/value styles.
5326
+ gaugeSeries['detail'] = this.deepMerge(gaugeSeries['detail'] ?? {}, generatedGaugeSeries.detail);
5249
5327
  const targetPointer = this.calculateTargetPointerGeometry(gaugeSeries);
5250
5328
  const generatedChartOption = {
5251
5329
  backgroundColor: this.config.backgroundColor ?? 'transparent',
@@ -5276,7 +5354,7 @@ class GaugeChart {
5276
5354
  axisLine: {
5277
5355
  lineStyle: {
5278
5356
  width: 0,
5279
- color: [[1, 'transparent']],
5357
+ color: [1, 'transparent'],
5280
5358
  },
5281
5359
  },
5282
5360
  pointer: {
@@ -5304,6 +5382,157 @@ class GaugeChart {
5304
5382
  this.chartInstance.setOption(this.chartOption, true);
5305
5383
  }
5306
5384
  }
5385
+ getRuleColor(rule) {
5386
+ return this.applyOpacity(rule.color, rule.opacity ?? 100);
5387
+ }
5388
+ clamp(value, min, max) {
5389
+ return Math.max(min, Math.min(max, value));
5390
+ }
5391
+ segmentsToColorStops(segments, min, max) {
5392
+ return segments
5393
+ .filter((segment) => segment.end > segment.start)
5394
+ .map((segment) => [this.clamp((segment.end - min) / (max - min), 0, 1), segment.color]);
5395
+ }
5396
+ convertToGaugeValue(value, unit, min, max, actualValue) {
5397
+ if (unit === 'percentage') {
5398
+ const percentage = this.clamp(value, 0, 100);
5399
+ return min + ((actualValue - min) * percentage) / 100;
5400
+ }
5401
+ return value;
5402
+ }
5403
+ convertRuleToSegment(rule, min, max, actualValue) {
5404
+ const value = this.convertToGaugeValue(rule.value, rule.unit, min, max, actualValue);
5405
+ const valueTo = rule.valueTo !== undefined
5406
+ ? this.convertToGaugeValue(rule.valueTo, rule.unit, min, max, actualValue)
5407
+ : undefined;
5408
+ switch (rule.operator) {
5409
+ case '<=':
5410
+ case '<':
5411
+ return {
5412
+ start: min,
5413
+ end: value,
5414
+ color: this.getRuleColor(rule),
5415
+ };
5416
+ case 'between':
5417
+ if (valueTo === undefined) {
5418
+ return null;
5419
+ }
5420
+ return {
5421
+ start: Math.min(value, valueTo),
5422
+ end: Math.max(value, valueTo),
5423
+ color: this.getRuleColor(rule),
5424
+ };
5425
+ case '>=':
5426
+ case '>':
5427
+ return {
5428
+ start: value,
5429
+ end: max,
5430
+ color: this.getRuleColor(rule),
5431
+ };
5432
+ default:
5433
+ return null;
5434
+ }
5435
+ }
5436
+ getGaugeAxisColors(rules, min, max, actualValue, progressColor, axisColor) {
5437
+ if (max <= min) {
5438
+ return [[1, axisColor]];
5439
+ }
5440
+ const actual = this.clamp(actualValue, min, max);
5441
+ // No progress
5442
+ if (actual <= min) {
5443
+ return [[1, axisColor]];
5444
+ }
5445
+ const ruleSegments = rules
5446
+ .map((rule) => this.convertRuleToSegment(rule, min, max, actual))
5447
+ .filter((segment) => segment !== null);
5448
+ /*
5449
+ * Rules are allowed ONLY inside actual progress.
5450
+ */
5451
+ const clippedRules = ruleSegments
5452
+ .map((rule) => ({
5453
+ ...rule,
5454
+ start: Math.max(rule.start, min),
5455
+ end: Math.min(rule.end, actual),
5456
+ }))
5457
+ .filter((rule) => rule.end > rule.start);
5458
+ /*
5459
+ * Build the complete gauge from min → max.
5460
+ */
5461
+ const segments = [];
5462
+ let cursor = min;
5463
+ /*
5464
+ * Sort rules by start position.
5465
+ */
5466
+ clippedRules.sort((a, b) => a.start - b.start);
5467
+ for (const rule of clippedRules) {
5468
+ /*
5469
+ * Gap before rule:
5470
+ * use progress color.
5471
+ */
5472
+ if (rule.start > cursor) {
5473
+ segments.push({
5474
+ start: cursor,
5475
+ end: rule.start,
5476
+ color: progressColor,
5477
+ });
5478
+ }
5479
+ /*
5480
+ * Rule area.
5481
+ */
5482
+ const start = Math.max(cursor, rule.start);
5483
+ if (rule.end > start) {
5484
+ segments.push({
5485
+ start,
5486
+ end: rule.end,
5487
+ color: rule.color,
5488
+ });
5489
+ cursor = Math.max(cursor, rule.end);
5490
+ }
5491
+ }
5492
+ /*
5493
+ * Remaining area inside actual progress.
5494
+ * Use progress color.
5495
+ */
5496
+ if (cursor < actual) {
5497
+ segments.push({
5498
+ start: cursor,
5499
+ end: actual,
5500
+ color: progressColor,
5501
+ });
5502
+ }
5503
+ /*
5504
+ * Everything after actual progress:
5505
+ * use axis color.
5506
+ */
5507
+ if (actual < max) {
5508
+ segments.push({
5509
+ start: actual,
5510
+ end: max,
5511
+ color: axisColor,
5512
+ });
5513
+ }
5514
+ return this.segmentsToColorStops(segments, min, max);
5515
+ }
5516
+ applyOpacity(color, opacity) {
5517
+ const alpha = this.clamp(opacity, 0, 100) / 100;
5518
+ if (color.startsWith('#')) {
5519
+ let hex = color.slice(1);
5520
+ if (hex.length === 3) {
5521
+ hex = hex
5522
+ .split('')
5523
+ .map((char) => char + char)
5524
+ .join('');
5525
+ }
5526
+ if (hex.length === 6) {
5527
+ const number = parseInt(hex, 16);
5528
+ const r = (number >> 16) & 255;
5529
+ const g = (number >> 8) & 255;
5530
+ const b = number & 255;
5531
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
5532
+ }
5533
+ }
5534
+ return color;
5535
+ }
5307
5536
  onChartInit(ec) {
5308
5537
  this.chartInstance = ec;
5309
5538
  this.buildOption();
@@ -5346,7 +5575,8 @@ class GaugeChart {
5346
5575
  const percentage = this.toFiniteNumber(radiusOption.slice(0, -1));
5347
5576
  if (percentage === undefined)
5348
5577
  return undefined;
5349
- return (Math.min(this.chartInstance.getWidth(), this.chartInstance.getHeight()) / 2) * (percentage / 100);
5578
+ return ((Math.min(this.chartInstance.getWidth(), this.chartInstance.getHeight()) / 2) *
5579
+ (percentage / 100));
5350
5580
  }
5351
5581
  observeChartResize() {
5352
5582
  if (typeof ResizeObserver === 'undefined' || !this.chartInstance)
@@ -5443,24 +5673,15 @@ class GaugeChart {
5443
5673
  // width is supplied, so a deliberately thin gauge is not enlarged.
5444
5674
  return this.clamp(configuredWidths.length ? Math.max(...configuredWidths) : fallback, 1, 80);
5445
5675
  }
5446
- resolveProgressVisibility(seriesOption, conditionalEnabled) {
5447
- const configuredProgressShow = seriesOption?.['progress']?.['show'];
5448
- if (typeof configuredProgressShow === 'boolean')
5449
- return configuredProgressShow;
5450
- if (conditionalEnabled)
5451
- return false;
5452
- const configuredAxisColors = seriesOption?.['axisLine']?.['lineStyle']?.['color'];
5453
- if (Array.isArray(configuredAxisColors) && configuredAxisColors.length > 1)
5454
- return false;
5455
- return true;
5456
- }
5457
5676
  mergeChartOptions(generatedOption, customOption) {
5458
5677
  if (!customOption)
5459
5678
  return generatedOption;
5460
5679
  const { series, ...customTopLevelOption } = customOption;
5461
5680
  const mergedOption = this.deepMerge({ ...generatedOption }, customTopLevelOption);
5462
5681
  if (Array.isArray(series)) {
5463
- const generatedSeries = Array.isArray(generatedOption['series']) ? generatedOption['series'] : [];
5682
+ const generatedSeries = Array.isArray(generatedOption['series'])
5683
+ ? generatedOption['series']
5684
+ : [];
5464
5685
  mergedOption['series'] = series.map((seriesOption, index) => this.deepMerge({ ...(generatedSeries[index] ?? {}) }, seriesOption));
5465
5686
  if (generatedSeries.length > series.length) {
5466
5687
  mergedOption['series'].push(...generatedSeries.slice(series.length));
@@ -5507,6 +5728,25 @@ class GaugeChart {
5507
5728
  return 0;
5508
5729
  return values.reduce((sum, value) => sum + value, 0);
5509
5730
  }
5731
+ resolveMetricNameWidth() {
5732
+ // `buildOption` also runs before chart initialisation. Use a conservative
5733
+ // fallback then recalculate from the actual chart dimensions on init and
5734
+ // resize.
5735
+ const chartWidth = this.chartInstance?.getWidth();
5736
+ if (!chartWidth)
5737
+ return 200;
5738
+ return this.clamp(Math.floor(chartWidth * 0.7), 80, 400);
5739
+ }
5740
+ truncateMetricName(name, availableWidth, fontSize) {
5741
+ // Rich-text overflow is not reliably applied to gauge detail text in all
5742
+ // ECharts renderers. Trim the string before it reaches the formatter so a
5743
+ // long word cannot escape the gauge even when it contains no spaces.
5744
+ const averageCharacterWidth = Math.max(fontSize, 8) * 0.62;
5745
+ const maximumCharacters = Math.max(Math.floor(availableWidth / averageCharacterWidth), 1);
5746
+ return name.length > maximumCharacters
5747
+ ? `${name.slice(0, Math.max(maximumCharacters - 3, 1))}...`
5748
+ : name;
5749
+ }
5510
5750
  resolveMetricValues() {
5511
5751
  return (this.config.data ?? [])
5512
5752
  .map((value) => this.toFiniteNumber(value))
@@ -5621,7 +5861,8 @@ class GaugeChart {
5621
5861
  return false;
5622
5862
  if (rule.secondCondition) {
5623
5863
  const second = this.ruleValueToNumber(rule.secondCondition.value, rule.secondCondition.unit, min, max);
5624
- return second !== undefined && this.matchesRuleCondition(value, second, rule.secondCondition.operator);
5864
+ return (second !== undefined &&
5865
+ this.matchesRuleCondition(value, second, rule.secondCondition.operator));
5625
5866
  }
5626
5867
  return true;
5627
5868
  }
@@ -5638,14 +5879,15 @@ class GaugeChart {
5638
5879
  case '=':
5639
5880
  return value === firstValue;
5640
5881
  case 'between':
5641
- return secondValue !== undefined && value >= Math.min(firstValue, secondValue) && value <= Math.max(firstValue, secondValue);
5882
+ return (secondValue !== undefined &&
5883
+ value >= Math.min(firstValue, secondValue) &&
5884
+ value <= Math.max(firstValue, secondValue));
5642
5885
  default:
5643
5886
  return false;
5644
5887
  }
5645
5888
  }
5646
5889
  resolveGradientStops(min, max) {
5647
- const points = [...(this.config.style?.conditionalFormatting?.gradientPoints ?? [])]
5648
- .sort((a, b) => a.position - b.position);
5890
+ const points = [...(this.config.style?.conditionalFormatting?.gradientPoints ?? [])].sort((a, b) => a.position - b.position);
5649
5891
  const normalized = points.length
5650
5892
  ? points
5651
5893
  : [
@@ -5676,7 +5918,7 @@ class GaugeChart {
5676
5918
  if (numeric === undefined)
5677
5919
  return undefined;
5678
5920
  const actual = unit === 'percentage' ? min + (this.clamp(numeric, 0, 100) / 100) * (max - min) : numeric;
5679
- return this.clamp((actual - min) / ((max - min) || 1), 0, 1);
5921
+ return this.clamp((actual - min) / (max - min || 1), 0, 1);
5680
5922
  }
5681
5923
  ruleValueToNumber(value, unit, min, max) {
5682
5924
  const numericValue = this.toFiniteNumber(value);
@@ -5786,9 +6028,6 @@ class GaugeChart {
5786
6028
  }
5787
6029
  return undefined;
5788
6030
  }
5789
- clamp(value, min, max) {
5790
- return Math.min(Math.max(value, min), max);
5791
- }
5792
6031
  ngOnDestroy() {
5793
6032
  this.chartResizeObserver?.disconnect();
5794
6033
  if (this.chartInstance) {