@ruc-lib/metered-progress-bar 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +126 -0
- package/esm2020/index.mjs +4 -0
- package/esm2020/lib/enums/lable-position.enum.mjs +9 -0
- package/esm2020/lib/model/metered-bar.config.mjs +5 -0
- package/esm2020/lib/ruc-metered-progress-bar/ruc-metered-progress-bar.component.mjs +193 -0
- package/esm2020/lib/ruclib-metered-progress-bar.module.mjs +20 -0
- package/esm2020/ruc-lib-meteredProgressBar.mjs +5 -0
- package/fesm2015/ruc-lib-meteredProgressBar.mjs +230 -0
- package/fesm2015/ruc-lib-meteredProgressBar.mjs.map +1 -0
- package/fesm2020/ruc-lib-meteredProgressBar.mjs +229 -0
- package/fesm2020/ruc-lib-meteredProgressBar.mjs.map +1 -0
- package/index.d.ts +3 -0
- package/lib/enums/lable-position.enum.d.ts +7 -0
- package/lib/model/metered-bar.config.d.ts +19 -0
- package/lib/ruc-metered-progress-bar/ruc-metered-progress-bar.component.d.ts +58 -0
- package/lib/ruclib-metered-progress-bar.module.d.ts +9 -0
- package/package.json +36 -0
package/README.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Metered Progress Bar
|
|
2
|
+
|
|
3
|
+
A customizable Angular progress bar component that displays progress with various styling options and categories. It supports different visual styles like solid, stripes, circles, and rectangles, and can be oriented horizontally or vertically.
|
|
4
|
+
|
|
5
|
+
## Installation Guide
|
|
6
|
+
|
|
7
|
+
To use the Metered Progress Bar component, you can install the entire RUC library or just this specific component.
|
|
8
|
+
|
|
9
|
+
### Install the Entire Library
|
|
10
|
+
```bash
|
|
11
|
+
npm install @uxpractice/ruc-lib
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### Install Individual Component
|
|
15
|
+
If you only need the Metered Progress Bar component:
|
|
16
|
+
```bash
|
|
17
|
+
npm install @uxpractice/metered-progress-bar
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
### 1. Import the Module
|
|
23
|
+
In your Angular module file (e.g., `app.module.ts`), import the `RucMeteredProgressBarModule`:
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { RucMeteredProgressBarModule } from '@uxpractice/metered-progress-bar';
|
|
27
|
+
import { AppComponent } from './app.component';
|
|
28
|
+
import { NgModule } from '@angular/core';
|
|
29
|
+
import { BrowserModule } from '@angular/platform-browser';
|
|
30
|
+
|
|
31
|
+
@NgModule({
|
|
32
|
+
declarations: [AppComponent],
|
|
33
|
+
imports: [
|
|
34
|
+
BrowserModule,
|
|
35
|
+
RucMeteredProgressBarModule
|
|
36
|
+
],
|
|
37
|
+
providers: [],
|
|
38
|
+
bootstrap: [AppComponent]
|
|
39
|
+
})
|
|
40
|
+
export class AppModule {}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 2. Use the Component
|
|
44
|
+
In your component's template, use the `<uxp-ruc-metered-progress-bar>` selector and pass the configuration object to the `rucInputData` input.
|
|
45
|
+
|
|
46
|
+
```html
|
|
47
|
+
<uxp-ruc-metered-progress-bar [rucInputData]="meteredBarConfig"></uxp-ruc-metered-progress-bar>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## API Reference
|
|
51
|
+
|
|
52
|
+
### Component Inputs
|
|
53
|
+
|
|
54
|
+
| Input | Type | Description |
|
|
55
|
+
|----------------|--------------------|----------------------------------------------|
|
|
56
|
+
| `rucInputData` | `MeteredBarConfig` | The main configuration object for the component. |
|
|
57
|
+
| `customTheme` | `string` | An optional CSS class for custom theming. |
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
### `MeteredBarConfig`
|
|
61
|
+
This is the main configuration object for the progress bar.
|
|
62
|
+
|
|
63
|
+
| Property | Type | Description |
|
|
64
|
+
|-----------------------------|--------------------------------------------------|---------------------------------------------------------------------------------------------------------|
|
|
65
|
+
| `min` | `number` | The minimum value of the progress bar (e.g., 0). |
|
|
66
|
+
| `max` | `number` | The maximum value of the progress bar (e.g., 100). |
|
|
67
|
+
| `orientation` | `'horizontal' \| 'vertical'` | The orientation of the progress bar. |
|
|
68
|
+
| `barLabels` | `boolean` | If `true`, displays percentage labels on the bar. |
|
|
69
|
+
| `barStyle` | `'solid' \| 'stripe' \| 'circle' \| 'rectangle'` | The visual style of the progress bar segments. Defaults to `solid`. |
|
|
70
|
+
| `categoryLabelsOrientation` | `'top' \| 'bottom' \| 'left' \| 'right'` | The orientation of category labels relative to the bar. |
|
|
71
|
+
| `categoryLabelStyle` | `'basic' \| 'widget'` | The display style for category labels. |
|
|
72
|
+
| `showCategoryLabels` | `boolean` | If `true`, displays the category labels. |
|
|
73
|
+
| `categories` | `CategoryConfig[]` | An array of category configurations that make up the progress bar. |
|
|
74
|
+
| `unitType` | `string` | An optional unit to display next to the value (e.g., 'MB', 'GB', '%'). |
|
|
75
|
+
|
|
76
|
+
### `CategoryConfig`
|
|
77
|
+
This object defines the configuration for each segment within the progress bar.
|
|
78
|
+
|
|
79
|
+
| Property | Type | Description |
|
|
80
|
+
|-----------|------------------------------------|--------------------------------------------------------------------------|
|
|
81
|
+
| `label` | `string` | The label for the category, displayed in the legend and on hover. |
|
|
82
|
+
| `color` | `string` | The color of the category segment (e.g., `'#34d399'`, `'rgb(251,191,36)'`). |
|
|
83
|
+
| `value` | `number` | The value of the category. |
|
|
84
|
+
| `icon` | `string` (optional) | The name of a Material Icon to display for the category. If empty, a colored dot is shown. |
|
|
85
|
+
| `handler` | `(event?: any) => void` (optional) | A function to handle events for the category (e.g., click). |
|
|
86
|
+
|
|
87
|
+
## Example Configuration
|
|
88
|
+
|
|
89
|
+
Here's an example of how to configure the Metered Progress Bar in your component's TypeScript file.
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { Component } from '@angular/core';
|
|
93
|
+
import { MeteredBarConfig } from '@uxpractice/metered-progress-bar';
|
|
94
|
+
|
|
95
|
+
@Component({
|
|
96
|
+
selector: 'app-root',
|
|
97
|
+
templateUrl: './app.component.html',
|
|
98
|
+
})
|
|
99
|
+
export class AppComponent {
|
|
100
|
+
meteredBarConfig: MeteredBarConfig = {
|
|
101
|
+
min: 0,
|
|
102
|
+
max: 150,
|
|
103
|
+
orientation: 'horizontal',
|
|
104
|
+
barLabels: true,
|
|
105
|
+
barStyle: 'stripe',
|
|
106
|
+
categoryLabelsOrientation: 'bottom',
|
|
107
|
+
categoryLabelStyle: 'widget',
|
|
108
|
+
showCategoryLabels: true,
|
|
109
|
+
categories: [
|
|
110
|
+
{ label: 'Applications', color: '#34d399', value: 95, icon: 'apps' },
|
|
111
|
+
{ label: 'Messages', color: '#fbbf24', value: 15, icon: 'message' },
|
|
112
|
+
{ label: 'Media', color: '#60a5fa', value: 21, icon: 'perm_media' },
|
|
113
|
+
{ label: 'Photos', color: '#6055ea', value: 12, icon: 'collections' }
|
|
114
|
+
],
|
|
115
|
+
unitType: 'MB'
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Contribution
|
|
121
|
+
|
|
122
|
+
Contributions are welcome! Feel free to open issues or pull requests for any enhancements or fixes.
|
|
123
|
+
|
|
124
|
+
## Acknowledgements
|
|
125
|
+
|
|
126
|
+
Thank you for choosing the Metered Progress Bar component. If you have any feedback or suggestions, please let us know!
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export * from './lib/ruclib-metered-progress-bar.module';
|
|
2
|
+
export * from './lib/model/metered-bar.config';
|
|
3
|
+
export * from './lib/ruc-metered-progress-bar/ruc-metered-progress-bar.component';
|
|
4
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYywwQ0FBMEMsQ0FBQztBQUN6RCxjQUFjLGdDQUFnQyxDQUFDO0FBQy9DLGNBQWMsbUVBQW1FLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tICcuL2xpYi9ydWNsaWItbWV0ZXJlZC1wcm9ncmVzcy1iYXIubW9kdWxlJztcclxuZXhwb3J0ICogZnJvbSAnLi9saWIvbW9kZWwvbWV0ZXJlZC1iYXIuY29uZmlnJztcclxuZXhwb3J0ICogZnJvbSAnLi9saWIvcnVjLW1ldGVyZWQtcHJvZ3Jlc3MtYmFyL3J1Yy1tZXRlcmVkLXByb2dyZXNzLWJhci5jb21wb25lbnQnO1xyXG4iXX0=
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export var LablePositionEnums;
|
|
2
|
+
(function (LablePositionEnums) {
|
|
3
|
+
LablePositionEnums["left"] = "left";
|
|
4
|
+
LablePositionEnums["right"] = "right";
|
|
5
|
+
LablePositionEnums["same"] = "same";
|
|
6
|
+
LablePositionEnums["top"] = "top";
|
|
7
|
+
LablePositionEnums["bottom"] = "bottom";
|
|
8
|
+
})(LablePositionEnums || (LablePositionEnums = {}));
|
|
9
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGFibGUtcG9zaXRpb24uZW51bS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvZW51bXMvbGFibGUtcG9zaXRpb24uZW51bS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxNQUFNLENBQU4sSUFBWSxrQkFNWDtBQU5ELFdBQVksa0JBQWtCO0lBQzFCLG1DQUFhLENBQUE7SUFDYixxQ0FBZSxDQUFBO0lBQ2YsbUNBQWEsQ0FBQTtJQUNiLGlDQUFXLENBQUE7SUFDWCx1Q0FBaUIsQ0FBQTtBQUNyQixDQUFDLEVBTlcsa0JBQWtCLEtBQWxCLGtCQUFrQixRQU03QiIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBlbnVtIExhYmxlUG9zaXRpb25FbnVtcyB7XHJcbiAgICBsZWZ0ID0gXCJsZWZ0XCIsXHJcbiAgICByaWdodCA9IFwicmlnaHRcIixcclxuICAgIHNhbWUgPSBcInNhbWVcIixcclxuICAgIHRvcCA9IFwidG9wXCIsXHJcbiAgICBib3R0b20gPSAnYm90dG9tJ1xyXG59XHJcbiJdfQ==
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export class MeteredBarConfig {
|
|
2
|
+
}
|
|
3
|
+
export class CategoryConfig {
|
|
4
|
+
}
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0ZXJlZC1iYXIuY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9tb2RlbC9tZXRlcmVkLWJhci5jb25maWcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsTUFBTSxPQUFPLGdCQUFnQjtDQVc1QjtBQUVELE1BQU0sT0FBTyxjQUFjO0NBTTFCIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGNsYXNzIE1ldGVyZWRCYXJDb25maWcge1xyXG4gICAgbWluITogbnVtYmVyO1xyXG4gICAgbWF4ITogbnVtYmVyO1xyXG4gICAgb3JpZW50YXRpb24hOiBzdHJpbmc7XHJcbiAgICBiYXJMYWJlbHMhOiBib29sZWFuO1xyXG4gICAgYmFyU3R5bGU/OiAnc29saWQnIHwgJ3N0cmlwZScgfCAnY2lyY2xlJyB8ICdyZWN0YW5nbGUnO1xyXG4gICAgY2F0ZWdvcnlMYWJlbHNPcmllbnRhdGlvbiE6IHN0cmluZztcclxuICAgIGNhdGVnb3J5TGFiZWxTdHlsZT86IHN0cmluZztcclxuICAgIHNob3dDYXRlZ29yeUxhYmVscz86IGJvb2xlYW47XHJcbiAgICBjYXRlZ29yaWVzITogQ2F0ZWdvcnlDb25maWdbXTtcclxuICAgIHVuaXRUeXBlPzogc3RyaW5nXHJcbn1cclxuXHJcbmV4cG9ydCBjbGFzcyBDYXRlZ29yeUNvbmZpZyB7XHJcbiAgICBsYWJlbCE6IHN0cmluZztcclxuICAgIGNvbG9yITogc3RyaW5nO1xyXG4gICAgdmFsdWUhOiBudW1iZXI7XHJcbiAgICBpY29uPzogc3RyaW5nO1xyXG4gICAgaGFuZGxlcj86IChldmVudD86IGFueSkgPT4gdm9pZDtcclxufVxyXG4iXX0=
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { Component, Input } from '@angular/core';
|
|
2
|
+
import { MeteredBarConfig } from '../model/metered-bar.config';
|
|
3
|
+
import { LablePositionEnums } from '../enums/lable-position.enum';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
import * as i1 from "@angular/common";
|
|
6
|
+
export class RucMeteredProgressBarComponent {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.hoveredCategoryDetail = null;
|
|
9
|
+
this.hoverLabelStyle = { left: '0px', top: '-28px', display: 'none', transform: 'translateX(-50%)' };
|
|
10
|
+
this.progressPercentage = 0;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Calculates the total value of all categories.
|
|
14
|
+
* @returns The sum of all category values.
|
|
15
|
+
*/
|
|
16
|
+
get totalValue() {
|
|
17
|
+
return this.rucInputData.categories.reduce((sum, category) => sum + category.value, 0);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Calculates the overall progress percentage of the bar based on total value, min, and max.
|
|
21
|
+
* @returns The progress as a percentage (0-100).
|
|
22
|
+
*/
|
|
23
|
+
get progress() {
|
|
24
|
+
return ((this.totalValue - this.rucInputData.min) / (this.rucInputData.max - this.rucInputData.min)) * 100;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Determines if the progress bar is oriented vertically.
|
|
28
|
+
* @returns True if the orientation is 'vertical', false otherwise.
|
|
29
|
+
*/
|
|
30
|
+
get isVertical() {
|
|
31
|
+
return this.rucInputData.orientation === 'vertical';
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Generates the CSS linear-gradient string for the progress bar.
|
|
35
|
+
* The gradient is composed of segments based on category values and colors.
|
|
36
|
+
* If no categories or total value is zero, it returns a transparent gradient.
|
|
37
|
+
* @returns A CSS linear-gradient string.
|
|
38
|
+
*/
|
|
39
|
+
get progressStyles() {
|
|
40
|
+
const direction = this.isVertical ? 'to bottom' : 'to right';
|
|
41
|
+
if (!this.rucInputData || !this.rucInputData.categories) {
|
|
42
|
+
return { background: 'transparent' };
|
|
43
|
+
}
|
|
44
|
+
const total = this.totalValue;
|
|
45
|
+
const colorStops = [];
|
|
46
|
+
let cumulativePercentage = 0;
|
|
47
|
+
if (total > 0) {
|
|
48
|
+
this.rucInputData.categories.forEach(category => {
|
|
49
|
+
if (category.value <= 0)
|
|
50
|
+
return; // Skip categories with zero or negative contribution
|
|
51
|
+
const segmentPercentage = (category.value / total) * 100;
|
|
52
|
+
const color = category.color;
|
|
53
|
+
// Add start of the segment using the previous cumulative percentage
|
|
54
|
+
colorStops.push(`${color} ${cumulativePercentage}%`);
|
|
55
|
+
// Update cumulative percentage for the end of this segment
|
|
56
|
+
cumulativePercentage += segmentPercentage;
|
|
57
|
+
// Add end of the segment
|
|
58
|
+
// Use Math.min to cap at 100% in case of floating point overshoot on the last segment
|
|
59
|
+
colorStops.push(`${color} ${Math.min(cumulativePercentage, 100)}%`);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
if (colorStops.length === 0) {
|
|
63
|
+
return { background: 'transparent' };
|
|
64
|
+
}
|
|
65
|
+
const baseGradient = `linear-gradient(${direction}, ${colorStops.join(', ')})`;
|
|
66
|
+
const styles = {};
|
|
67
|
+
const barStyle = this.rucInputData?.barStyle;
|
|
68
|
+
switch (barStyle) {
|
|
69
|
+
case 'stripe':
|
|
70
|
+
// This uses multiple backgrounds for an overlay effect, as requested.
|
|
71
|
+
styles['background'] = `repeating-linear-gradient(-45deg, transparent, transparent 5px, rgba(0, 0, 0, 0.1) 5px, rgba(0, 0, 0, 0.1) 10px), ${baseGradient}`;
|
|
72
|
+
break;
|
|
73
|
+
case 'circle': {
|
|
74
|
+
// This uses a mask. The background is the color, the mask cuts out the shape.
|
|
75
|
+
styles['background'] = baseGradient;
|
|
76
|
+
// A repeating pattern of circles. Each circle has a diameter of 8px, with a 4px gap.
|
|
77
|
+
const circleMask = 'radial-gradient(circle, black 4px, transparent 4px) 0 0 / 12px 12px';
|
|
78
|
+
styles['-webkit-mask'] = circleMask;
|
|
79
|
+
styles['mask'] = circleMask;
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
case 'rectangle': {
|
|
83
|
+
styles['background'] = baseGradient;
|
|
84
|
+
// For vertical bar, create horizontal rectangles (0deg). For horizontal bar, create vertical rectangles (90deg).
|
|
85
|
+
const rectDirection = this.isVertical ? '0deg' : '90deg';
|
|
86
|
+
// A repeating pattern of bars. Each bar is 6px wide with a 6px gap.
|
|
87
|
+
const rectangleMask = `repeating-linear-gradient(${rectDirection}, black, black 6px, transparent 6px, transparent 12px)`;
|
|
88
|
+
styles['-webkit-mask'] = rectangleMask;
|
|
89
|
+
styles['mask'] = rectangleMask;
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
default: // 'solid' or undefined
|
|
93
|
+
styles['background'] = baseGradient;
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
return styles;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Handles mouse movement over the progress bar to display category-specific hover details.
|
|
100
|
+
* It calculates the hovered segment based on mouse position and updates the hover label.
|
|
101
|
+
* @param event The MouseEvent object.
|
|
102
|
+
*/
|
|
103
|
+
onProgressMouseMove(event) {
|
|
104
|
+
const progressBarElement = event.target;
|
|
105
|
+
let currentCumulativeGradientPct = 0;
|
|
106
|
+
let foundCategoryForHover = null;
|
|
107
|
+
let hoverPercentage_onFilledBar = 0;
|
|
108
|
+
let mousePositionWithinProgressDiv = 0;
|
|
109
|
+
if (this.isVertical) {
|
|
110
|
+
mousePositionWithinProgressDiv = event.offsetY; // Y position within the .progress div
|
|
111
|
+
const filledHeightPx = progressBarElement.offsetHeight;
|
|
112
|
+
if (filledHeightPx <= 0) { // Avoid division by zero if element has no height
|
|
113
|
+
this.onProgressMouseLeave();
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
hoverPercentage_onFilledBar = (mousePositionWithinProgressDiv / filledHeightPx) * 100;
|
|
117
|
+
}
|
|
118
|
+
else { // Horizontal
|
|
119
|
+
mousePositionWithinProgressDiv = event.offsetX; // X position within the .progress div
|
|
120
|
+
const filledWidthPx = progressBarElement.offsetWidth;
|
|
121
|
+
if (filledWidthPx <= 0) { // Avoid division by zero if element has no width
|
|
122
|
+
this.onProgressMouseLeave();
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
hoverPercentage_onFilledBar = (mousePositionWithinProgressDiv / filledWidthPx) * 100;
|
|
126
|
+
}
|
|
127
|
+
if (this.totalValue > 0) {
|
|
128
|
+
for (const category of this.rucInputData.categories) {
|
|
129
|
+
if (category.value <= 0)
|
|
130
|
+
continue; // Skip categories with zero or negative contribution
|
|
131
|
+
const segmentGradientPct = (category.value / this.totalValue) * 100;
|
|
132
|
+
const segmentStartGradientPct = currentCumulativeGradientPct;
|
|
133
|
+
const segmentEndGradientPct = currentCumulativeGradientPct + segmentGradientPct;
|
|
134
|
+
// Ensure hoverPercentage is within the segment, handling potential floating point inaccuracies for the last segment
|
|
135
|
+
if (hoverPercentage_onFilledBar >= segmentStartGradientPct && // Check if mouse is within or at the start of the segment
|
|
136
|
+
(hoverPercentage_onFilledBar < segmentEndGradientPct ||
|
|
137
|
+
(segmentEndGradientPct >= 99.99 && hoverPercentage_onFilledBar <= 100.01))) { // Tolerate slight overshoot for last segment
|
|
138
|
+
foundCategoryForHover = category;
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
currentCumulativeGradientPct = segmentEndGradientPct;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (foundCategoryForHover) {
|
|
145
|
+
const percentageOfMax = (foundCategoryForHover.value / this.rucInputData.max) * 100; // Calculate percentage relative to max value
|
|
146
|
+
this.hoveredCategoryDetail = { category: foundCategoryForHover, percentageText: percentageOfMax.toFixed(0) + '%' };
|
|
147
|
+
if (this.isVertical) {
|
|
148
|
+
this.hoverLabelStyle = {
|
|
149
|
+
left: 'calc(100% + 5px)',
|
|
150
|
+
top: mousePositionWithinProgressDiv + 'px',
|
|
151
|
+
display: 'block',
|
|
152
|
+
transform: 'translateY(-50%)' // Vertically center label on mouse Y
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
this.hoverLabelStyle = {
|
|
157
|
+
left: mousePositionWithinProgressDiv + 'px',
|
|
158
|
+
top: '-28px',
|
|
159
|
+
display: 'block',
|
|
160
|
+
transform: 'translateX(-50%)' // Horizontally center label on mouse X
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
this.hoveredCategoryDetail = null;
|
|
166
|
+
this.hoverLabelStyle = { ...this.hoverLabelStyle, display: 'none' };
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Hides the hover label when the mouse leaves the progress bar.
|
|
171
|
+
*/
|
|
172
|
+
onProgressMouseLeave() {
|
|
173
|
+
this.hoveredCategoryDetail = null;
|
|
174
|
+
this.hoverLabelStyle = { ...this.hoverLabelStyle, display: 'none' };
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* get the label position string value
|
|
178
|
+
*/
|
|
179
|
+
get LablePositionEnums() {
|
|
180
|
+
return LablePositionEnums;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
RucMeteredProgressBarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RucMeteredProgressBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
184
|
+
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" }] });
|
|
185
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RucMeteredProgressBarComponent, decorators: [{
|
|
186
|
+
type: Component,
|
|
187
|
+
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"] }]
|
|
188
|
+
}], propDecorators: { rucInputData: [{
|
|
189
|
+
type: Input
|
|
190
|
+
}], customTheme: [{
|
|
191
|
+
type: Input
|
|
192
|
+
}] } });
|
|
193
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVjLW1ldGVyZWQtcHJvZ3Jlc3MtYmFyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvcnVjLW1ldGVyZWQtcHJvZ3Jlc3MtYmFyL3J1Yy1tZXRlcmVkLXByb2dyZXNzLWJhci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9zcmMvbGliL3J1Yy1tZXRlcmVkLXByb2dyZXNzLWJhci9ydWMtbWV0ZXJlZC1wcm9ncmVzcy1iYXIuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDakQsT0FBTyxFQUFrQixnQkFBZ0IsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQy9FLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDhCQUE4QixDQUFDOzs7QUFVbEUsTUFBTSxPQUFPLDhCQUE4QjtJQVAzQztRQVVFLDBCQUFxQixHQUFnRSxJQUFJLENBQUM7UUFDMUYsb0JBQWUsR0FBdUUsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsa0JBQWtCLEVBQUUsQ0FBQztRQUNwSyx1QkFBa0IsR0FBRyxDQUFDLENBQUM7S0F5THhCO0lBeExDOzs7T0FHRztJQUNILElBQUksVUFBVTtRQUNaLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLFFBQVEsRUFBRSxFQUFFLENBQUMsR0FBRyxHQUFHLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDekYsQ0FBQztJQUVEOzs7T0FHRztJQUNILElBQUksUUFBUTtRQUNWLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUM7SUFDN0csQ0FBQztJQUVEOzs7T0FHRztJQUNILElBQUksVUFBVTtRQUNaLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLEtBQUssVUFBVSxDQUFDO0lBQ3RELENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILElBQUksY0FBYztRQUNoQixNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQztRQUU3RCxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsVUFBVSxFQUFFO1lBQ3ZELE9BQU8sRUFBRSxVQUFVLEVBQUUsYUFBYSxFQUFFLENBQUM7U0FDdEM7UUFFRCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDO1FBQzlCLE1BQU0sVUFBVSxHQUFhLEVBQUUsQ0FBQztRQUNoQyxJQUFJLG9CQUFvQixHQUFHLENBQUMsQ0FBQztRQUU3QixJQUFJLEtBQUssR0FBRyxDQUFDLEVBQUU7WUFDYixJQUFJLENBQUMsWUFBWSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEVBQUU7Z0JBQzlDLElBQUksUUFBUSxDQUFDLEtBQUssSUFBSSxDQUFDO29CQUFFLE9BQU8sQ0FBQyxxREFBcUQ7Z0JBRXRGLE1BQU0saUJBQWlCLEdBQUcsQ0FBQyxRQUFRLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQyxHQUFHLEdBQUcsQ0FBQztnQkFDekQsTUFBTSxLQUFLLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQztnQkFFN0Isb0VBQW9FO2dCQUNwRSxVQUFVLENBQUMsSUFBSSxDQUFDLEdBQUcsS0FBSyxJQUFJLG9CQUFvQixHQUFHLENBQUMsQ0FBQztnQkFFckQsMkRBQTJEO2dCQUMzRCxvQkFBb0IsSUFBSSxpQkFBaUIsQ0FBQztnQkFFMUMseUJBQXlCO2dCQUN6QixzRkFBc0Y7Z0JBQ3RGLFVBQVUsQ0FBQyxJQUFJLENBQUMsR0FBRyxLQUFLLElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxvQkFBb0IsRUFBRSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDdEUsQ0FBQyxDQUFDLENBQUM7U0FDSjtRQUVELElBQUksVUFBVSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7WUFDM0IsT0FBTyxFQUFFLFVBQVUsRUFBRSxhQUFhLEVBQUUsQ0FBQztTQUN0QztRQUVELE1BQU0sWUFBWSxHQUFHLG1CQUFtQixTQUFTLEtBQUssVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDO1FBQy9FLE1BQU0sTUFBTSxHQUE4QixFQUFFLENBQUM7UUFDN0MsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFlBQVksRUFBRSxRQUFRLENBQUM7UUFFN0MsUUFBUSxRQUFRLEVBQUU7WUFDaEIsS0FBSyxRQUFRO2dCQUNYLHNFQUFzRTtnQkFDdEUsTUFBTSxDQUFDLFlBQVksQ0FBQyxHQUFHLHFIQUFxSCxZQUFZLEVBQUUsQ0FBQztnQkFDM0osTUFBTTtZQUNSLEtBQUssUUFBUSxDQUFDLENBQUM7Z0JBQ2IsOEVBQThFO2dCQUM5RSxNQUFNLENBQUMsWUFBWSxDQUFDLEdBQUcsWUFBWSxDQUFDO2dCQUNwQyxxRkFBcUY7Z0JBQ3JGLE1BQU0sVUFBVSxHQUFHLHFFQUFxRSxDQUFDO2dCQUN6RixNQUFNLENBQUMsY0FBYyxDQUFDLEdBQUcsVUFBVSxDQUFDO2dCQUNwQyxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsVUFBVSxDQUFDO2dCQUM1QixNQUFNO2FBQ1A7WUFDRCxLQUFLLFdBQVcsQ0FBQyxDQUFDO2dCQUNoQixNQUFNLENBQUMsWUFBWSxDQUFDLEdBQUcsWUFBWSxDQUFDO2dCQUNwQyxpSEFBaUg7Z0JBQ2pILE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO2dCQUN6RCxvRUFBb0U7Z0JBQ3BFLE1BQU0sYUFBYSxHQUFHLDZCQUE2QixhQUFhLHdEQUF3RCxDQUFDO2dCQUN6SCxNQUFNLENBQUMsY0FBYyxDQUFDLEdBQUcsYUFBYSxDQUFDO2dCQUN2QyxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsYUFBYSxDQUFDO2dCQUMvQixNQUFNO2FBQ1A7WUFDRCxTQUFTLHVCQUF1QjtnQkFDOUIsTUFBTSxDQUFDLFlBQVksQ0FBQyxHQUFHLFlBQVksQ0FBQztnQkFDcEMsTUFBTTtTQUNUO1FBQ0QsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQUNEOzs7O09BSUc7SUFDSCxtQkFBbUIsQ0FBQyxLQUFpQjtRQUNuQyxNQUFNLGtCQUFrQixHQUFHLEtBQUssQ0FBQyxNQUFxQixDQUFDO1FBQ3ZELElBQUksNEJBQTRCLEdBQUcsQ0FBQyxDQUFDO1FBQ3JDLElBQUkscUJBQXFCLEdBQTBCLElBQUksQ0FBQztRQUN4RCxJQUFJLDJCQUEyQixHQUFHLENBQUMsQ0FBQztRQUNwQyxJQUFJLDhCQUE4QixHQUFHLENBQUMsQ0FBQztRQUV2QyxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUU7WUFDbkIsOEJBQThCLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLHNDQUFzQztZQUN0RixNQUFNLGNBQWMsR0FBRyxrQkFBa0IsQ0FBQyxZQUFZLENBQUM7WUFDdkQsSUFBSSxjQUFjLElBQUksQ0FBQyxFQUFFLEVBQUUsa0RBQWtEO2dCQUMzRSxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztnQkFDNUIsT0FBTzthQUNSO1lBQ0QsMkJBQTJCLEdBQUcsQ0FBQyw4QkFBOEIsR0FBRyxjQUFjLENBQUMsR0FBRyxHQUFHLENBQUM7U0FDdkY7YUFBTSxFQUFFLGFBQWE7WUFDcEIsOEJBQThCLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLHNDQUFzQztZQUN0RixNQUFNLGFBQWEsR0FBRyxrQkFBa0IsQ0FBQyxXQUFXLENBQUM7WUFDckQsSUFBSSxhQUFhLElBQUksQ0FBQyxFQUFFLEVBQUUsaURBQWlEO2dCQUN6RSxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztnQkFDNUIsT0FBTzthQUNSO1lBQ0QsMkJBQTJCLEdBQUcsQ0FBQyw4QkFBOEIsR0FBRyxhQUFhLENBQUMsR0FBRyxHQUFHLENBQUM7U0FDdEY7UUFFRCxJQUFJLElBQUksQ0FBQyxVQUFVLEdBQUcsQ0FBQyxFQUFFO1lBQ3ZCLEtBQUssTUFBTSxRQUFRLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxVQUFVLEVBQUU7Z0JBQ25ELElBQUksUUFBUSxDQUFDLEtBQUssSUFBSSxDQUFDO29CQUFFLFNBQVMsQ0FBQyxxREFBcUQ7Z0JBRXhGLE1BQU0sa0JBQWtCLEdBQUcsQ0FBQyxRQUFRLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxHQUFHLENBQUM7Z0JBQ3BFLE1BQU0sdUJBQXVCLEdBQUcsNEJBQTRCLENBQUM7Z0JBQzdELE1BQU0scUJBQXFCLEdBQUcsNEJBQTRCLEdBQUcsa0JBQWtCLENBQUM7Z0JBRWhGLG9IQUFvSDtnQkFDcEgsSUFBSSwyQkFBMkIsSUFBSSx1QkFBdUIsSUFBSSwwREFBMEQ7b0JBQ3RILENBQUMsMkJBQTJCLEdBQUcscUJBQXFCO3dCQUNsRCxDQUFDLHFCQUFxQixJQUFJLEtBQUssSUFBSSwyQkFBMkIsSUFBSSxNQUFNLENBQUMsQ0FBQyxFQUFFLEVBQUUsNkNBQTZDO29CQUM3SCxxQkFBcUIsR0FBRyxRQUFRLENBQUM7b0JBQ2pDLE1BQU07aUJBQ1A7Z0JBQ0QsNEJBQTRCLEdBQUcscUJBQXFCLENBQUM7YUFDdEQ7U0FDRjtRQUVELElBQUkscUJBQXFCLEVBQUU7WUFDekIsTUFBTSxlQUFlLEdBQUcsQ0FBQyxxQkFBcUIsQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyw2Q0FBNkM7WUFDbEksSUFBSSxDQUFDLHFCQUFxQixHQUFHLEVBQUUsUUFBUSxFQUFFLHFCQUFxQixFQUFFLGNBQWMsRUFBRSxlQUFlLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDO1lBQ25ILElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRTtnQkFDbkIsSUFBSSxDQUFDLGVBQWUsR0FBRztvQkFDckIsSUFBSSxFQUFFLGtCQUFrQjtvQkFDeEIsR0FBRyxFQUFFLDhCQUE4QixHQUFHLElBQUk7b0JBQzFDLE9BQU8sRUFBRSxPQUFPO29CQUNoQixTQUFTLEVBQUUsa0JBQWtCLENBQUMscUNBQXFDO2lCQUNwRSxDQUFDO2FBQ0g7aUJBQU07Z0JBQ0wsSUFBSSxDQUFDLGVBQWUsR0FBRztvQkFDckIsSUFBSSxFQUFFLDhCQUE4QixHQUFHLElBQUk7b0JBQzNDLEdBQUcsRUFBRSxPQUFPO29CQUNaLE9BQU8sRUFBRSxPQUFPO29CQUNoQixTQUFTLEVBQUUsa0JBQWtCLENBQUMsdUNBQXVDO2lCQUN0RSxDQUFDO2FBQ0g7U0FDRjthQUFNO1lBQ0wsSUFBSSxDQUFDLHFCQUFxQixHQUFHLElBQUksQ0FBQztZQUNsQyxJQUFJLENBQUMsZUFBZSxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsZUFBZSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsQ0FBQztTQUNyRTtJQUNILENBQUM7SUFFRDs7T0FFRztJQUNILG9CQUFvQjtRQUNsQixJQUFJLENBQUMscUJBQXFCLEdBQUcsSUFBSSxDQUFDO1FBQ2xDLElBQUksQ0FBQyxlQUFlLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxlQUFlLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxDQUFDO0lBQ3RFLENBQUM7SUFDRDs7U0FFSztJQUNMLElBQVcsa0JBQWtCO1FBQzNCLE9BQU8sa0JBQWtCLENBQUM7SUFDNUIsQ0FBQzs7NEhBN0xVLDhCQUE4QjtnSEFBOUIsOEJBQThCLDBJQ1ozQyxvdEtBaUZNOzRGRHJFTyw4QkFBOEI7a0JBUDFDLFNBQVM7K0JBQ0UsOEJBQThCOzhCQU8vQixZQUFZO3NCQUFwQixLQUFLO2dCQUNHLFdBQVc7c0JBQW5CLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIElucHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IENhdGVnb3J5Q29uZmlnLCBNZXRlcmVkQmFyQ29uZmlnIH0gZnJvbSAnLi4vbW9kZWwvbWV0ZXJlZC1iYXIuY29uZmlnJztcclxuaW1wb3J0IHsgTGFibGVQb3NpdGlvbkVudW1zIH0gZnJvbSAnLi4vZW51bXMvbGFibGUtcG9zaXRpb24uZW51bSc7XHJcblxyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICd1eHAtcnVjLW1ldGVyZWQtcHJvZ3Jlc3MtYmFyJyxcclxuICB0ZW1wbGF0ZVVybDogJy4vcnVjLW1ldGVyZWQtcHJvZ3Jlc3MtYmFyLmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi9ydWMtbWV0ZXJlZC1wcm9ncmVzcy1iYXIuY29tcG9uZW50LnNjc3MnXSxcclxufSlcclxuXHJcblxyXG5leHBvcnQgY2xhc3MgUnVjTWV0ZXJlZFByb2dyZXNzQmFyQ29tcG9uZW50IHtcclxuICBASW5wdXQoKSBydWNJbnB1dERhdGEhOiBNZXRlcmVkQmFyQ29uZmlnO1xyXG4gIEBJbnB1dCgpIGN1c3RvbVRoZW1lITogc3RyaW5nO1xyXG4gIGhvdmVyZWRDYXRlZ29yeURldGFpbDogeyBjYXRlZ29yeTogQ2F0ZWdvcnlDb25maWcsIHBlcmNlbnRhZ2VUZXh0OiBzdHJpbmcgfSB8IG51bGwgPSBudWxsO1xyXG4gIGhvdmVyTGFiZWxTdHlsZTogeyBsZWZ0OiBzdHJpbmc7IHRvcDogc3RyaW5nOyBkaXNwbGF5OiBzdHJpbmc7IHRyYW5zZm9ybTogc3RyaW5nOyB9ID0geyBsZWZ0OiAnMHB4JywgdG9wOiAnLTI4cHgnLCBkaXNwbGF5OiAnbm9uZScsIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZVgoLTUwJSknIH07XHJcbiAgcHJvZ3Jlc3NQZXJjZW50YWdlID0gMDtcclxuICAvKipcclxuICAgKiBDYWxjdWxhdGVzIHRoZSB0b3RhbCB2YWx1ZSBvZiBhbGwgY2F0ZWdvcmllcy5cclxuICAgKiBAcmV0dXJucyBUaGUgc3VtIG9mIGFsbCBjYXRlZ29yeSB2YWx1ZXMuXHJcbiAgICovXHJcbiAgZ2V0IHRvdGFsVmFsdWUoKTogbnVtYmVyIHtcclxuICAgIHJldHVybiB0aGlzLnJ1Y0lucHV0RGF0YS5jYXRlZ29yaWVzLnJlZHVjZSgoc3VtLCBjYXRlZ29yeSkgPT4gc3VtICsgY2F0ZWdvcnkudmFsdWUsIDApO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ2FsY3VsYXRlcyB0aGUgb3ZlcmFsbCBwcm9ncmVzcyBwZXJjZW50YWdlIG9mIHRoZSBiYXIgYmFzZWQgb24gdG90YWwgdmFsdWUsIG1pbiwgYW5kIG1heC5cclxuICAgKiBAcmV0dXJucyBUaGUgcHJvZ3Jlc3MgYXMgYSBwZXJjZW50YWdlICgwLTEwMCkuXHJcbiAgICovXHJcbiAgZ2V0IHByb2dyZXNzKCk6IG51bWJlciB7XHJcbiAgICByZXR1cm4gKCh0aGlzLnRvdGFsVmFsdWUgLSB0aGlzLnJ1Y0lucHV0RGF0YS5taW4pIC8gKHRoaXMucnVjSW5wdXREYXRhLm1heCAtIHRoaXMucnVjSW5wdXREYXRhLm1pbikpICogMTAwO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRGV0ZXJtaW5lcyBpZiB0aGUgcHJvZ3Jlc3MgYmFyIGlzIG9yaWVudGVkIHZlcnRpY2FsbHkuXHJcbiAgICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgb3JpZW50YXRpb24gaXMgJ3ZlcnRpY2FsJywgZmFsc2Ugb3RoZXJ3aXNlLlxyXG4gICAqL1xyXG4gIGdldCBpc1ZlcnRpY2FsKCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHRoaXMucnVjSW5wdXREYXRhLm9yaWVudGF0aW9uID09PSAndmVydGljYWwnO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2VuZXJhdGVzIHRoZSBDU1MgbGluZWFyLWdyYWRpZW50IHN0cmluZyBmb3IgdGhlIHByb2dyZXNzIGJhci5cclxuICAgKiBUaGUgZ3JhZGllbnQgaXMgY29tcG9zZWQgb2Ygc2VnbWVudHMgYmFzZWQgb24gY2F0ZWdvcnkgdmFsdWVzIGFuZCBjb2xvcnMuXHJcbiAgICogSWYgbm8gY2F0ZWdvcmllcyBvciB0b3RhbCB2YWx1ZSBpcyB6ZXJvLCBpdCByZXR1cm5zIGEgdHJhbnNwYXJlbnQgZ3JhZGllbnQuXHJcbiAgICogQHJldHVybnMgQSBDU1MgbGluZWFyLWdyYWRpZW50IHN0cmluZy5cclxuICAgKi9cclxuICBnZXQgcHJvZ3Jlc3NTdHlsZXMoKTogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSB7XHJcbiAgICBjb25zdCBkaXJlY3Rpb24gPSB0aGlzLmlzVmVydGljYWwgPyAndG8gYm90dG9tJyA6ICd0byByaWdodCc7XHJcblxyXG4gICAgaWYgKCF0aGlzLnJ1Y0lucHV0RGF0YSB8fCAhdGhpcy5ydWNJbnB1dERhdGEuY2F0ZWdvcmllcykge1xyXG4gICAgICByZXR1cm4geyBiYWNrZ3JvdW5kOiAndHJhbnNwYXJlbnQnIH07XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgdG90YWwgPSB0aGlzLnRvdGFsVmFsdWU7XHJcbiAgICBjb25zdCBjb2xvclN0b3BzOiBzdHJpbmdbXSA9IFtdO1xyXG4gICAgbGV0IGN1bXVsYXRpdmVQZXJjZW50YWdlID0gMDtcclxuXHJcbiAgICBpZiAodG90YWwgPiAwKSB7XHJcbiAgICAgIHRoaXMucnVjSW5wdXREYXRhLmNhdGVnb3JpZXMuZm9yRWFjaChjYXRlZ29yeSA9PiB7XHJcbiAgICAgICAgaWYgKGNhdGVnb3J5LnZhbHVlIDw9IDApIHJldHVybjsgLy8gU2tpcCBjYXRlZ29yaWVzIHdpdGggemVybyBvciBuZWdhdGl2ZSBjb250cmlidXRpb25cclxuXHJcbiAgICAgICAgY29uc3Qgc2VnbWVudFBlcmNlbnRhZ2UgPSAoY2F0ZWdvcnkudmFsdWUgLyB0b3RhbCkgKiAxMDA7XHJcbiAgICAgICAgY29uc3QgY29sb3IgPSBjYXRlZ29yeS5jb2xvcjtcclxuXHJcbiAgICAgICAgLy8gQWRkIHN0YXJ0IG9mIHRoZSBzZWdtZW50IHVzaW5nIHRoZSBwcmV2aW91cyBjdW11bGF0aXZlIHBlcmNlbnRhZ2VcclxuICAgICAgICBjb2xvclN0b3BzLnB1c2goYCR7Y29sb3J9ICR7Y3VtdWxhdGl2ZVBlcmNlbnRhZ2V9JWApO1xyXG5cclxuICAgICAgICAvLyBVcGRhdGUgY3VtdWxhdGl2ZSBwZXJjZW50YWdlIGZvciB0aGUgZW5kIG9mIHRoaXMgc2VnbWVudFxyXG4gICAgICAgIGN1bXVsYXRpdmVQZXJjZW50YWdlICs9IHNlZ21lbnRQZXJjZW50YWdlO1xyXG5cclxuICAgICAgICAvLyBBZGQgZW5kIG9mIHRoZSBzZWdtZW50XHJcbiAgICAgICAgLy8gVXNlIE1hdGgubWluIHRvIGNhcCBhdCAxMDAlIGluIGNhc2Ugb2YgZmxvYXRpbmcgcG9pbnQgb3ZlcnNob290IG9uIHRoZSBsYXN0IHNlZ21lbnRcclxuICAgICAgICBjb2xvclN0b3BzLnB1c2goYCR7Y29sb3J9ICR7TWF0aC5taW4oY3VtdWxhdGl2ZVBlcmNlbnRhZ2UsIDEwMCl9JWApO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoY29sb3JTdG9wcy5sZW5ndGggPT09IDApIHtcclxuICAgICAgcmV0dXJuIHsgYmFja2dyb3VuZDogJ3RyYW5zcGFyZW50JyB9O1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGJhc2VHcmFkaWVudCA9IGBsaW5lYXItZ3JhZGllbnQoJHtkaXJlY3Rpb259LCAke2NvbG9yU3RvcHMuam9pbignLCAnKX0pYDtcclxuICAgIGNvbnN0IHN0eWxlczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSA9IHt9O1xyXG4gICAgY29uc3QgYmFyU3R5bGUgPSB0aGlzLnJ1Y0lucHV0RGF0YT8uYmFyU3R5bGU7XHJcblxyXG4gICAgc3dpdGNoIChiYXJTdHlsZSkge1xyXG4gICAgICBjYXNlICdzdHJpcGUnOlxyXG4gICAgICAgIC8vIFRoaXMgdXNlcyBtdWx0aXBsZSBiYWNrZ3JvdW5kcyBmb3IgYW4gb3ZlcmxheSBlZmZlY3QsIGFzIHJlcXVlc3RlZC5cclxuICAgICAgICBzdHlsZXNbJ2JhY2tncm91bmQnXSA9IGByZXBlYXRpbmctbGluZWFyLWdyYWRpZW50KC00NWRlZywgdHJhbnNwYXJlbnQsIHRyYW5zcGFyZW50IDVweCwgcmdiYSgwLCAwLCAwLCAwLjEpIDVweCwgcmdiYSgwLCAwLCAwLCAwLjEpIDEwcHgpLCAke2Jhc2VHcmFkaWVudH1gO1xyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICBjYXNlICdjaXJjbGUnOiB7XHJcbiAgICAgICAgLy8gVGhpcyB1c2VzIGEgbWFzay4gVGhlIGJhY2tncm91bmQgaXMgdGhlIGNvbG9yLCB0aGUgbWFzayBjdXRzIG91dCB0aGUgc2hhcGUuXHJcbiAgICAgICAgc3R5bGVzWydiYWNrZ3JvdW5kJ10gPSBiYXNlR3JhZGllbnQ7XHJcbiAgICAgICAgLy8gQSByZXBlYXRpbmcgcGF0dGVybiBvZiBjaXJjbGVzLiBFYWNoIGNpcmNsZSBoYXMgYSBkaWFtZXRlciBvZiA4cHgsIHdpdGggYSA0cHggZ2FwLlxyXG4gICAgICAgIGNvbnN0IGNpcmNsZU1hc2sgPSAncmFkaWFsLWdyYWRpZW50KGNpcmNsZSwgYmxhY2sgNHB4LCB0cmFuc3BhcmVudCA0cHgpIDAgMCAvIDEycHggMTJweCc7XHJcbiAgICAgICAgc3R5bGVzWyctd2Via2l0LW1hc2snXSA9IGNpcmNsZU1hc2s7XHJcbiAgICAgICAgc3R5bGVzWydtYXNrJ10gPSBjaXJjbGVNYXNrO1xyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICB9XHJcbiAgICAgIGNhc2UgJ3JlY3RhbmdsZSc6IHtcclxuICAgICAgICBzdHlsZXNbJ2JhY2tncm91bmQnXSA9IGJhc2VHcmFkaWVudDtcclxuICAgICAgICAvLyBGb3IgdmVydGljYWwgYmFyLCBjcmVhdGUgaG9yaXpvbnRhbCByZWN0YW5nbGVzICgwZGVnKS4gRm9yIGhvcml6b250YWwgYmFyLCBjcmVhdGUgdmVydGljYWwgcmVjdGFuZ2xlcyAoOTBkZWcpLlxyXG4gICAgICAgIGNvbnN0IHJlY3REaXJlY3Rpb24gPSB0aGlzLmlzVmVydGljYWwgPyAnMGRlZycgOiAnOTBkZWcnO1xyXG4gICAgICAgIC8vIEEgcmVwZWF0aW5nIHBhdHRlcm4gb2YgYmFycy4gRWFjaCBiYXIgaXMgNnB4IHdpZGUgd2l0aCBhIDZweCBnYXAuXHJcbiAgICAgICAgY29uc3QgcmVjdGFuZ2xlTWFzayA9IGByZXBlYXRpbmctbGluZWFyLWdyYWRpZW50KCR7cmVjdERpcmVjdGlvbn0sIGJsYWNrLCBibGFjayA2cHgsIHRyYW5zcGFyZW50IDZweCwgdHJhbnNwYXJlbnQgMTJweClgO1xyXG4gICAgICAgIHN0eWxlc1snLXdlYmtpdC1tYXNrJ10gPSByZWN0YW5nbGVNYXNrO1xyXG4gICAgICAgIHN0eWxlc1snbWFzayddID0gcmVjdGFuZ2xlTWFzaztcclxuICAgICAgICBicmVhaztcclxuICAgICAgfVxyXG4gICAgICBkZWZhdWx0OiAvLyAnc29saWQnIG9yIHVuZGVmaW5lZFxyXG4gICAgICAgIHN0eWxlc1snYmFja2dyb3VuZCddID0gYmFzZUdyYWRpZW50O1xyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHN0eWxlcztcclxuICB9XHJcbiAgLyoqXHJcbiAgICogSGFuZGxlcyBtb3VzZSBtb3ZlbWVudCBvdmVyIHRoZSBwcm9ncmVzcyBiYXIgdG8gZGlzcGxheSBjYXRlZ29yeS1zcGVjaWZpYyBob3ZlciBkZXRhaWxzLlxyXG4gICAqIEl0IGNhbGN1bGF0ZXMgdGhlIGhvdmVyZWQgc2VnbWVudCBiYXNlZCBvbiBtb3VzZSBwb3NpdGlvbiBhbmQgdXBkYXRlcyB0aGUgaG92ZXIgbGFiZWwuXHJcbiAgICogQHBhcmFtIGV2ZW50IFRoZSBNb3VzZUV2ZW50IG9iamVjdC5cclxuICAgKi9cclxuICBvblByb2dyZXNzTW91c2VNb3ZlKGV2ZW50OiBNb3VzZUV2ZW50KTogdm9pZCB7XHJcbiAgICBjb25zdCBwcm9ncmVzc0JhckVsZW1lbnQgPSBldmVudC50YXJnZXQgYXMgSFRNTEVsZW1lbnQ7XHJcbiAgICBsZXQgY3VycmVudEN1bXVsYXRpdmVHcmFkaWVudFBjdCA9IDA7XHJcbiAgICBsZXQgZm91bmRDYXRlZ29yeUZvckhvdmVyOiBDYXRlZ29yeUNvbmZpZyB8IG51bGwgPSBudWxsO1xyXG4gICAgbGV0IGhvdmVyUGVyY2VudGFnZV9vbkZpbGxlZEJhciA9IDA7XHJcbiAgICBsZXQgbW91c2VQb3NpdGlvbldpdGhpblByb2dyZXNzRGl2ID0gMDtcclxuXHJcbiAgICBpZiAodGhpcy5pc1ZlcnRpY2FsKSB7XHJcbiAgICAgIG1vdXNlUG9zaXRpb25XaXRoaW5Qcm9ncmVzc0RpdiA9IGV2ZW50Lm9mZnNldFk7IC8vIFkgcG9zaXRpb24gd2l0aGluIHRoZSAucHJvZ3Jlc3MgZGl2XHJcbiAgICAgIGNvbnN0IGZpbGxlZEhlaWdodFB4ID0gcHJvZ3Jlc3NCYXJFbGVtZW50Lm9mZnNldEhlaWdodDtcclxuICAgICAgaWYgKGZpbGxlZEhlaWdodFB4IDw9IDApIHsgLy8gQXZvaWQgZGl2aXNpb24gYnkgemVybyBpZiBlbGVtZW50IGhhcyBubyBoZWlnaHRcclxuICAgICAgICB0aGlzLm9uUHJvZ3Jlc3NNb3VzZUxlYXZlKCk7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcbiAgICAgIGhvdmVyUGVyY2VudGFnZV9vbkZpbGxlZEJhciA9IChtb3VzZVBvc2l0aW9uV2l0aGluUHJvZ3Jlc3NEaXYgLyBmaWxsZWRIZWlnaHRQeCkgKiAxMDA7XHJcbiAgICB9IGVsc2UgeyAvLyBIb3Jpem9udGFsXHJcbiAgICAgIG1vdXNlUG9zaXRpb25XaXRoaW5Qcm9ncmVzc0RpdiA9IGV2ZW50Lm9mZnNldFg7IC8vIFggcG9zaXRpb24gd2l0aGluIHRoZSAucHJvZ3Jlc3MgZGl2XHJcbiAgICAgIGNvbnN0IGZpbGxlZFdpZHRoUHggPSBwcm9ncmVzc0JhckVsZW1lbnQub2Zmc2V0V2lkdGg7XHJcbiAgICAgIGlmIChmaWxsZWRXaWR0aFB4IDw9IDApIHsgLy8gQXZvaWQgZGl2aXNpb24gYnkgemVybyBpZiBlbGVtZW50IGhhcyBubyB3aWR0aFxyXG4gICAgICAgIHRoaXMub25Qcm9ncmVzc01vdXNlTGVhdmUoKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuICAgICAgaG92ZXJQZXJjZW50YWdlX29uRmlsbGVkQmFyID0gKG1vdXNlUG9zaXRpb25XaXRoaW5Qcm9ncmVzc0RpdiAvIGZpbGxlZFdpZHRoUHgpICogMTAwO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLnRvdGFsVmFsdWUgPiAwKSB7XHJcbiAgICAgIGZvciAoY29uc3QgY2F0ZWdvcnkgb2YgdGhpcy5ydWNJbnB1dERhdGEuY2F0ZWdvcmllcykge1xyXG4gICAgICAgIGlmIChjYXRlZ29yeS52YWx1ZSA8PSAwKSBjb250aW51ZTsgLy8gU2tpcCBjYXRlZ29yaWVzIHdpdGggemVybyBvciBuZWdhdGl2ZSBjb250cmlidXRpb25cclxuXHJcbiAgICAgICAgY29uc3Qgc2VnbWVudEdyYWRpZW50UGN0ID0gKGNhdGVnb3J5LnZhbHVlIC8gdGhpcy50b3RhbFZhbHVlKSAqIDEwMDtcclxuICAgICAgICBjb25zdCBzZWdtZW50U3RhcnRHcmFkaWVudFBjdCA9IGN1cnJlbnRDdW11bGF0aXZlR3JhZGllbnRQY3Q7XHJcbiAgICAgICAgY29uc3Qgc2VnbWVudEVuZEdyYWRpZW50UGN0ID0gY3VycmVudEN1bXVsYXRpdmVHcmFkaWVudFBjdCArIHNlZ21lbnRHcmFkaWVudFBjdDtcclxuXHJcbiAgICAgICAgLy8gRW5zdXJlIGhvdmVyUGVyY2VudGFnZSBpcyB3aXRoaW4gdGhlIHNlZ21lbnQsIGhhbmRsaW5nIHBvdGVudGlhbCBmbG9hdGluZyBwb2ludCBpbmFjY3VyYWNpZXMgZm9yIHRoZSBsYXN0IHNlZ21lbnRcclxuICAgICAgICBpZiAoaG92ZXJQZXJjZW50YWdlX29uRmlsbGVkQmFyID49IHNlZ21lbnRTdGFydEdyYWRpZW50UGN0ICYmIC8vIENoZWNrIGlmIG1vdXNlIGlzIHdpdGhpbiBvciBhdCB0aGUgc3RhcnQgb2YgdGhlIHNlZ21lbnRcclxuICAgICAgICAgIChob3ZlclBlcmNlbnRhZ2Vfb25GaWxsZWRCYXIgPCBzZWdtZW50RW5kR3JhZGllbnRQY3QgfHxcclxuICAgICAgICAgICAgKHNlZ21lbnRFbmRHcmFkaWVudFBjdCA+PSA5OS45OSAmJiBob3ZlclBlcmNlbnRhZ2Vfb25GaWxsZWRCYXIgPD0gMTAwLjAxKSkpIHsgLy8gVG9sZXJhdGUgc2xpZ2h0IG92ZXJzaG9vdCBmb3IgbGFzdCBzZWdtZW50XHJcbiAgICAgICAgICBmb3VuZENhdGVnb3J5Rm9ySG92ZXIgPSBjYXRlZ29yeTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIH1cclxuICAgICAgICBjdXJyZW50Q3VtdWxhdGl2ZUdyYWRpZW50UGN0ID0gc2VnbWVudEVuZEdyYWRpZW50UGN0O1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGZvdW5kQ2F0ZWdvcnlGb3JIb3Zlcikge1xyXG4gICAgICBjb25zdCBwZXJjZW50YWdlT2ZNYXggPSAoZm91bmRDYXRlZ29yeUZvckhvdmVyLnZhbHVlIC8gdGhpcy5ydWNJbnB1dERhdGEubWF4KSAqIDEwMDsgLy8gQ2FsY3VsYXRlIHBlcmNlbnRhZ2UgcmVsYXRpdmUgdG8gbWF4IHZhbHVlXHJcbiAgICAgIHRoaXMuaG92ZXJlZENhdGVnb3J5RGV0YWlsID0geyBjYXRlZ29yeTogZm91bmRDYXRlZ29yeUZvckhvdmVyLCBwZXJjZW50YWdlVGV4dDogcGVyY2VudGFnZU9mTWF4LnRvRml4ZWQoMCkgKyAnJScgfTtcclxuICAgICAgaWYgKHRoaXMuaXNWZXJ0aWNhbCkge1xyXG4gICAgICAgIHRoaXMuaG92ZXJMYWJlbFN0eWxlID0ge1xyXG4gICAgICAgICAgbGVmdDogJ2NhbGMoMTAwJSArIDVweCknLCAvLyBQb3NpdGlvbiB0byB0aGUgcmlnaHQgb2YgdGhlIHZlcnRpY2FsIGJhclxyXG4gICAgICAgICAgdG9wOiBtb3VzZVBvc2l0aW9uV2l0aGluUHJvZ3Jlc3NEaXYgKyAncHgnLFxyXG4gICAgICAgICAgZGlzcGxheTogJ2Jsb2NrJyxcclxuICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZVkoLTUwJSknIC8vIFZlcnRpY2FsbHkgY2VudGVyIGxhYmVsIG9uIG1vdXNlIFlcclxuICAgICAgICB9O1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMuaG92ZXJMYWJlbFN0eWxlID0ge1xyXG4gICAgICAgICAgbGVmdDogbW91c2VQb3NpdGlvbldpdGhpblByb2dyZXNzRGl2ICsgJ3B4JyxcclxuICAgICAgICAgIHRvcDogJy0yOHB4JywgLy8gUG9zaXRpb24gYWJvdmUgaG9yaXpvbnRhbCBiYXJcclxuICAgICAgICAgIGRpc3BsYXk6ICdibG9jaycsXHJcbiAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGVYKC01MCUpJyAvLyBIb3Jpem9udGFsbHkgY2VudGVyIGxhYmVsIG9uIG1vdXNlIFhcclxuICAgICAgICB9O1xyXG4gICAgICB9XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLmhvdmVyZWRDYXRlZ29yeURldGFpbCA9IG51bGw7XHJcbiAgICAgIHRoaXMuaG92ZXJMYWJlbFN0eWxlID0geyAuLi50aGlzLmhvdmVyTGFiZWxTdHlsZSwgZGlzcGxheTogJ25vbmUnIH07XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBIaWRlcyB0aGUgaG92ZXIgbGFiZWwgd2hlbiB0aGUgbW91c2UgbGVhdmVzIHRoZSBwcm9ncmVzcyBiYXIuXHJcbiAgICovXHJcbiAgb25Qcm9ncmVzc01vdXNlTGVhdmUoKTogdm9pZCB7XHJcbiAgICB0aGlzLmhvdmVyZWRDYXRlZ29yeURldGFpbCA9IG51bGw7XHJcbiAgICB0aGlzLmhvdmVyTGFiZWxTdHlsZSA9IHsgLi4udGhpcy5ob3ZlckxhYmVsU3R5bGUsIGRpc3BsYXk6ICdub25lJyB9O1xyXG4gIH1cclxuICAvKipcclxuICAgKiBnZXQgdGhlIGxhYmVsIHBvc2l0aW9uICBzdHJpbmcgdmFsdWVcclxuICAgICAqL1xyXG4gIHB1YmxpYyBnZXQgTGFibGVQb3NpdGlvbkVudW1zKCk6IHR5cGVvZiBMYWJsZVBvc2l0aW9uRW51bXMge1xyXG4gICAgcmV0dXJuIExhYmxlUG9zaXRpb25FbnVtcztcclxuICB9XHJcbn1cclxuIiwiPGRpdiBjbGFzcz1cInByb2dyZXNzLWNvbnRhaW5lclwiIGNsYXNzPXt7Y3VzdG9tVGhlbWV9fSBbY2xhc3MudmVydGljYWxdPVwiaXNWZXJ0aWNhbFwiIFtjbGFzcy5ob3Jpem9udGFsXT1cIiFpc1ZlcnRpY2FsXCI+XHJcbiAgPGRpdiBjbGFzcz1cInByb2dyZXNzLWJhclwiPlxyXG4gICAgPCEtLSBSZW1vdmVkIChtb3VzZWVudGVyKSBhbmQgKG1vdXNlbGVhdmUpIGZyb20gcHJvZ3Jlc3MtYmFyIGlmIG9ubHkgY2F0ZWdvcnkgaG92ZXIgaXMgbmVlZGVkIC0tPlxyXG4gICAgPGRpdiAqbmdJZj1cInJ1Y0lucHV0RGF0YS5iYXJMYWJlbHNcIiBjbGFzcz1cInByb2dyZXNzLWxhYmVsLWNvbnRhaW5lciB7e3J1Y0lucHV0RGF0YS5vcmllbnRhdGlvbn19XCI+XHJcbiAgICAgIDxzcGFuIGNsYXNzPVwicHJvZ3Jlc3MtbGFiZWxcIj57e3Byb2dyZXNzIHwgbnVtYmVyOicxLjAtMCd9fSUgb2Yge3tydWNJbnB1dERhdGEubWF4fX0ge3tydWNJbnB1dERhdGEudW5pdFR5cGV9fVxyXG4gICAgICAgIFVzZWQ8L3NwYW4+XHJcbiAgICA8L2Rpdj5cclxuICAgIDxkaXYgY2xhc3M9XCJwcm9ncmVzc1wiIFtzdHlsZS53aWR0aF09XCJpc1ZlcnRpY2FsID8gJzEwMCUnIDogcHJvZ3Jlc3MgKyAnJSdcIlxyXG4gICAgICBbc3R5bGUuaGVpZ2h0XT1cImlzVmVydGljYWwgPyBwcm9ncmVzcyArICclJyA6ICcxMDAlJ1wiXHJcbiAgICAgIFtzdHlsZS50cmFuc2l0aW9uXT1cInJ1Y0lucHV0RGF0YS5vcmllbnRhdGlvbiA9PT0gJ3ZlcnRpY2FsJyA/ICdoZWlnaHQgMC4zcyBlYXNlJyA6ICd3aWR0aCAwLjNzIGVhc2UnXCJcclxuICAgICAgW25nU3R5bGVdPVwicHJvZ3Jlc3NTdHlsZXNcIj5cclxuICAgICAgPCEtLSBUaGlzIGRpdiBpcyBub3cgb25seSBmb3IgZGlzcGxheWluZyB0aGUgY29sb3JlZCBiYXIgLS0+XHJcbiAgICA8L2Rpdj5cclxuICAgIDwhLS0gVGhlIGhvdmVyIGxhYmVsIGlzIG5vdyBhIHNpYmxpbmcgdG8gLnByb2dyZXNzLCBwb3NpdGlvbmVkIGFic29sdXRlbHkgd2l0aGluIC5wcm9ncmVzcy1iYXIgLS0+XHJcbiAgICA8ZGl2IGNsYXNzPVwiaG92ZXItbGFiZWxcIiAqbmdJZj1cImhvdmVyZWRDYXRlZ29yeURldGFpbFwiIFtuZ1N0eWxlXT1cImhvdmVyTGFiZWxTdHlsZVwiPlxyXG4gICAgICB7e2hvdmVyZWRDYXRlZ29yeURldGFpbC5jYXRlZ29yeS5sYWJlbH19OiB7e2hvdmVyZWRDYXRlZ29yeURldGFpbC5wZXJjZW50YWdlVGV4dH19XHJcbiAgICA8L2Rpdj5cclxuICAgIDwhLS0gVGhpcyBvdmVybGF5IGlzIG5vdyBhIHNpYmxpbmcgdG8gLnByb2dyZXNzLCBzaXplZCB0byBtYXRjaCBpdCwgdG8gcmVsaWFibHkgY2FwdHVyZSBtb3VzZSBldmVudHMgLS0+XHJcbiAgICA8ZGl2IGNsYXNzPVwicHJvZ3Jlc3MtZXZlbnQtb3ZlcmxheVwiIFtzdHlsZS53aWR0aF09XCJpc1ZlcnRpY2FsID8gJzEwMCUnIDogcHJvZ3Jlc3MgKyAnJSdcIlxyXG4gICAgICBbc3R5bGUuaGVpZ2h0XT1cImlzVmVydGljYWwgPyBwcm9ncmVzcyArICclJyA6ICcxMDAlJ1wiIChtb3VzZW1vdmUpPVwib25Qcm9ncmVzc01vdXNlTW92ZSgkZXZlbnQpXCJcclxuICAgICAgKG1vdXNlbGVhdmUpPVwib25Qcm9ncmVzc01vdXNlTGVhdmUoKVwiPjwvZGl2PlxyXG4gIDwvZGl2PlxyXG4gIDxkaXYgY2xhc3M9XCJjYXRlZ29yaWVzLWNvbnRhaW5lclwiICpuZ0lmPVwicnVjSW5wdXREYXRhLmNhdGVnb3JpZXMubGVuZ3RoID4gMFwiPlxyXG4gICAgPGRpdiAqbmdJZj1cInJ1Y0lucHV0RGF0YS5zaG93Q2F0ZWdvcnlMYWJlbHMgJiYgcnVjSW5wdXREYXRhLmNhdGVnb3J5TGFiZWxTdHlsZSA9PT0gJ2Jhc2ljJ1wiIFtuZ0NsYXNzXT1cIntcclxuICAgICAgICAgICAnY2F0ZWdvcmllcy1ibG9jay10b3AnOiAgICAhaXNWZXJ0aWNhbCAmJiAocnVjSW5wdXREYXRhLmNhdGVnb3J5TGFiZWxzT3JpZW50YXRpb24gPT09ICd0b3AnIHx8IHJ1Y0lucHV0RGF0YS5jYXRlZ29yeUxhYmVsc09yaWVudGF0aW9uID09PSAnc2FtZScpLFxyXG4gICAgICAgICAgICdjYXRlZ29yaWVzLWJsb2NrLWxlZnQnOiAgIGlzVmVydGljYWwgJiYgKHJ1Y0lucHV0RGF0YS5jYXRlZ29yeUxhYmVsc09yaWVudGF0aW9uID09PSAnbGVmdCcgfHwgcnVjSW5wdXREYXRhLmNhdGVnb3J5TGFiZWxzT3JpZW50YXRpb24gPT09ICdzYW1lJyksXHJcbiAgICAgICAgICAgJ2NhdGVnb3JpZXMtYmxvY2stcmlnaHQnOiAgaXNWZXJ0aWNhbCAmJiAhKHJ1Y0lucHV0RGF0YS5jYXRlZ29yeUxhYmVsc09yaWVudGF0aW9uID09PSAnbGVmdCcgfHwgcnVjSW5wdXREYXRhLmNhdGVnb3J5TGFiZWxzT3JpZW50YXRpb24gPT09ICdzYW1lJylcclxuICAgICAgICAgfVwiIGNsYXNzPVwiY2F0ZWdvcmllc1wiPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwiY2F0ZWdvcnlcIiAqbmdGb3I9XCJsZXQgY2F0ZWdvcnkgb2YgcnVjSW5wdXREYXRhLmNhdGVnb3JpZXNcIiBbc3R5bGUuY29sb3JdPVwiY2F0ZWdvcnkuY29sb3JcIj5cclxuICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiY2F0ZWdvcnkuaWNvbiAhPT0gdW5kZWZpbmVkXCI+XHJcbiAgICAgICAgICA8ZGl2ICpuZ0lmPVwiY2F0ZWdvcnkuaWNvbjsgZWxzZSBjb2xvckRvdEJhc2ljXCIgY2xhc3M9XCJjYXRlZ29yeS1pY29uLXdyYXBwZXJcIj5cclxuICAgICAgICAgICAgPGkgY2xhc3M9XCJtYXRlcmlhbC1pY29uc1wiIFtzdHlsZS5jb2xvcl09XCJjYXRlZ29yeS5jb2xvclwiPnt7IGNhdGVnb3J5Lmljb24gfX08L2k+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjY29sb3JEb3RCYXNpYz5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNhdGVnb3J5LWNvbG9yXCI+XHJcbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvbG9yLWdyYWRpZW50XCJcclxuICAgICAgICAgICAgICAgIFtzdHlsZS5iYWNrZ3JvdW5kXT1cImNhdGVnb3J5LmNvbG9yID8gJ2xpbmVhci1ncmFkaWVudCh0byByaWdodCwgJyArIGNhdGVnb3J5LmNvbG9yICsgJywgJyArIGNhdGVnb3J5LmNvbG9yICsgJyknIDogJydcIj5cclxuICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxyXG4gICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgIDxzcGFuIGNsYXNzPVwiY2F0ZWdvcnktbGFiZWxcIj57e2NhdGVnb3J5LmxhYmVsfX08L3NwYW4+XHJcbiAgICAgICAgPHNwYW4gY2xhc3M9XCJjYXRlZ29yeS12YWx1ZVwiPih7eyhjYXRlZ29yeS52YWx1ZSAvIHJ1Y0lucHV0RGF0YS5tYXggKiAxMDApIHwgbnVtYmVyOicxLjAtMCcgfX0lKTwvc3Bhbj5cclxuICAgICAgPC9kaXY+XHJcbiAgICA8L2Rpdj5cclxuXHJcbiAgICA8ZGl2ICpuZ0lmPVwicnVjSW5wdXREYXRhLnNob3dDYXRlZ29yeUxhYmVscyAmJiBydWNJbnB1dERhdGEuY2F0ZWdvcnlMYWJlbFN0eWxlID09PSAnd2lkZ2V0J1wiXHJcbiAgICAgIGNsYXNzPVwiY2F0ZWdvcmllcyB3aWRnZXQtc3R5bGVcIiBbbmdDbGFzc109XCJ7XHJcbiAgICAgICAgICAgJ2NhdGVnb3JpZXMtYmxvY2stdG9wJzogICAgIWlzVmVydGljYWwgJiYgKHJ1Y0lucHV0RGF0YS5jYXRlZ29yeUxhYmVsc09yaWVudGF0aW9uID09PSBMYWJsZVBvc2l0aW9uRW51bXMudG9wIHx8IHJ1Y0lucHV0RGF0YS5jYXRlZ29yeUxhYmVsc09yaWVudGF0aW9uID09PSBMYWJsZVBvc2l0aW9uRW51bXMuc2FtZSksXHJcbiAgICAgICAgICAgJ2NhdGVnb3JpZXMtYmxvY2stbGVmdCc6ICAgaXNWZXJ0aWNhbCAmJiAocnVjSW5wdXREYXRhLmNhdGVnb3J5TGFiZWxzT3JpZW50YXRpb24gPT09IExhYmxlUG9zaXRpb25FbnVtcy5sZWZ0IHx8IHJ1Y0lucHV0RGF0YS5jYXRlZ29yeUxhYmVsc09yaWVudGF0aW9uID09PSBMYWJsZVBvc2l0aW9uRW51bXMuc2FtZSksXHJcbiAgICAgICAgICAgJ2NhdGVnb3JpZXMtYmxvY2stcmlnaHQnOiAgaXNWZXJ0aWNhbCAmJiAhKHJ1Y0lucHV0RGF0YS5jYXRlZ29yeUxhYmVsc09yaWVudGF0aW9uID09PSBMYWJsZVBvc2l0aW9uRW51bXMubGVmdCB8fCBydWNJbnB1dERhdGEuY2F0ZWdvcnlMYWJlbHNPcmllbnRhdGlvbiA9PT0gTGFibGVQb3NpdGlvbkVudW1zLnNhbWUpXHJcbiAgICAgICAgIH1cIj5cclxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgY2F0ZWdvcnkgb2YgcnVjSW5wdXREYXRhLmNhdGVnb3JpZXNcIj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwid2lkZ2V0LWNhdGVnb3J5XCI+XHJcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwid2lkZ2V0LWNvbnRlbnRcIj5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIndpZGdldC1pY29uLWJveFwiPlxyXG4gICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJjYXRlZ29yeS5pY29uICE9PSB1bmRlZmluZWRcIj5cclxuICAgICAgICAgICAgICAgIDxkaXYgKm5nSWY9XCJjYXRlZ29yeS5pY29uOyBlbHNlIGNvbG9yRG90V2lkZ2V0XCIgY2xhc3M9XCJ3aWRnZXQtaWNvblwiPlxyXG4gICAgICAgICAgICAgICAgICA8aSBjbGFzcz1cIm1hdGVyaWFsLWljb25zXCIgW3N0eWxlLmNvbG9yXT1cImNhdGVnb3J5LmNvbG9yXCI+e3sgY2F0ZWdvcnkuaWNvbiB9fTwvaT5cclxuICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlICNjb2xvckRvdFdpZGdldD5cclxuICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNhdGVnb3J5LWNvbG9yXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvbG9yLWdyYWRpZW50XCJcclxuICAgICAgICAgICAgICAgICAgICAgIFtzdHlsZS5iYWNrZ3JvdW5kXT1cImNhdGVnb3J5LmNvbG9yID8gJ2xpbmVhci1ncmFkaWVudCh0byByaWdodCwgJyArIGNhdGVnb3J5LmNvbG9yICsgJywgJyArIGNhdGVnb3J5LmNvbG9yICsgJyknIDogJydcIj5cclxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxyXG4gICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ3aWRnZXQtbGFiZWxcIj57e2NhdGVnb3J5LmxhYmVsfX08L2Rpdj5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJ3aWRnZXQtdmFsdWVcIj5cclxuICAgICAgICAgICAgPGRpdj57e2NhdGVnb3J5LnZhbHVlfX08L2Rpdj5cclxuICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG5cclxuXHJcbiAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgPC9kaXY+XHJcblxyXG4gIDwvZGl2PlxyXG48L2Rpdj4iXX0=
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { NgModule } from '@angular/core';
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
3
|
+
import { MatIconModule } from '@angular/material/icon';
|
|
4
|
+
import { RucMeteredProgressBarComponent } from './ruc-metered-progress-bar/ruc-metered-progress-bar.component';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
// import { RucMeteredProgressBarComponent } from './ruc-metered-progress-bar/ruc-metered-progress-bar/ruc-metered-progress-bar.component';
|
|
7
|
+
export class RuclibMeteredProgressBarModule {
|
|
8
|
+
}
|
|
9
|
+
RuclibMeteredProgressBarModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RuclibMeteredProgressBarModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
10
|
+
RuclibMeteredProgressBarModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: RuclibMeteredProgressBarModule, declarations: [RucMeteredProgressBarComponent], imports: [CommonModule, MatIconModule], exports: [RucMeteredProgressBarComponent] });
|
|
11
|
+
RuclibMeteredProgressBarModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RuclibMeteredProgressBarModule, imports: [CommonModule, MatIconModule] });
|
|
12
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RuclibMeteredProgressBarModule, decorators: [{
|
|
13
|
+
type: NgModule,
|
|
14
|
+
args: [{
|
|
15
|
+
imports: [CommonModule, MatIconModule],
|
|
16
|
+
declarations: [RucMeteredProgressBarComponent],
|
|
17
|
+
exports: [RucMeteredProgressBarComponent],
|
|
18
|
+
}]
|
|
19
|
+
}] });
|
|
20
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVjbGliLW1ldGVyZWQtcHJvZ3Jlc3MtYmFyLm1vZHVsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvcnVjbGliLW1ldGVyZWQtcHJvZ3Jlc3MtYmFyLm1vZHVsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDdkQsT0FBTyxFQUFFLDhCQUE4QixFQUFFLE1BQU0sK0RBQStELENBQUM7O0FBQy9HLDJJQUEySTtBQU8zSSxNQUFNLE9BQU8sOEJBQThCOzs0SEFBOUIsOEJBQThCOzZIQUE5Qiw4QkFBOEIsaUJBSDFCLDhCQUE4QixhQURuQyxZQUFZLEVBQUMsYUFBYSxhQUUxQiw4QkFBOEI7NkhBRTdCLDhCQUE4QixZQUovQixZQUFZLEVBQUMsYUFBYTs0RkFJekIsOEJBQThCO2tCQUwxQyxRQUFRO21CQUFDO29CQUNSLE9BQU8sRUFBRSxDQUFDLFlBQVksRUFBQyxhQUFhLENBQUM7b0JBQ3JDLFlBQVksRUFBRSxDQUFDLDhCQUE4QixDQUFDO29CQUM5QyxPQUFPLEVBQUUsQ0FBQyw4QkFBOEIsQ0FBQztpQkFDMUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBOZ01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xyXG5pbXBvcnQgeyBNYXRJY29uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvaWNvbic7XHJcbmltcG9ydCB7IFJ1Y01ldGVyZWRQcm9ncmVzc0JhckNvbXBvbmVudCB9IGZyb20gJy4vcnVjLW1ldGVyZWQtcHJvZ3Jlc3MtYmFyL3J1Yy1tZXRlcmVkLXByb2dyZXNzLWJhci5jb21wb25lbnQnO1xyXG4vLyBpbXBvcnQgeyBSdWNNZXRlcmVkUHJvZ3Jlc3NCYXJDb21wb25lbnQgfSBmcm9tICcuL3J1Yy1tZXRlcmVkLXByb2dyZXNzLWJhci9ydWMtbWV0ZXJlZC1wcm9ncmVzcy1iYXIvcnVjLW1ldGVyZWQtcHJvZ3Jlc3MtYmFyLmNvbXBvbmVudCc7XHJcblxyXG5ATmdNb2R1bGUoe1xyXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGUsTWF0SWNvbk1vZHVsZV0sXHJcbiAgZGVjbGFyYXRpb25zOiBbUnVjTWV0ZXJlZFByb2dyZXNzQmFyQ29tcG9uZW50XSxcclxuICBleHBvcnRzOiBbUnVjTWV0ZXJlZFByb2dyZXNzQmFyQ29tcG9uZW50XSxcclxufSlcclxuZXhwb3J0IGNsYXNzIFJ1Y2xpYk1ldGVyZWRQcm9ncmVzc0Jhck1vZHVsZSB7fVxyXG4iXX0=
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generated bundle index. Do not edit.
|
|
3
|
+
*/
|
|
4
|
+
export * from './index';
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVjLWxpYi1tZXRlcmVkUHJvZ3Jlc3NCYXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcnVjLWxpYi1tZXRlcmVkUHJvZ3Jlc3NCYXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxjQUFjLFNBQVMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogR2VuZXJhdGVkIGJ1bmRsZSBpbmRleC4gRG8gbm90IGVkaXQuXG4gKi9cblxuZXhwb3J0ICogZnJvbSAnLi9pbmRleCc7XG4iXX0=
|