@ruc-lib/metered-progress-bar 2.0.0 → 2.0.1

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.
@@ -1,230 +0,0 @@
1
- import * as i0 from '@angular/core';
2
- import { Component, Input, NgModule } from '@angular/core';
3
- import * as i1 from '@angular/common';
4
- import { CommonModule } from '@angular/common';
5
- import { MatIconModule } from '@angular/material/icon';
6
-
7
- var LablePositionEnums;
8
- (function (LablePositionEnums) {
9
- LablePositionEnums["left"] = "left";
10
- LablePositionEnums["right"] = "right";
11
- LablePositionEnums["same"] = "same";
12
- LablePositionEnums["top"] = "top";
13
- LablePositionEnums["bottom"] = "bottom";
14
- })(LablePositionEnums || (LablePositionEnums = {}));
15
-
16
- class RucMeteredProgressBarComponent {
17
- constructor() {
18
- this.hoveredCategoryDetail = null;
19
- this.hoverLabelStyle = { left: '0px', top: '-28px', display: 'none', transform: 'translateX(-50%)' };
20
- this.progressPercentage = 0;
21
- }
22
- /**
23
- * Calculates the total value of all categories.
24
- * @returns The sum of all category values.
25
- */
26
- get totalValue() {
27
- return this.rucInputData.categories.reduce((sum, category) => sum + category.value, 0);
28
- }
29
- /**
30
- * Calculates the overall progress percentage of the bar based on total value, min, and max.
31
- * @returns The progress as a percentage (0-100).
32
- */
33
- get progress() {
34
- return ((this.totalValue - this.rucInputData.min) / (this.rucInputData.max - this.rucInputData.min)) * 100;
35
- }
36
- /**
37
- * Determines if the progress bar is oriented vertically.
38
- * @returns True if the orientation is 'vertical', false otherwise.
39
- */
40
- get isVertical() {
41
- return this.rucInputData.orientation === 'vertical';
42
- }
43
- /**
44
- * Generates the CSS linear-gradient string for the progress bar.
45
- * The gradient is composed of segments based on category values and colors.
46
- * If no categories or total value is zero, it returns a transparent gradient.
47
- * @returns A CSS linear-gradient string.
48
- */
49
- get progressStyles() {
50
- var _a;
51
- const direction = this.isVertical ? 'to bottom' : 'to right';
52
- if (!this.rucInputData || !this.rucInputData.categories) {
53
- return { background: 'transparent' };
54
- }
55
- const total = this.totalValue;
56
- const colorStops = [];
57
- let cumulativePercentage = 0;
58
- if (total > 0) {
59
- this.rucInputData.categories.forEach(category => {
60
- if (category.value <= 0)
61
- return; // Skip categories with zero or negative contribution
62
- const segmentPercentage = (category.value / total) * 100;
63
- const color = category.color;
64
- // Add start of the segment using the previous cumulative percentage
65
- colorStops.push(`${color} ${cumulativePercentage}%`);
66
- // Update cumulative percentage for the end of this segment
67
- cumulativePercentage += segmentPercentage;
68
- // Add end of the segment
69
- // Use Math.min to cap at 100% in case of floating point overshoot on the last segment
70
- colorStops.push(`${color} ${Math.min(cumulativePercentage, 100)}%`);
71
- });
72
- }
73
- if (colorStops.length === 0) {
74
- return { background: 'transparent' };
75
- }
76
- const baseGradient = `linear-gradient(${direction}, ${colorStops.join(', ')})`;
77
- const styles = {};
78
- const barStyle = (_a = this.rucInputData) === null || _a === void 0 ? void 0 : _a.barStyle;
79
- switch (barStyle) {
80
- case 'stripe':
81
- // This uses multiple backgrounds for an overlay effect, as requested.
82
- styles['background'] = `repeating-linear-gradient(-45deg, transparent, transparent 5px, rgba(0, 0, 0, 0.1) 5px, rgba(0, 0, 0, 0.1) 10px), ${baseGradient}`;
83
- break;
84
- case 'circle': {
85
- // This uses a mask. The background is the color, the mask cuts out the shape.
86
- styles['background'] = baseGradient;
87
- // A repeating pattern of circles. Each circle has a diameter of 8px, with a 4px gap.
88
- const circleMask = 'radial-gradient(circle, black 4px, transparent 4px) 0 0 / 12px 12px';
89
- styles['-webkit-mask'] = circleMask;
90
- styles['mask'] = circleMask;
91
- break;
92
- }
93
- case 'rectangle': {
94
- styles['background'] = baseGradient;
95
- // For vertical bar, create horizontal rectangles (0deg). For horizontal bar, create vertical rectangles (90deg).
96
- const rectDirection = this.isVertical ? '0deg' : '90deg';
97
- // A repeating pattern of bars. Each bar is 6px wide with a 6px gap.
98
- const rectangleMask = `repeating-linear-gradient(${rectDirection}, black, black 6px, transparent 6px, transparent 12px)`;
99
- styles['-webkit-mask'] = rectangleMask;
100
- styles['mask'] = rectangleMask;
101
- break;
102
- }
103
- default: // 'solid' or undefined
104
- styles['background'] = baseGradient;
105
- break;
106
- }
107
- return styles;
108
- }
109
- /**
110
- * Handles mouse movement over the progress bar to display category-specific hover details.
111
- * It calculates the hovered segment based on mouse position and updates the hover label.
112
- * @param event The MouseEvent object.
113
- */
114
- onProgressMouseMove(event) {
115
- const progressBarElement = event.target;
116
- let currentCumulativeGradientPct = 0;
117
- let foundCategoryForHover = null;
118
- let hoverPercentage_onFilledBar = 0;
119
- let mousePositionWithinProgressDiv = 0;
120
- if (this.isVertical) {
121
- mousePositionWithinProgressDiv = event.offsetY; // Y position within the .progress div
122
- const filledHeightPx = progressBarElement.offsetHeight;
123
- if (filledHeightPx <= 0) { // Avoid division by zero if element has no height
124
- this.onProgressMouseLeave();
125
- return;
126
- }
127
- hoverPercentage_onFilledBar = (mousePositionWithinProgressDiv / filledHeightPx) * 100;
128
- }
129
- else { // Horizontal
130
- mousePositionWithinProgressDiv = event.offsetX; // X position within the .progress div
131
- const filledWidthPx = progressBarElement.offsetWidth;
132
- if (filledWidthPx <= 0) { // Avoid division by zero if element has no width
133
- this.onProgressMouseLeave();
134
- return;
135
- }
136
- hoverPercentage_onFilledBar = (mousePositionWithinProgressDiv / filledWidthPx) * 100;
137
- }
138
- if (this.totalValue > 0) {
139
- for (const category of this.rucInputData.categories) {
140
- if (category.value <= 0)
141
- continue; // Skip categories with zero or negative contribution
142
- const segmentGradientPct = (category.value / this.totalValue) * 100;
143
- const segmentStartGradientPct = currentCumulativeGradientPct;
144
- const segmentEndGradientPct = currentCumulativeGradientPct + segmentGradientPct;
145
- // Ensure hoverPercentage is within the segment, handling potential floating point inaccuracies for the last segment
146
- if (hoverPercentage_onFilledBar >= segmentStartGradientPct && // Check if mouse is within or at the start of the segment
147
- (hoverPercentage_onFilledBar < segmentEndGradientPct ||
148
- (segmentEndGradientPct >= 99.99 && hoverPercentage_onFilledBar <= 100.01))) { // Tolerate slight overshoot for last segment
149
- foundCategoryForHover = category;
150
- break;
151
- }
152
- currentCumulativeGradientPct = segmentEndGradientPct;
153
- }
154
- }
155
- if (foundCategoryForHover) {
156
- const percentageOfMax = (foundCategoryForHover.value / this.rucInputData.max) * 100; // Calculate percentage relative to max value
157
- this.hoveredCategoryDetail = { category: foundCategoryForHover, percentageText: percentageOfMax.toFixed(0) + '%' };
158
- if (this.isVertical) {
159
- this.hoverLabelStyle = {
160
- left: 'calc(100% + 5px)',
161
- top: mousePositionWithinProgressDiv + 'px',
162
- display: 'block',
163
- transform: 'translateY(-50%)' // Vertically center label on mouse Y
164
- };
165
- }
166
- else {
167
- this.hoverLabelStyle = {
168
- left: mousePositionWithinProgressDiv + 'px',
169
- top: '-28px',
170
- display: 'block',
171
- transform: 'translateX(-50%)' // Horizontally center label on mouse X
172
- };
173
- }
174
- }
175
- else {
176
- this.hoveredCategoryDetail = null;
177
- this.hoverLabelStyle = Object.assign(Object.assign({}, this.hoverLabelStyle), { display: 'none' });
178
- }
179
- }
180
- /**
181
- * Hides the hover label when the mouse leaves the progress bar.
182
- */
183
- onProgressMouseLeave() {
184
- this.hoveredCategoryDetail = null;
185
- this.hoverLabelStyle = Object.assign(Object.assign({}, this.hoverLabelStyle), { display: 'none' });
186
- }
187
- /**
188
- * get the label position string value
189
- */
190
- get LablePositionEnums() {
191
- return LablePositionEnums;
192
- }
193
- }
194
- RucMeteredProgressBarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RucMeteredProgressBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
195
- RucMeteredProgressBarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: RucMeteredProgressBarComponent, selector: "uxp-ruc-metered-progress-bar", inputs: { rucInputData: "rucInputData", customTheme: "customTheme" }, ngImport: i0, template: "<div class=\"progress-container\" class={{customTheme}} [class.vertical]=\"isVertical\" [class.horizontal]=\"!isVertical\">\r\n <div class=\"progress-bar\">\r\n <!-- Removed (mouseenter) and (mouseleave) from progress-bar if only category hover is needed -->\r\n <div *ngIf=\"rucInputData.barLabels\" class=\"progress-label-container {{rucInputData.orientation}}\">\r\n <span class=\"progress-label\">{{progress | number:'1.0-0'}}% of {{rucInputData.max}} {{rucInputData.unitType}}\r\n Used</span>\r\n </div>\r\n <div class=\"progress\" [style.width]=\"isVertical ? '100%' : progress + '%'\"\r\n [style.height]=\"isVertical ? progress + '%' : '100%'\"\r\n [style.transition]=\"rucInputData.orientation === 'vertical' ? 'height 0.3s ease' : 'width 0.3s ease'\"\r\n [ngStyle]=\"progressStyles\">\r\n <!-- This div is now only for displaying the colored bar -->\r\n </div>\r\n <!-- The hover label is now a sibling to .progress, positioned absolutely within .progress-bar -->\r\n <div class=\"hover-label\" *ngIf=\"hoveredCategoryDetail\" [ngStyle]=\"hoverLabelStyle\">\r\n {{hoveredCategoryDetail.category.label}}: {{hoveredCategoryDetail.percentageText}}\r\n </div>\r\n <!-- This overlay is now a sibling to .progress, sized to match it, to reliably capture mouse events -->\r\n <div class=\"progress-event-overlay\" [style.width]=\"isVertical ? '100%' : progress + '%'\"\r\n [style.height]=\"isVertical ? progress + '%' : '100%'\" (mousemove)=\"onProgressMouseMove($event)\"\r\n (mouseleave)=\"onProgressMouseLeave()\"></div>\r\n </div>\r\n <div class=\"categories-container\" *ngIf=\"rucInputData.categories.length > 0\">\r\n <div *ngIf=\"rucInputData.showCategoryLabels && rucInputData.categoryLabelStyle === 'basic'\" [ngClass]=\"{\r\n 'categories-block-top': !isVertical && (rucInputData.categoryLabelsOrientation === 'top' || rucInputData.categoryLabelsOrientation === 'same'),\r\n 'categories-block-left': isVertical && (rucInputData.categoryLabelsOrientation === 'left' || rucInputData.categoryLabelsOrientation === 'same'),\r\n 'categories-block-right': isVertical && !(rucInputData.categoryLabelsOrientation === 'left' || rucInputData.categoryLabelsOrientation === 'same')\r\n }\" class=\"categories\">\r\n <div class=\"category\" *ngFor=\"let category of rucInputData.categories\" [style.color]=\"category.color\">\r\n <ng-container *ngIf=\"category.icon !== undefined\">\r\n <div *ngIf=\"category.icon; else colorDotBasic\" class=\"category-icon-wrapper\">\r\n <i class=\"material-icons\" [style.color]=\"category.color\">{{ category.icon }}</i>\r\n </div>\r\n <ng-template #colorDotBasic>\r\n <div class=\"category-color\">\r\n <div class=\"color-gradient\"\r\n [style.background]=\"category.color ? 'linear-gradient(to right, ' + category.color + ', ' + category.color + ')' : ''\">\r\n </div>\r\n </div>\r\n </ng-template>\r\n </ng-container>\r\n <span class=\"category-label\">{{category.label}}</span>\r\n <span class=\"category-value\">({{(category.value / rucInputData.max * 100) | number:'1.0-0' }}%)</span>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"rucInputData.showCategoryLabels && rucInputData.categoryLabelStyle === 'widget'\"\r\n class=\"categories widget-style\" [ngClass]=\"{\r\n 'categories-block-top': !isVertical && (rucInputData.categoryLabelsOrientation === LablePositionEnums.top || rucInputData.categoryLabelsOrientation === LablePositionEnums.same),\r\n 'categories-block-left': isVertical && (rucInputData.categoryLabelsOrientation === LablePositionEnums.left || rucInputData.categoryLabelsOrientation === LablePositionEnums.same),\r\n 'categories-block-right': isVertical && !(rucInputData.categoryLabelsOrientation === LablePositionEnums.left || rucInputData.categoryLabelsOrientation === LablePositionEnums.same)\r\n }\">\r\n <ng-container *ngFor=\"let category of rucInputData.categories\">\r\n <div class=\"widget-category\">\r\n <div class=\"widget-content\">\r\n <div class=\"widget-icon-box\">\r\n <ng-container *ngIf=\"category.icon !== undefined\">\r\n <div *ngIf=\"category.icon; else colorDotWidget\" class=\"widget-icon\">\r\n <i class=\"material-icons\" [style.color]=\"category.color\">{{ category.icon }}</i>\r\n </div>\r\n <ng-template #colorDotWidget>\r\n <div class=\"category-color\">\r\n <div class=\"color-gradient\"\r\n [style.background]=\"category.color ? 'linear-gradient(to right, ' + category.color + ', ' + category.color + ')' : ''\">\r\n </div>\r\n </div>\r\n </ng-template>\r\n </ng-container>\r\n <div class=\"widget-label\">{{category.label}}</div>\r\n </div>\r\n </div>\r\n <div class=\"widget-value\">\r\n <div>{{category.value}}</div>\r\n </div>\r\n </div>\r\n\r\n\r\n </ng-container>\r\n </div>\r\n\r\n </div>\r\n</div>", styles: [".progress-container{position:relative;margin:20px 0}.progress-container.horizontal{width:100%;height:35px}.progress-container.horizontal .progress-bar{width:100%;height:42%}.progress-container.vertical{width:60px;height:320px;margin:0 auto}.progress-container.vertical .progress-bar{width:24%;height:100%}.progress-label-container{position:absolute;z-index:2;width:100%;height:100%;pointer-events:none;display:flex}.progress-label-container.horizontal{justify-content:right;align-items:flex-end;bottom:15px}.progress-label-container.vertical{justify-content:flex-start;align-items:flex-end;left:35px}.progress-label{padding:2px 5px;font-size:12px;color:#333;white-space:nowrap}.progress-label-container.horizontal .progress-label{margin-top:5px;margin-right:5px}.progress-label-container.vertical .progress-label{transform:rotate(-90deg);transform-origin:bottom left;margin-right:5px}.progress-bar{position:relative;background:white;border:1px solid #e0e0e0;border-radius:4px}.progress-bar .hover-label{position:absolute;top:-28px;left:50%;transform:translate(-50%);background-color:#000c;color:#fff;padding:4px 8px;border-radius:4px;font-size:.8em;z-index:5;white-space:nowrap;pointer-events:none}.progress-event-overlay{position:absolute;top:0;left:0;z-index:4}.progress{position:relative;background:#2196F3;transition:width .3s ease,height .3s ease}.progress-bar.horizontal .progress{width:100%;height:100%}.progress-bar.vertical .progress{width:100%;height:0}.icons-container{position:absolute;display:flex;justify-content:space-between;width:100%;height:100%;align-items:center}.icons-container i{position:absolute;font-size:1.2em;color:#fff}.start-icon{left:0}.end-icon{right:0}.above-threshold{color:gold}.categories-container{width:100%;box-sizing:border-box}.categories{display:flex;flex-direction:row;flex-wrap:wrap;gap:1px}.categories-block-top,.categories-block-bottom,.categories-block-left,.categories-block-right{position:absolute;z-index:1}.categories-block-top{bottom:100%;left:0;padding-bottom:8px}.categories-block-bottom{top:100%;left:0;padding-top:10px}.categories-block-left{right:100%;top:0;padding-right:8px;width:200px}.categories-block-left .categories{flex-direction:inherit;align-items:flex-start;gap:0px}.categories-block-right{left:100%;top:0;padding-left:8px;width:200px}.categories-block-right .categories{flex-direction:inherit;align-items:flex-start;gap:0px}.category{display:flex;align-items:center;gap:6px;padding:8px;border-radius:4px}.category-label{font-weight:500}.category-value{color:#666;font-size:.9em}.category-color{width:10px;height:10px;border-radius:50%;overflow:hidden;flex-shrink:0}.category-icon-wrapper{display:flex;align-items:center;justify-content:center;width:100%;height:100%}.color-gradient{width:100%;height:100%}.categories.widget-style{display:flex;flex-wrap:wrap;gap:10px;justify-content:flex-start;align-items:flex-start;margin:10px 0}.categories.widget-style .widget-category{width:calc(25% - 7.5px);min-width:159px;box-sizing:border-box;flex-shrink:0;flex-grow:0}@media (max-width: 1200px){.categories.widget-style .widget-category{width:calc(33.33% - 6.66px)}}@media (max-width: 768px){.categories.widget-style .widget-category{width:calc(50% - 5px)}}@media (max-width: 480px){.categories.widget-style .widget-category{width:100%}}.categories-block-left,.categories-block-right{flex-direction:inherit;align-items:flex-start;gap:10px}.categories-block-left .widget-category,.categories-block-right .widget-category{width:100%;max-width:none}.widget-category{background-color:#fff;border:1px solid #e0e0e0;border-radius:8px;padding:10px 15px;box-shadow:0 2px 4px #0000001a}.widget-content{display:flex;width:100%;align-items:center;margin:0}.widget-icon{border:1px solid #ddd;border-radius:10px;width:35px;height:35px;line-height:45px;text-align:center;background-color:#fdfdfd}.widget-content .category-color{margin-right:35px}.widget-icon,.widget-color{margin-right:8px;flex-shrink:0}.widget-color{width:24px;height:24px;border-radius:50%}.widget-label{flex-grow:1;text-align:left;display:block}.widget-value{font-weight:700;flex-shrink:0;margin-left:45px;text-align:left;margin-top:5px}.widget-icon-box{display:flex;align-items:center}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: i1.DecimalPipe, name: "number" }] });
196
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RucMeteredProgressBarComponent, decorators: [{
197
- type: Component,
198
- args: [{ selector: 'uxp-ruc-metered-progress-bar', template: "<div class=\"progress-container\" class={{customTheme}} [class.vertical]=\"isVertical\" [class.horizontal]=\"!isVertical\">\r\n <div class=\"progress-bar\">\r\n <!-- Removed (mouseenter) and (mouseleave) from progress-bar if only category hover is needed -->\r\n <div *ngIf=\"rucInputData.barLabels\" class=\"progress-label-container {{rucInputData.orientation}}\">\r\n <span class=\"progress-label\">{{progress | number:'1.0-0'}}% of {{rucInputData.max}} {{rucInputData.unitType}}\r\n Used</span>\r\n </div>\r\n <div class=\"progress\" [style.width]=\"isVertical ? '100%' : progress + '%'\"\r\n [style.height]=\"isVertical ? progress + '%' : '100%'\"\r\n [style.transition]=\"rucInputData.orientation === 'vertical' ? 'height 0.3s ease' : 'width 0.3s ease'\"\r\n [ngStyle]=\"progressStyles\">\r\n <!-- This div is now only for displaying the colored bar -->\r\n </div>\r\n <!-- The hover label is now a sibling to .progress, positioned absolutely within .progress-bar -->\r\n <div class=\"hover-label\" *ngIf=\"hoveredCategoryDetail\" [ngStyle]=\"hoverLabelStyle\">\r\n {{hoveredCategoryDetail.category.label}}: {{hoveredCategoryDetail.percentageText}}\r\n </div>\r\n <!-- This overlay is now a sibling to .progress, sized to match it, to reliably capture mouse events -->\r\n <div class=\"progress-event-overlay\" [style.width]=\"isVertical ? '100%' : progress + '%'\"\r\n [style.height]=\"isVertical ? progress + '%' : '100%'\" (mousemove)=\"onProgressMouseMove($event)\"\r\n (mouseleave)=\"onProgressMouseLeave()\"></div>\r\n </div>\r\n <div class=\"categories-container\" *ngIf=\"rucInputData.categories.length > 0\">\r\n <div *ngIf=\"rucInputData.showCategoryLabels && rucInputData.categoryLabelStyle === 'basic'\" [ngClass]=\"{\r\n 'categories-block-top': !isVertical && (rucInputData.categoryLabelsOrientation === 'top' || rucInputData.categoryLabelsOrientation === 'same'),\r\n 'categories-block-left': isVertical && (rucInputData.categoryLabelsOrientation === 'left' || rucInputData.categoryLabelsOrientation === 'same'),\r\n 'categories-block-right': isVertical && !(rucInputData.categoryLabelsOrientation === 'left' || rucInputData.categoryLabelsOrientation === 'same')\r\n }\" class=\"categories\">\r\n <div class=\"category\" *ngFor=\"let category of rucInputData.categories\" [style.color]=\"category.color\">\r\n <ng-container *ngIf=\"category.icon !== undefined\">\r\n <div *ngIf=\"category.icon; else colorDotBasic\" class=\"category-icon-wrapper\">\r\n <i class=\"material-icons\" [style.color]=\"category.color\">{{ category.icon }}</i>\r\n </div>\r\n <ng-template #colorDotBasic>\r\n <div class=\"category-color\">\r\n <div class=\"color-gradient\"\r\n [style.background]=\"category.color ? 'linear-gradient(to right, ' + category.color + ', ' + category.color + ')' : ''\">\r\n </div>\r\n </div>\r\n </ng-template>\r\n </ng-container>\r\n <span class=\"category-label\">{{category.label}}</span>\r\n <span class=\"category-value\">({{(category.value / rucInputData.max * 100) | number:'1.0-0' }}%)</span>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"rucInputData.showCategoryLabels && rucInputData.categoryLabelStyle === 'widget'\"\r\n class=\"categories widget-style\" [ngClass]=\"{\r\n 'categories-block-top': !isVertical && (rucInputData.categoryLabelsOrientation === LablePositionEnums.top || rucInputData.categoryLabelsOrientation === LablePositionEnums.same),\r\n 'categories-block-left': isVertical && (rucInputData.categoryLabelsOrientation === LablePositionEnums.left || rucInputData.categoryLabelsOrientation === LablePositionEnums.same),\r\n 'categories-block-right': isVertical && !(rucInputData.categoryLabelsOrientation === LablePositionEnums.left || rucInputData.categoryLabelsOrientation === LablePositionEnums.same)\r\n }\">\r\n <ng-container *ngFor=\"let category of rucInputData.categories\">\r\n <div class=\"widget-category\">\r\n <div class=\"widget-content\">\r\n <div class=\"widget-icon-box\">\r\n <ng-container *ngIf=\"category.icon !== undefined\">\r\n <div *ngIf=\"category.icon; else colorDotWidget\" class=\"widget-icon\">\r\n <i class=\"material-icons\" [style.color]=\"category.color\">{{ category.icon }}</i>\r\n </div>\r\n <ng-template #colorDotWidget>\r\n <div class=\"category-color\">\r\n <div class=\"color-gradient\"\r\n [style.background]=\"category.color ? 'linear-gradient(to right, ' + category.color + ', ' + category.color + ')' : ''\">\r\n </div>\r\n </div>\r\n </ng-template>\r\n </ng-container>\r\n <div class=\"widget-label\">{{category.label}}</div>\r\n </div>\r\n </div>\r\n <div class=\"widget-value\">\r\n <div>{{category.value}}</div>\r\n </div>\r\n </div>\r\n\r\n\r\n </ng-container>\r\n </div>\r\n\r\n </div>\r\n</div>", styles: [".progress-container{position:relative;margin:20px 0}.progress-container.horizontal{width:100%;height:35px}.progress-container.horizontal .progress-bar{width:100%;height:42%}.progress-container.vertical{width:60px;height:320px;margin:0 auto}.progress-container.vertical .progress-bar{width:24%;height:100%}.progress-label-container{position:absolute;z-index:2;width:100%;height:100%;pointer-events:none;display:flex}.progress-label-container.horizontal{justify-content:right;align-items:flex-end;bottom:15px}.progress-label-container.vertical{justify-content:flex-start;align-items:flex-end;left:35px}.progress-label{padding:2px 5px;font-size:12px;color:#333;white-space:nowrap}.progress-label-container.horizontal .progress-label{margin-top:5px;margin-right:5px}.progress-label-container.vertical .progress-label{transform:rotate(-90deg);transform-origin:bottom left;margin-right:5px}.progress-bar{position:relative;background:white;border:1px solid #e0e0e0;border-radius:4px}.progress-bar .hover-label{position:absolute;top:-28px;left:50%;transform:translate(-50%);background-color:#000c;color:#fff;padding:4px 8px;border-radius:4px;font-size:.8em;z-index:5;white-space:nowrap;pointer-events:none}.progress-event-overlay{position:absolute;top:0;left:0;z-index:4}.progress{position:relative;background:#2196F3;transition:width .3s ease,height .3s ease}.progress-bar.horizontal .progress{width:100%;height:100%}.progress-bar.vertical .progress{width:100%;height:0}.icons-container{position:absolute;display:flex;justify-content:space-between;width:100%;height:100%;align-items:center}.icons-container i{position:absolute;font-size:1.2em;color:#fff}.start-icon{left:0}.end-icon{right:0}.above-threshold{color:gold}.categories-container{width:100%;box-sizing:border-box}.categories{display:flex;flex-direction:row;flex-wrap:wrap;gap:1px}.categories-block-top,.categories-block-bottom,.categories-block-left,.categories-block-right{position:absolute;z-index:1}.categories-block-top{bottom:100%;left:0;padding-bottom:8px}.categories-block-bottom{top:100%;left:0;padding-top:10px}.categories-block-left{right:100%;top:0;padding-right:8px;width:200px}.categories-block-left .categories{flex-direction:inherit;align-items:flex-start;gap:0px}.categories-block-right{left:100%;top:0;padding-left:8px;width:200px}.categories-block-right .categories{flex-direction:inherit;align-items:flex-start;gap:0px}.category{display:flex;align-items:center;gap:6px;padding:8px;border-radius:4px}.category-label{font-weight:500}.category-value{color:#666;font-size:.9em}.category-color{width:10px;height:10px;border-radius:50%;overflow:hidden;flex-shrink:0}.category-icon-wrapper{display:flex;align-items:center;justify-content:center;width:100%;height:100%}.color-gradient{width:100%;height:100%}.categories.widget-style{display:flex;flex-wrap:wrap;gap:10px;justify-content:flex-start;align-items:flex-start;margin:10px 0}.categories.widget-style .widget-category{width:calc(25% - 7.5px);min-width:159px;box-sizing:border-box;flex-shrink:0;flex-grow:0}@media (max-width: 1200px){.categories.widget-style .widget-category{width:calc(33.33% - 6.66px)}}@media (max-width: 768px){.categories.widget-style .widget-category{width:calc(50% - 5px)}}@media (max-width: 480px){.categories.widget-style .widget-category{width:100%}}.categories-block-left,.categories-block-right{flex-direction:inherit;align-items:flex-start;gap:10px}.categories-block-left .widget-category,.categories-block-right .widget-category{width:100%;max-width:none}.widget-category{background-color:#fff;border:1px solid #e0e0e0;border-radius:8px;padding:10px 15px;box-shadow:0 2px 4px #0000001a}.widget-content{display:flex;width:100%;align-items:center;margin:0}.widget-icon{border:1px solid #ddd;border-radius:10px;width:35px;height:35px;line-height:45px;text-align:center;background-color:#fdfdfd}.widget-content .category-color{margin-right:35px}.widget-icon,.widget-color{margin-right:8px;flex-shrink:0}.widget-color{width:24px;height:24px;border-radius:50%}.widget-label{flex-grow:1;text-align:left;display:block}.widget-value{font-weight:700;flex-shrink:0;margin-left:45px;text-align:left;margin-top:5px}.widget-icon-box{display:flex;align-items:center}\n"] }]
199
- }], propDecorators: { rucInputData: [{
200
- type: Input
201
- }], customTheme: [{
202
- type: Input
203
- }] } });
204
-
205
- // import { RucMeteredProgressBarComponent } from './ruc-metered-progress-bar/ruc-metered-progress-bar/ruc-metered-progress-bar.component';
206
- class RuclibMeteredProgressBarModule {
207
- }
208
- RuclibMeteredProgressBarModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RuclibMeteredProgressBarModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
209
- RuclibMeteredProgressBarModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: RuclibMeteredProgressBarModule, declarations: [RucMeteredProgressBarComponent], imports: [CommonModule, MatIconModule], exports: [RucMeteredProgressBarComponent] });
210
- RuclibMeteredProgressBarModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RuclibMeteredProgressBarModule, imports: [CommonModule, MatIconModule] });
211
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RuclibMeteredProgressBarModule, decorators: [{
212
- type: NgModule,
213
- args: [{
214
- imports: [CommonModule, MatIconModule],
215
- declarations: [RucMeteredProgressBarComponent],
216
- exports: [RucMeteredProgressBarComponent],
217
- }]
218
- }] });
219
-
220
- class MeteredBarConfig {
221
- }
222
- class CategoryConfig {
223
- }
224
-
225
- /**
226
- * Generated bundle index. Do not edit.
227
- */
228
-
229
- export { CategoryConfig, MeteredBarConfig, RucMeteredProgressBarComponent, RuclibMeteredProgressBarModule };
230
- //# sourceMappingURL=ruc-lib-meteredProgressBar.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ruc-lib-meteredProgressBar.mjs","sources":["../../src/lib/enums/lable-position.enum.ts","../../src/lib/ruc-metered-progress-bar/ruc-metered-progress-bar.component.ts","../../src/lib/ruc-metered-progress-bar/ruc-metered-progress-bar.component.html","../../src/lib/ruclib-metered-progress-bar.module.ts","../../src/lib/model/metered-bar.config.ts","../../src/ruc-lib-meteredProgressBar.ts"],"sourcesContent":["export enum LablePositionEnums {\r\n left = \"left\",\r\n right = \"right\",\r\n same = \"same\",\r\n top = \"top\",\r\n bottom = 'bottom'\r\n}\r\n","import { Component, Input } from '@angular/core';\r\nimport { CategoryConfig, MeteredBarConfig } from '../model/metered-bar.config';\r\nimport { LablePositionEnums } from '../enums/lable-position.enum';\r\n\r\n\r\n@Component({\r\n selector: 'uxp-ruc-metered-progress-bar',\r\n templateUrl: './ruc-metered-progress-bar.component.html',\r\n styleUrls: ['./ruc-metered-progress-bar.component.scss'],\r\n})\r\n\r\n\r\nexport class RucMeteredProgressBarComponent {\r\n @Input() rucInputData!: MeteredBarConfig;\r\n @Input() customTheme!: string;\r\n hoveredCategoryDetail: { category: CategoryConfig, percentageText: string } | null = null;\r\n hoverLabelStyle: { left: string; top: string; display: string; transform: string; } = { left: '0px', top: '-28px', display: 'none', transform: 'translateX(-50%)' };\r\n progressPercentage = 0;\r\n /**\r\n * Calculates the total value of all categories.\r\n * @returns The sum of all category values.\r\n */\r\n get totalValue(): number {\r\n return this.rucInputData.categories.reduce((sum, category) => sum + category.value, 0);\r\n }\r\n\r\n /**\r\n * Calculates the overall progress percentage of the bar based on total value, min, and max.\r\n * @returns The progress as a percentage (0-100).\r\n */\r\n get progress(): number {\r\n return ((this.totalValue - this.rucInputData.min) / (this.rucInputData.max - this.rucInputData.min)) * 100;\r\n }\r\n\r\n /**\r\n * Determines if the progress bar is oriented vertically.\r\n * @returns True if the orientation is 'vertical', false otherwise.\r\n */\r\n get isVertical(): boolean {\r\n return this.rucInputData.orientation === 'vertical';\r\n }\r\n\r\n /**\r\n * Generates the CSS linear-gradient string for the progress bar.\r\n * The gradient is composed of segments based on category values and colors.\r\n * If no categories or total value is zero, it returns a transparent gradient.\r\n * @returns A CSS linear-gradient string.\r\n */\r\n get progressStyles(): { [key: string]: string } {\r\n const direction = this.isVertical ? 'to bottom' : 'to right';\r\n\r\n if (!this.rucInputData || !this.rucInputData.categories) {\r\n return { background: 'transparent' };\r\n }\r\n\r\n const total = this.totalValue;\r\n const colorStops: string[] = [];\r\n let cumulativePercentage = 0;\r\n\r\n if (total > 0) {\r\n this.rucInputData.categories.forEach(category => {\r\n if (category.value <= 0) return; // Skip categories with zero or negative contribution\r\n\r\n const segmentPercentage = (category.value / total) * 100;\r\n const color = category.color;\r\n\r\n // Add start of the segment using the previous cumulative percentage\r\n colorStops.push(`${color} ${cumulativePercentage}%`);\r\n\r\n // Update cumulative percentage for the end of this segment\r\n cumulativePercentage += segmentPercentage;\r\n\r\n // Add end of the segment\r\n // Use Math.min to cap at 100% in case of floating point overshoot on the last segment\r\n colorStops.push(`${color} ${Math.min(cumulativePercentage, 100)}%`);\r\n });\r\n }\r\n\r\n if (colorStops.length === 0) {\r\n return { background: 'transparent' };\r\n }\r\n\r\n const baseGradient = `linear-gradient(${direction}, ${colorStops.join(', ')})`;\r\n const styles: { [key: string]: string } = {};\r\n const barStyle = this.rucInputData?.barStyle;\r\n\r\n switch (barStyle) {\r\n case 'stripe':\r\n // This uses multiple backgrounds for an overlay effect, as requested.\r\n styles['background'] = `repeating-linear-gradient(-45deg, transparent, transparent 5px, rgba(0, 0, 0, 0.1) 5px, rgba(0, 0, 0, 0.1) 10px), ${baseGradient}`;\r\n break;\r\n case 'circle': {\r\n // This uses a mask. The background is the color, the mask cuts out the shape.\r\n styles['background'] = baseGradient;\r\n // A repeating pattern of circles. Each circle has a diameter of 8px, with a 4px gap.\r\n const circleMask = 'radial-gradient(circle, black 4px, transparent 4px) 0 0 / 12px 12px';\r\n styles['-webkit-mask'] = circleMask;\r\n styles['mask'] = circleMask;\r\n break;\r\n }\r\n case 'rectangle': {\r\n styles['background'] = baseGradient;\r\n // For vertical bar, create horizontal rectangles (0deg). For horizontal bar, create vertical rectangles (90deg).\r\n const rectDirection = this.isVertical ? '0deg' : '90deg';\r\n // A repeating pattern of bars. Each bar is 6px wide with a 6px gap.\r\n const rectangleMask = `repeating-linear-gradient(${rectDirection}, black, black 6px, transparent 6px, transparent 12px)`;\r\n styles['-webkit-mask'] = rectangleMask;\r\n styles['mask'] = rectangleMask;\r\n break;\r\n }\r\n default: // 'solid' or undefined\r\n styles['background'] = baseGradient;\r\n break;\r\n }\r\n return styles;\r\n }\r\n /**\r\n * Handles mouse movement over the progress bar to display category-specific hover details.\r\n * It calculates the hovered segment based on mouse position and updates the hover label.\r\n * @param event The MouseEvent object.\r\n */\r\n onProgressMouseMove(event: MouseEvent): void {\r\n const progressBarElement = event.target as HTMLElement;\r\n let currentCumulativeGradientPct = 0;\r\n let foundCategoryForHover: CategoryConfig | null = null;\r\n let hoverPercentage_onFilledBar = 0;\r\n let mousePositionWithinProgressDiv = 0;\r\n\r\n if (this.isVertical) {\r\n mousePositionWithinProgressDiv = event.offsetY; // Y position within the .progress div\r\n const filledHeightPx = progressBarElement.offsetHeight;\r\n if (filledHeightPx <= 0) { // Avoid division by zero if element has no height\r\n this.onProgressMouseLeave();\r\n return;\r\n }\r\n hoverPercentage_onFilledBar = (mousePositionWithinProgressDiv / filledHeightPx) * 100;\r\n } else { // Horizontal\r\n mousePositionWithinProgressDiv = event.offsetX; // X position within the .progress div\r\n const filledWidthPx = progressBarElement.offsetWidth;\r\n if (filledWidthPx <= 0) { // Avoid division by zero if element has no width\r\n this.onProgressMouseLeave();\r\n return;\r\n }\r\n hoverPercentage_onFilledBar = (mousePositionWithinProgressDiv / filledWidthPx) * 100;\r\n }\r\n\r\n if (this.totalValue > 0) {\r\n for (const category of this.rucInputData.categories) {\r\n if (category.value <= 0) continue; // Skip categories with zero or negative contribution\r\n\r\n const segmentGradientPct = (category.value / this.totalValue) * 100;\r\n const segmentStartGradientPct = currentCumulativeGradientPct;\r\n const segmentEndGradientPct = currentCumulativeGradientPct + segmentGradientPct;\r\n\r\n // Ensure hoverPercentage is within the segment, handling potential floating point inaccuracies for the last segment\r\n if (hoverPercentage_onFilledBar >= segmentStartGradientPct && // Check if mouse is within or at the start of the segment\r\n (hoverPercentage_onFilledBar < segmentEndGradientPct ||\r\n (segmentEndGradientPct >= 99.99 && hoverPercentage_onFilledBar <= 100.01))) { // Tolerate slight overshoot for last segment\r\n foundCategoryForHover = category;\r\n break;\r\n }\r\n currentCumulativeGradientPct = segmentEndGradientPct;\r\n }\r\n }\r\n\r\n if (foundCategoryForHover) {\r\n const percentageOfMax = (foundCategoryForHover.value / this.rucInputData.max) * 100; // Calculate percentage relative to max value\r\n this.hoveredCategoryDetail = { category: foundCategoryForHover, percentageText: percentageOfMax.toFixed(0) + '%' };\r\n if (this.isVertical) {\r\n this.hoverLabelStyle = {\r\n left: 'calc(100% + 5px)', // Position to the right of the vertical bar\r\n top: mousePositionWithinProgressDiv + 'px',\r\n display: 'block',\r\n transform: 'translateY(-50%)' // Vertically center label on mouse Y\r\n };\r\n } else {\r\n this.hoverLabelStyle = {\r\n left: mousePositionWithinProgressDiv + 'px',\r\n top: '-28px', // Position above horizontal bar\r\n display: 'block',\r\n transform: 'translateX(-50%)' // Horizontally center label on mouse X\r\n };\r\n }\r\n } else {\r\n this.hoveredCategoryDetail = null;\r\n this.hoverLabelStyle = { ...this.hoverLabelStyle, display: 'none' };\r\n }\r\n }\r\n\r\n /**\r\n * Hides the hover label when the mouse leaves the progress bar.\r\n */\r\n onProgressMouseLeave(): void {\r\n this.hoveredCategoryDetail = null;\r\n this.hoverLabelStyle = { ...this.hoverLabelStyle, display: 'none' };\r\n }\r\n /**\r\n * get the label position string value\r\n */\r\n public get LablePositionEnums(): typeof LablePositionEnums {\r\n return LablePositionEnums;\r\n }\r\n}\r\n","<div class=\"progress-container\" class={{customTheme}} [class.vertical]=\"isVertical\" [class.horizontal]=\"!isVertical\">\r\n <div class=\"progress-bar\">\r\n <!-- Removed (mouseenter) and (mouseleave) from progress-bar if only category hover is needed -->\r\n <div *ngIf=\"rucInputData.barLabels\" class=\"progress-label-container {{rucInputData.orientation}}\">\r\n <span class=\"progress-label\">{{progress | number:'1.0-0'}}% of {{rucInputData.max}} {{rucInputData.unitType}}\r\n Used</span>\r\n </div>\r\n <div class=\"progress\" [style.width]=\"isVertical ? '100%' : progress + '%'\"\r\n [style.height]=\"isVertical ? progress + '%' : '100%'\"\r\n [style.transition]=\"rucInputData.orientation === 'vertical' ? 'height 0.3s ease' : 'width 0.3s ease'\"\r\n [ngStyle]=\"progressStyles\">\r\n <!-- This div is now only for displaying the colored bar -->\r\n </div>\r\n <!-- The hover label is now a sibling to .progress, positioned absolutely within .progress-bar -->\r\n <div class=\"hover-label\" *ngIf=\"hoveredCategoryDetail\" [ngStyle]=\"hoverLabelStyle\">\r\n {{hoveredCategoryDetail.category.label}}: {{hoveredCategoryDetail.percentageText}}\r\n </div>\r\n <!-- This overlay is now a sibling to .progress, sized to match it, to reliably capture mouse events -->\r\n <div class=\"progress-event-overlay\" [style.width]=\"isVertical ? '100%' : progress + '%'\"\r\n [style.height]=\"isVertical ? progress + '%' : '100%'\" (mousemove)=\"onProgressMouseMove($event)\"\r\n (mouseleave)=\"onProgressMouseLeave()\"></div>\r\n </div>\r\n <div class=\"categories-container\" *ngIf=\"rucInputData.categories.length > 0\">\r\n <div *ngIf=\"rucInputData.showCategoryLabels && rucInputData.categoryLabelStyle === 'basic'\" [ngClass]=\"{\r\n 'categories-block-top': !isVertical && (rucInputData.categoryLabelsOrientation === 'top' || rucInputData.categoryLabelsOrientation === 'same'),\r\n 'categories-block-left': isVertical && (rucInputData.categoryLabelsOrientation === 'left' || rucInputData.categoryLabelsOrientation === 'same'),\r\n 'categories-block-right': isVertical && !(rucInputData.categoryLabelsOrientation === 'left' || rucInputData.categoryLabelsOrientation === 'same')\r\n }\" class=\"categories\">\r\n <div class=\"category\" *ngFor=\"let category of rucInputData.categories\" [style.color]=\"category.color\">\r\n <ng-container *ngIf=\"category.icon !== undefined\">\r\n <div *ngIf=\"category.icon; else colorDotBasic\" class=\"category-icon-wrapper\">\r\n <i class=\"material-icons\" [style.color]=\"category.color\">{{ category.icon }}</i>\r\n </div>\r\n <ng-template #colorDotBasic>\r\n <div class=\"category-color\">\r\n <div class=\"color-gradient\"\r\n [style.background]=\"category.color ? 'linear-gradient(to right, ' + category.color + ', ' + category.color + ')' : ''\">\r\n </div>\r\n </div>\r\n </ng-template>\r\n </ng-container>\r\n <span class=\"category-label\">{{category.label}}</span>\r\n <span class=\"category-value\">({{(category.value / rucInputData.max * 100) | number:'1.0-0' }}%)</span>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"rucInputData.showCategoryLabels && rucInputData.categoryLabelStyle === 'widget'\"\r\n class=\"categories widget-style\" [ngClass]=\"{\r\n 'categories-block-top': !isVertical && (rucInputData.categoryLabelsOrientation === LablePositionEnums.top || rucInputData.categoryLabelsOrientation === LablePositionEnums.same),\r\n 'categories-block-left': isVertical && (rucInputData.categoryLabelsOrientation === LablePositionEnums.left || rucInputData.categoryLabelsOrientation === LablePositionEnums.same),\r\n 'categories-block-right': isVertical && !(rucInputData.categoryLabelsOrientation === LablePositionEnums.left || rucInputData.categoryLabelsOrientation === LablePositionEnums.same)\r\n }\">\r\n <ng-container *ngFor=\"let category of rucInputData.categories\">\r\n <div class=\"widget-category\">\r\n <div class=\"widget-content\">\r\n <div class=\"widget-icon-box\">\r\n <ng-container *ngIf=\"category.icon !== undefined\">\r\n <div *ngIf=\"category.icon; else colorDotWidget\" class=\"widget-icon\">\r\n <i class=\"material-icons\" [style.color]=\"category.color\">{{ category.icon }}</i>\r\n </div>\r\n <ng-template #colorDotWidget>\r\n <div class=\"category-color\">\r\n <div class=\"color-gradient\"\r\n [style.background]=\"category.color ? 'linear-gradient(to right, ' + category.color + ', ' + category.color + ')' : ''\">\r\n </div>\r\n </div>\r\n </ng-template>\r\n </ng-container>\r\n <div class=\"widget-label\">{{category.label}}</div>\r\n </div>\r\n </div>\r\n <div class=\"widget-value\">\r\n <div>{{category.value}}</div>\r\n </div>\r\n </div>\r\n\r\n\r\n </ng-container>\r\n </div>\r\n\r\n </div>\r\n</div>","import { NgModule } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { MatIconModule } from '@angular/material/icon';\r\nimport { RucMeteredProgressBarComponent } from './ruc-metered-progress-bar/ruc-metered-progress-bar.component';\r\n// import { RucMeteredProgressBarComponent } from './ruc-metered-progress-bar/ruc-metered-progress-bar/ruc-metered-progress-bar.component';\r\n\r\n@NgModule({\r\n imports: [CommonModule,MatIconModule],\r\n declarations: [RucMeteredProgressBarComponent],\r\n exports: [RucMeteredProgressBarComponent],\r\n})\r\nexport class RuclibMeteredProgressBarModule {}\r\n","export class MeteredBarConfig {\r\n min!: number;\r\n max!: number;\r\n orientation!: string;\r\n barLabels!: boolean;\r\n barStyle?: 'solid' | 'stripe' | 'circle' | 'rectangle';\r\n categoryLabelsOrientation!: string;\r\n categoryLabelStyle?: string;\r\n showCategoryLabels?: boolean;\r\n categories!: CategoryConfig[];\r\n unitType?: string\r\n}\r\n\r\nexport class CategoryConfig {\r\n label!: string;\r\n color!: string;\r\n value!: number;\r\n icon?: string;\r\n handler?: (event?: any) => void;\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -1,229 +0,0 @@
1
- import * as i0 from '@angular/core';
2
- import { Component, Input, NgModule } from '@angular/core';
3
- import * as i1 from '@angular/common';
4
- import { CommonModule } from '@angular/common';
5
- import { MatIconModule } from '@angular/material/icon';
6
-
7
- class MeteredBarConfig {
8
- }
9
- class CategoryConfig {
10
- }
11
-
12
- var LablePositionEnums;
13
- (function (LablePositionEnums) {
14
- LablePositionEnums["left"] = "left";
15
- LablePositionEnums["right"] = "right";
16
- LablePositionEnums["same"] = "same";
17
- LablePositionEnums["top"] = "top";
18
- LablePositionEnums["bottom"] = "bottom";
19
- })(LablePositionEnums || (LablePositionEnums = {}));
20
-
21
- class RucMeteredProgressBarComponent {
22
- constructor() {
23
- this.hoveredCategoryDetail = null;
24
- this.hoverLabelStyle = { left: '0px', top: '-28px', display: 'none', transform: 'translateX(-50%)' };
25
- this.progressPercentage = 0;
26
- }
27
- /**
28
- * Calculates the total value of all categories.
29
- * @returns The sum of all category values.
30
- */
31
- get totalValue() {
32
- return this.rucInputData.categories.reduce((sum, category) => sum + category.value, 0);
33
- }
34
- /**
35
- * Calculates the overall progress percentage of the bar based on total value, min, and max.
36
- * @returns The progress as a percentage (0-100).
37
- */
38
- get progress() {
39
- return ((this.totalValue - this.rucInputData.min) / (this.rucInputData.max - this.rucInputData.min)) * 100;
40
- }
41
- /**
42
- * Determines if the progress bar is oriented vertically.
43
- * @returns True if the orientation is 'vertical', false otherwise.
44
- */
45
- get isVertical() {
46
- return this.rucInputData.orientation === 'vertical';
47
- }
48
- /**
49
- * Generates the CSS linear-gradient string for the progress bar.
50
- * The gradient is composed of segments based on category values and colors.
51
- * If no categories or total value is zero, it returns a transparent gradient.
52
- * @returns A CSS linear-gradient string.
53
- */
54
- get progressStyles() {
55
- const direction = this.isVertical ? 'to bottom' : 'to right';
56
- if (!this.rucInputData || !this.rucInputData.categories) {
57
- return { background: 'transparent' };
58
- }
59
- const total = this.totalValue;
60
- const colorStops = [];
61
- let cumulativePercentage = 0;
62
- if (total > 0) {
63
- this.rucInputData.categories.forEach(category => {
64
- if (category.value <= 0)
65
- return; // Skip categories with zero or negative contribution
66
- const segmentPercentage = (category.value / total) * 100;
67
- const color = category.color;
68
- // Add start of the segment using the previous cumulative percentage
69
- colorStops.push(`${color} ${cumulativePercentage}%`);
70
- // Update cumulative percentage for the end of this segment
71
- cumulativePercentage += segmentPercentage;
72
- // Add end of the segment
73
- // Use Math.min to cap at 100% in case of floating point overshoot on the last segment
74
- colorStops.push(`${color} ${Math.min(cumulativePercentage, 100)}%`);
75
- });
76
- }
77
- if (colorStops.length === 0) {
78
- return { background: 'transparent' };
79
- }
80
- const baseGradient = `linear-gradient(${direction}, ${colorStops.join(', ')})`;
81
- const styles = {};
82
- const barStyle = this.rucInputData?.barStyle;
83
- switch (barStyle) {
84
- case 'stripe':
85
- // This uses multiple backgrounds for an overlay effect, as requested.
86
- styles['background'] = `repeating-linear-gradient(-45deg, transparent, transparent 5px, rgba(0, 0, 0, 0.1) 5px, rgba(0, 0, 0, 0.1) 10px), ${baseGradient}`;
87
- break;
88
- case 'circle': {
89
- // This uses a mask. The background is the color, the mask cuts out the shape.
90
- styles['background'] = baseGradient;
91
- // A repeating pattern of circles. Each circle has a diameter of 8px, with a 4px gap.
92
- const circleMask = 'radial-gradient(circle, black 4px, transparent 4px) 0 0 / 12px 12px';
93
- styles['-webkit-mask'] = circleMask;
94
- styles['mask'] = circleMask;
95
- break;
96
- }
97
- case 'rectangle': {
98
- styles['background'] = baseGradient;
99
- // For vertical bar, create horizontal rectangles (0deg). For horizontal bar, create vertical rectangles (90deg).
100
- const rectDirection = this.isVertical ? '0deg' : '90deg';
101
- // A repeating pattern of bars. Each bar is 6px wide with a 6px gap.
102
- const rectangleMask = `repeating-linear-gradient(${rectDirection}, black, black 6px, transparent 6px, transparent 12px)`;
103
- styles['-webkit-mask'] = rectangleMask;
104
- styles['mask'] = rectangleMask;
105
- break;
106
- }
107
- default: // 'solid' or undefined
108
- styles['background'] = baseGradient;
109
- break;
110
- }
111
- return styles;
112
- }
113
- /**
114
- * Handles mouse movement over the progress bar to display category-specific hover details.
115
- * It calculates the hovered segment based on mouse position and updates the hover label.
116
- * @param event The MouseEvent object.
117
- */
118
- onProgressMouseMove(event) {
119
- const progressBarElement = event.target;
120
- let currentCumulativeGradientPct = 0;
121
- let foundCategoryForHover = null;
122
- let hoverPercentage_onFilledBar = 0;
123
- let mousePositionWithinProgressDiv = 0;
124
- if (this.isVertical) {
125
- mousePositionWithinProgressDiv = event.offsetY; // Y position within the .progress div
126
- const filledHeightPx = progressBarElement.offsetHeight;
127
- if (filledHeightPx <= 0) { // Avoid division by zero if element has no height
128
- this.onProgressMouseLeave();
129
- return;
130
- }
131
- hoverPercentage_onFilledBar = (mousePositionWithinProgressDiv / filledHeightPx) * 100;
132
- }
133
- else { // Horizontal
134
- mousePositionWithinProgressDiv = event.offsetX; // X position within the .progress div
135
- const filledWidthPx = progressBarElement.offsetWidth;
136
- if (filledWidthPx <= 0) { // Avoid division by zero if element has no width
137
- this.onProgressMouseLeave();
138
- return;
139
- }
140
- hoverPercentage_onFilledBar = (mousePositionWithinProgressDiv / filledWidthPx) * 100;
141
- }
142
- if (this.totalValue > 0) {
143
- for (const category of this.rucInputData.categories) {
144
- if (category.value <= 0)
145
- continue; // Skip categories with zero or negative contribution
146
- const segmentGradientPct = (category.value / this.totalValue) * 100;
147
- const segmentStartGradientPct = currentCumulativeGradientPct;
148
- const segmentEndGradientPct = currentCumulativeGradientPct + segmentGradientPct;
149
- // Ensure hoverPercentage is within the segment, handling potential floating point inaccuracies for the last segment
150
- if (hoverPercentage_onFilledBar >= segmentStartGradientPct && // Check if mouse is within or at the start of the segment
151
- (hoverPercentage_onFilledBar < segmentEndGradientPct ||
152
- (segmentEndGradientPct >= 99.99 && hoverPercentage_onFilledBar <= 100.01))) { // Tolerate slight overshoot for last segment
153
- foundCategoryForHover = category;
154
- break;
155
- }
156
- currentCumulativeGradientPct = segmentEndGradientPct;
157
- }
158
- }
159
- if (foundCategoryForHover) {
160
- const percentageOfMax = (foundCategoryForHover.value / this.rucInputData.max) * 100; // Calculate percentage relative to max value
161
- this.hoveredCategoryDetail = { category: foundCategoryForHover, percentageText: percentageOfMax.toFixed(0) + '%' };
162
- if (this.isVertical) {
163
- this.hoverLabelStyle = {
164
- left: 'calc(100% + 5px)',
165
- top: mousePositionWithinProgressDiv + 'px',
166
- display: 'block',
167
- transform: 'translateY(-50%)' // Vertically center label on mouse Y
168
- };
169
- }
170
- else {
171
- this.hoverLabelStyle = {
172
- left: mousePositionWithinProgressDiv + 'px',
173
- top: '-28px',
174
- display: 'block',
175
- transform: 'translateX(-50%)' // Horizontally center label on mouse X
176
- };
177
- }
178
- }
179
- else {
180
- this.hoveredCategoryDetail = null;
181
- this.hoverLabelStyle = { ...this.hoverLabelStyle, display: 'none' };
182
- }
183
- }
184
- /**
185
- * Hides the hover label when the mouse leaves the progress bar.
186
- */
187
- onProgressMouseLeave() {
188
- this.hoveredCategoryDetail = null;
189
- this.hoverLabelStyle = { ...this.hoverLabelStyle, display: 'none' };
190
- }
191
- /**
192
- * get the label position string value
193
- */
194
- get LablePositionEnums() {
195
- return LablePositionEnums;
196
- }
197
- }
198
- RucMeteredProgressBarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RucMeteredProgressBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
199
- RucMeteredProgressBarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: RucMeteredProgressBarComponent, selector: "uxp-ruc-metered-progress-bar", inputs: { rucInputData: "rucInputData", customTheme: "customTheme" }, ngImport: i0, template: "<div class=\"progress-container\" class={{customTheme}} [class.vertical]=\"isVertical\" [class.horizontal]=\"!isVertical\">\r\n <div class=\"progress-bar\">\r\n <!-- Removed (mouseenter) and (mouseleave) from progress-bar if only category hover is needed -->\r\n <div *ngIf=\"rucInputData.barLabels\" class=\"progress-label-container {{rucInputData.orientation}}\">\r\n <span class=\"progress-label\">{{progress | number:'1.0-0'}}% of {{rucInputData.max}} {{rucInputData.unitType}}\r\n Used</span>\r\n </div>\r\n <div class=\"progress\" [style.width]=\"isVertical ? '100%' : progress + '%'\"\r\n [style.height]=\"isVertical ? progress + '%' : '100%'\"\r\n [style.transition]=\"rucInputData.orientation === 'vertical' ? 'height 0.3s ease' : 'width 0.3s ease'\"\r\n [ngStyle]=\"progressStyles\">\r\n <!-- This div is now only for displaying the colored bar -->\r\n </div>\r\n <!-- The hover label is now a sibling to .progress, positioned absolutely within .progress-bar -->\r\n <div class=\"hover-label\" *ngIf=\"hoveredCategoryDetail\" [ngStyle]=\"hoverLabelStyle\">\r\n {{hoveredCategoryDetail.category.label}}: {{hoveredCategoryDetail.percentageText}}\r\n </div>\r\n <!-- This overlay is now a sibling to .progress, sized to match it, to reliably capture mouse events -->\r\n <div class=\"progress-event-overlay\" [style.width]=\"isVertical ? '100%' : progress + '%'\"\r\n [style.height]=\"isVertical ? progress + '%' : '100%'\" (mousemove)=\"onProgressMouseMove($event)\"\r\n (mouseleave)=\"onProgressMouseLeave()\"></div>\r\n </div>\r\n <div class=\"categories-container\" *ngIf=\"rucInputData.categories.length > 0\">\r\n <div *ngIf=\"rucInputData.showCategoryLabels && rucInputData.categoryLabelStyle === 'basic'\" [ngClass]=\"{\r\n 'categories-block-top': !isVertical && (rucInputData.categoryLabelsOrientation === 'top' || rucInputData.categoryLabelsOrientation === 'same'),\r\n 'categories-block-left': isVertical && (rucInputData.categoryLabelsOrientation === 'left' || rucInputData.categoryLabelsOrientation === 'same'),\r\n 'categories-block-right': isVertical && !(rucInputData.categoryLabelsOrientation === 'left' || rucInputData.categoryLabelsOrientation === 'same')\r\n }\" class=\"categories\">\r\n <div class=\"category\" *ngFor=\"let category of rucInputData.categories\" [style.color]=\"category.color\">\r\n <ng-container *ngIf=\"category.icon !== undefined\">\r\n <div *ngIf=\"category.icon; else colorDotBasic\" class=\"category-icon-wrapper\">\r\n <i class=\"material-icons\" [style.color]=\"category.color\">{{ category.icon }}</i>\r\n </div>\r\n <ng-template #colorDotBasic>\r\n <div class=\"category-color\">\r\n <div class=\"color-gradient\"\r\n [style.background]=\"category.color ? 'linear-gradient(to right, ' + category.color + ', ' + category.color + ')' : ''\">\r\n </div>\r\n </div>\r\n </ng-template>\r\n </ng-container>\r\n <span class=\"category-label\">{{category.label}}</span>\r\n <span class=\"category-value\">({{(category.value / rucInputData.max * 100) | number:'1.0-0' }}%)</span>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"rucInputData.showCategoryLabels && rucInputData.categoryLabelStyle === 'widget'\"\r\n class=\"categories widget-style\" [ngClass]=\"{\r\n 'categories-block-top': !isVertical && (rucInputData.categoryLabelsOrientation === LablePositionEnums.top || rucInputData.categoryLabelsOrientation === LablePositionEnums.same),\r\n 'categories-block-left': isVertical && (rucInputData.categoryLabelsOrientation === LablePositionEnums.left || rucInputData.categoryLabelsOrientation === LablePositionEnums.same),\r\n 'categories-block-right': isVertical && !(rucInputData.categoryLabelsOrientation === LablePositionEnums.left || rucInputData.categoryLabelsOrientation === LablePositionEnums.same)\r\n }\">\r\n <ng-container *ngFor=\"let category of rucInputData.categories\">\r\n <div class=\"widget-category\">\r\n <div class=\"widget-content\">\r\n <div class=\"widget-icon-box\">\r\n <ng-container *ngIf=\"category.icon !== undefined\">\r\n <div *ngIf=\"category.icon; else colorDotWidget\" class=\"widget-icon\">\r\n <i class=\"material-icons\" [style.color]=\"category.color\">{{ category.icon }}</i>\r\n </div>\r\n <ng-template #colorDotWidget>\r\n <div class=\"category-color\">\r\n <div class=\"color-gradient\"\r\n [style.background]=\"category.color ? 'linear-gradient(to right, ' + category.color + ', ' + category.color + ')' : ''\">\r\n </div>\r\n </div>\r\n </ng-template>\r\n </ng-container>\r\n <div class=\"widget-label\">{{category.label}}</div>\r\n </div>\r\n </div>\r\n <div class=\"widget-value\">\r\n <div>{{category.value}}</div>\r\n </div>\r\n </div>\r\n\r\n\r\n </ng-container>\r\n </div>\r\n\r\n </div>\r\n</div>", styles: [".progress-container{position:relative;margin:20px 0}.progress-container.horizontal{width:100%;height:35px}.progress-container.horizontal .progress-bar{width:100%;height:42%}.progress-container.vertical{width:60px;height:320px;margin:0 auto}.progress-container.vertical .progress-bar{width:24%;height:100%}.progress-label-container{position:absolute;z-index:2;width:100%;height:100%;pointer-events:none;display:flex}.progress-label-container.horizontal{justify-content:right;align-items:flex-end;bottom:15px}.progress-label-container.vertical{justify-content:flex-start;align-items:flex-end;left:35px}.progress-label{padding:2px 5px;font-size:12px;color:#333;white-space:nowrap}.progress-label-container.horizontal .progress-label{margin-top:5px;margin-right:5px}.progress-label-container.vertical .progress-label{transform:rotate(-90deg);transform-origin:bottom left;margin-right:5px}.progress-bar{position:relative;background:white;border:1px solid #e0e0e0;border-radius:4px}.progress-bar .hover-label{position:absolute;top:-28px;left:50%;transform:translate(-50%);background-color:#000c;color:#fff;padding:4px 8px;border-radius:4px;font-size:.8em;z-index:5;white-space:nowrap;pointer-events:none}.progress-event-overlay{position:absolute;top:0;left:0;z-index:4}.progress{position:relative;background:#2196F3;transition:width .3s ease,height .3s ease}.progress-bar.horizontal .progress{width:100%;height:100%}.progress-bar.vertical .progress{width:100%;height:0}.icons-container{position:absolute;display:flex;justify-content:space-between;width:100%;height:100%;align-items:center}.icons-container i{position:absolute;font-size:1.2em;color:#fff}.start-icon{left:0}.end-icon{right:0}.above-threshold{color:gold}.categories-container{width:100%;box-sizing:border-box}.categories{display:flex;flex-direction:row;flex-wrap:wrap;gap:1px}.categories-block-top,.categories-block-bottom,.categories-block-left,.categories-block-right{position:absolute;z-index:1}.categories-block-top{bottom:100%;left:0;padding-bottom:8px}.categories-block-bottom{top:100%;left:0;padding-top:10px}.categories-block-left{right:100%;top:0;padding-right:8px;width:200px}.categories-block-left .categories{flex-direction:inherit;align-items:flex-start;gap:0px}.categories-block-right{left:100%;top:0;padding-left:8px;width:200px}.categories-block-right .categories{flex-direction:inherit;align-items:flex-start;gap:0px}.category{display:flex;align-items:center;gap:6px;padding:8px;border-radius:4px}.category-label{font-weight:500}.category-value{color:#666;font-size:.9em}.category-color{width:10px;height:10px;border-radius:50%;overflow:hidden;flex-shrink:0}.category-icon-wrapper{display:flex;align-items:center;justify-content:center;width:100%;height:100%}.color-gradient{width:100%;height:100%}.categories.widget-style{display:flex;flex-wrap:wrap;gap:10px;justify-content:flex-start;align-items:flex-start;margin:10px 0}.categories.widget-style .widget-category{width:calc(25% - 7.5px);min-width:159px;box-sizing:border-box;flex-shrink:0;flex-grow:0}@media (max-width: 1200px){.categories.widget-style .widget-category{width:calc(33.33% - 6.66px)}}@media (max-width: 768px){.categories.widget-style .widget-category{width:calc(50% - 5px)}}@media (max-width: 480px){.categories.widget-style .widget-category{width:100%}}.categories-block-left,.categories-block-right{flex-direction:inherit;align-items:flex-start;gap:10px}.categories-block-left .widget-category,.categories-block-right .widget-category{width:100%;max-width:none}.widget-category{background-color:#fff;border:1px solid #e0e0e0;border-radius:8px;padding:10px 15px;box-shadow:0 2px 4px #0000001a}.widget-content{display:flex;width:100%;align-items:center;margin:0}.widget-icon{border:1px solid #ddd;border-radius:10px;width:35px;height:35px;line-height:45px;text-align:center;background-color:#fdfdfd}.widget-content .category-color{margin-right:35px}.widget-icon,.widget-color{margin-right:8px;flex-shrink:0}.widget-color{width:24px;height:24px;border-radius:50%}.widget-label{flex-grow:1;text-align:left;display:block}.widget-value{font-weight:700;flex-shrink:0;margin-left:45px;text-align:left;margin-top:5px}.widget-icon-box{display:flex;align-items:center}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: i1.DecimalPipe, name: "number" }] });
200
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RucMeteredProgressBarComponent, decorators: [{
201
- type: Component,
202
- args: [{ selector: 'uxp-ruc-metered-progress-bar', template: "<div class=\"progress-container\" class={{customTheme}} [class.vertical]=\"isVertical\" [class.horizontal]=\"!isVertical\">\r\n <div class=\"progress-bar\">\r\n <!-- Removed (mouseenter) and (mouseleave) from progress-bar if only category hover is needed -->\r\n <div *ngIf=\"rucInputData.barLabels\" class=\"progress-label-container {{rucInputData.orientation}}\">\r\n <span class=\"progress-label\">{{progress | number:'1.0-0'}}% of {{rucInputData.max}} {{rucInputData.unitType}}\r\n Used</span>\r\n </div>\r\n <div class=\"progress\" [style.width]=\"isVertical ? '100%' : progress + '%'\"\r\n [style.height]=\"isVertical ? progress + '%' : '100%'\"\r\n [style.transition]=\"rucInputData.orientation === 'vertical' ? 'height 0.3s ease' : 'width 0.3s ease'\"\r\n [ngStyle]=\"progressStyles\">\r\n <!-- This div is now only for displaying the colored bar -->\r\n </div>\r\n <!-- The hover label is now a sibling to .progress, positioned absolutely within .progress-bar -->\r\n <div class=\"hover-label\" *ngIf=\"hoveredCategoryDetail\" [ngStyle]=\"hoverLabelStyle\">\r\n {{hoveredCategoryDetail.category.label}}: {{hoveredCategoryDetail.percentageText}}\r\n </div>\r\n <!-- This overlay is now a sibling to .progress, sized to match it, to reliably capture mouse events -->\r\n <div class=\"progress-event-overlay\" [style.width]=\"isVertical ? '100%' : progress + '%'\"\r\n [style.height]=\"isVertical ? progress + '%' : '100%'\" (mousemove)=\"onProgressMouseMove($event)\"\r\n (mouseleave)=\"onProgressMouseLeave()\"></div>\r\n </div>\r\n <div class=\"categories-container\" *ngIf=\"rucInputData.categories.length > 0\">\r\n <div *ngIf=\"rucInputData.showCategoryLabels && rucInputData.categoryLabelStyle === 'basic'\" [ngClass]=\"{\r\n 'categories-block-top': !isVertical && (rucInputData.categoryLabelsOrientation === 'top' || rucInputData.categoryLabelsOrientation === 'same'),\r\n 'categories-block-left': isVertical && (rucInputData.categoryLabelsOrientation === 'left' || rucInputData.categoryLabelsOrientation === 'same'),\r\n 'categories-block-right': isVertical && !(rucInputData.categoryLabelsOrientation === 'left' || rucInputData.categoryLabelsOrientation === 'same')\r\n }\" class=\"categories\">\r\n <div class=\"category\" *ngFor=\"let category of rucInputData.categories\" [style.color]=\"category.color\">\r\n <ng-container *ngIf=\"category.icon !== undefined\">\r\n <div *ngIf=\"category.icon; else colorDotBasic\" class=\"category-icon-wrapper\">\r\n <i class=\"material-icons\" [style.color]=\"category.color\">{{ category.icon }}</i>\r\n </div>\r\n <ng-template #colorDotBasic>\r\n <div class=\"category-color\">\r\n <div class=\"color-gradient\"\r\n [style.background]=\"category.color ? 'linear-gradient(to right, ' + category.color + ', ' + category.color + ')' : ''\">\r\n </div>\r\n </div>\r\n </ng-template>\r\n </ng-container>\r\n <span class=\"category-label\">{{category.label}}</span>\r\n <span class=\"category-value\">({{(category.value / rucInputData.max * 100) | number:'1.0-0' }}%)</span>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"rucInputData.showCategoryLabels && rucInputData.categoryLabelStyle === 'widget'\"\r\n class=\"categories widget-style\" [ngClass]=\"{\r\n 'categories-block-top': !isVertical && (rucInputData.categoryLabelsOrientation === LablePositionEnums.top || rucInputData.categoryLabelsOrientation === LablePositionEnums.same),\r\n 'categories-block-left': isVertical && (rucInputData.categoryLabelsOrientation === LablePositionEnums.left || rucInputData.categoryLabelsOrientation === LablePositionEnums.same),\r\n 'categories-block-right': isVertical && !(rucInputData.categoryLabelsOrientation === LablePositionEnums.left || rucInputData.categoryLabelsOrientation === LablePositionEnums.same)\r\n }\">\r\n <ng-container *ngFor=\"let category of rucInputData.categories\">\r\n <div class=\"widget-category\">\r\n <div class=\"widget-content\">\r\n <div class=\"widget-icon-box\">\r\n <ng-container *ngIf=\"category.icon !== undefined\">\r\n <div *ngIf=\"category.icon; else colorDotWidget\" class=\"widget-icon\">\r\n <i class=\"material-icons\" [style.color]=\"category.color\">{{ category.icon }}</i>\r\n </div>\r\n <ng-template #colorDotWidget>\r\n <div class=\"category-color\">\r\n <div class=\"color-gradient\"\r\n [style.background]=\"category.color ? 'linear-gradient(to right, ' + category.color + ', ' + category.color + ')' : ''\">\r\n </div>\r\n </div>\r\n </ng-template>\r\n </ng-container>\r\n <div class=\"widget-label\">{{category.label}}</div>\r\n </div>\r\n </div>\r\n <div class=\"widget-value\">\r\n <div>{{category.value}}</div>\r\n </div>\r\n </div>\r\n\r\n\r\n </ng-container>\r\n </div>\r\n\r\n </div>\r\n</div>", styles: [".progress-container{position:relative;margin:20px 0}.progress-container.horizontal{width:100%;height:35px}.progress-container.horizontal .progress-bar{width:100%;height:42%}.progress-container.vertical{width:60px;height:320px;margin:0 auto}.progress-container.vertical .progress-bar{width:24%;height:100%}.progress-label-container{position:absolute;z-index:2;width:100%;height:100%;pointer-events:none;display:flex}.progress-label-container.horizontal{justify-content:right;align-items:flex-end;bottom:15px}.progress-label-container.vertical{justify-content:flex-start;align-items:flex-end;left:35px}.progress-label{padding:2px 5px;font-size:12px;color:#333;white-space:nowrap}.progress-label-container.horizontal .progress-label{margin-top:5px;margin-right:5px}.progress-label-container.vertical .progress-label{transform:rotate(-90deg);transform-origin:bottom left;margin-right:5px}.progress-bar{position:relative;background:white;border:1px solid #e0e0e0;border-radius:4px}.progress-bar .hover-label{position:absolute;top:-28px;left:50%;transform:translate(-50%);background-color:#000c;color:#fff;padding:4px 8px;border-radius:4px;font-size:.8em;z-index:5;white-space:nowrap;pointer-events:none}.progress-event-overlay{position:absolute;top:0;left:0;z-index:4}.progress{position:relative;background:#2196F3;transition:width .3s ease,height .3s ease}.progress-bar.horizontal .progress{width:100%;height:100%}.progress-bar.vertical .progress{width:100%;height:0}.icons-container{position:absolute;display:flex;justify-content:space-between;width:100%;height:100%;align-items:center}.icons-container i{position:absolute;font-size:1.2em;color:#fff}.start-icon{left:0}.end-icon{right:0}.above-threshold{color:gold}.categories-container{width:100%;box-sizing:border-box}.categories{display:flex;flex-direction:row;flex-wrap:wrap;gap:1px}.categories-block-top,.categories-block-bottom,.categories-block-left,.categories-block-right{position:absolute;z-index:1}.categories-block-top{bottom:100%;left:0;padding-bottom:8px}.categories-block-bottom{top:100%;left:0;padding-top:10px}.categories-block-left{right:100%;top:0;padding-right:8px;width:200px}.categories-block-left .categories{flex-direction:inherit;align-items:flex-start;gap:0px}.categories-block-right{left:100%;top:0;padding-left:8px;width:200px}.categories-block-right .categories{flex-direction:inherit;align-items:flex-start;gap:0px}.category{display:flex;align-items:center;gap:6px;padding:8px;border-radius:4px}.category-label{font-weight:500}.category-value{color:#666;font-size:.9em}.category-color{width:10px;height:10px;border-radius:50%;overflow:hidden;flex-shrink:0}.category-icon-wrapper{display:flex;align-items:center;justify-content:center;width:100%;height:100%}.color-gradient{width:100%;height:100%}.categories.widget-style{display:flex;flex-wrap:wrap;gap:10px;justify-content:flex-start;align-items:flex-start;margin:10px 0}.categories.widget-style .widget-category{width:calc(25% - 7.5px);min-width:159px;box-sizing:border-box;flex-shrink:0;flex-grow:0}@media (max-width: 1200px){.categories.widget-style .widget-category{width:calc(33.33% - 6.66px)}}@media (max-width: 768px){.categories.widget-style .widget-category{width:calc(50% - 5px)}}@media (max-width: 480px){.categories.widget-style .widget-category{width:100%}}.categories-block-left,.categories-block-right{flex-direction:inherit;align-items:flex-start;gap:10px}.categories-block-left .widget-category,.categories-block-right .widget-category{width:100%;max-width:none}.widget-category{background-color:#fff;border:1px solid #e0e0e0;border-radius:8px;padding:10px 15px;box-shadow:0 2px 4px #0000001a}.widget-content{display:flex;width:100%;align-items:center;margin:0}.widget-icon{border:1px solid #ddd;border-radius:10px;width:35px;height:35px;line-height:45px;text-align:center;background-color:#fdfdfd}.widget-content .category-color{margin-right:35px}.widget-icon,.widget-color{margin-right:8px;flex-shrink:0}.widget-color{width:24px;height:24px;border-radius:50%}.widget-label{flex-grow:1;text-align:left;display:block}.widget-value{font-weight:700;flex-shrink:0;margin-left:45px;text-align:left;margin-top:5px}.widget-icon-box{display:flex;align-items:center}\n"] }]
203
- }], propDecorators: { rucInputData: [{
204
- type: Input
205
- }], customTheme: [{
206
- type: Input
207
- }] } });
208
-
209
- // import { RucMeteredProgressBarComponent } from './ruc-metered-progress-bar/ruc-metered-progress-bar/ruc-metered-progress-bar.component';
210
- class RuclibMeteredProgressBarModule {
211
- }
212
- RuclibMeteredProgressBarModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RuclibMeteredProgressBarModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
213
- RuclibMeteredProgressBarModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: RuclibMeteredProgressBarModule, declarations: [RucMeteredProgressBarComponent], imports: [CommonModule, MatIconModule], exports: [RucMeteredProgressBarComponent] });
214
- RuclibMeteredProgressBarModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RuclibMeteredProgressBarModule, imports: [CommonModule, MatIconModule] });
215
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RuclibMeteredProgressBarModule, decorators: [{
216
- type: NgModule,
217
- args: [{
218
- imports: [CommonModule, MatIconModule],
219
- declarations: [RucMeteredProgressBarComponent],
220
- exports: [RucMeteredProgressBarComponent],
221
- }]
222
- }] });
223
-
224
- /**
225
- * Generated bundle index. Do not edit.
226
- */
227
-
228
- export { CategoryConfig, MeteredBarConfig, RucMeteredProgressBarComponent, RuclibMeteredProgressBarModule };
229
- //# sourceMappingURL=ruc-lib-meteredProgressBar.mjs.map