ng-hub-ui-metrics 22.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/LICENSE +21 -0
- package/README.md +198 -0
- package/fesm2022/ng-hub-ui-metrics.mjs +283 -0
- package/fesm2022/ng-hub-ui-metrics.mjs.map +1 -0
- package/ng-hub-ui-metrics-22.0.0.tgz +0 -0
- package/package.json +47 -0
- package/src/lib/styles/_index.scss +11 -0
- package/src/lib/styles/mixins/_metrics-theme.scss +57 -0
- package/types/ng-hub-ui-metrics.d.ts +212 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Carlos Morcillo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# ng-hub-ui-metrics
|
|
2
|
+
|
|
3
|
+
[Español](./README.es.md) | **English**
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/ng-hub-ui-metrics)
|
|
6
|
+
[](https://angular.dev)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
9
|
+
Read-only value visualizations for Angular 21+ — a linear **progress** bar, a graded **meter** gauge and a circular **ring** (gauge) — bundled into a single standalone, signal-driven library. Zero external dependencies; every colour and dimension is a `--hub-*` CSS custom property derived from the shared design-system tokens.
|
|
10
|
+
|
|
11
|
+
## Documentation and Live Examples
|
|
12
|
+
|
|
13
|
+
This package is part of [Hub UI](https://hubui.dev/), a collection of Angular component libraries for standalone apps.
|
|
14
|
+
|
|
15
|
+
- Docs: https://hubui.dev/metrics/overview/
|
|
16
|
+
- Live examples: https://hubui.dev/metrics/examples/
|
|
17
|
+
- Hub UI: https://hubui.dev/
|
|
18
|
+
|
|
19
|
+
## 🧩 Library Family `ng-hub-ui`
|
|
20
|
+
|
|
21
|
+
This library is part of the **ng-hub-ui** ecosystem:
|
|
22
|
+
|
|
23
|
+
- [**ng-hub-ui-action-sheet**](https://www.npmjs.com/package/ng-hub-ui-action-sheet)
|
|
24
|
+
- [**ng-hub-ui-avatar**](https://www.npmjs.com/package/ng-hub-ui-avatar)
|
|
25
|
+
- [**ng-hub-ui-badges**](https://www.npmjs.com/package/ng-hub-ui-badges)
|
|
26
|
+
- [**ng-hub-ui-board**](https://www.npmjs.com/package/ng-hub-ui-board)
|
|
27
|
+
- [**ng-hub-ui-breadcrumbs**](https://www.npmjs.com/package/ng-hub-ui-breadcrumbs)
|
|
28
|
+
- [**ng-hub-ui-buttons**](https://www.npmjs.com/package/ng-hub-ui-buttons)
|
|
29
|
+
- [**ng-hub-ui-calendar**](https://www.npmjs.com/package/ng-hub-ui-calendar)
|
|
30
|
+
- [**ng-hub-ui-forms**](https://www.npmjs.com/package/ng-hub-ui-forms)
|
|
31
|
+
- [**ng-hub-ui-history**](https://www.npmjs.com/package/ng-hub-ui-history)
|
|
32
|
+
- [**ng-hub-ui-metrics**](https://www.npmjs.com/package/ng-hub-ui-metrics) ← You are here
|
|
33
|
+
- [**ng-hub-ui-milestones**](https://www.npmjs.com/package/ng-hub-ui-milestones)
|
|
34
|
+
- [**ng-hub-ui-modal**](https://www.npmjs.com/package/ng-hub-ui-modal)
|
|
35
|
+
- [**ng-hub-ui-nav**](https://www.npmjs.com/package/ng-hub-ui-nav)
|
|
36
|
+
- [**ng-hub-ui-paginable**](https://www.npmjs.com/package/ng-hub-ui-paginable)
|
|
37
|
+
- [**ng-hub-ui-panels**](https://www.npmjs.com/package/ng-hub-ui-panels)
|
|
38
|
+
- [**ng-hub-ui-portal**](https://www.npmjs.com/package/ng-hub-ui-portal)
|
|
39
|
+
- [**ng-hub-ui-skeleton**](https://www.npmjs.com/package/ng-hub-ui-skeleton)
|
|
40
|
+
- [**ng-hub-ui-sortable**](https://www.npmjs.com/package/ng-hub-ui-sortable)
|
|
41
|
+
- [**ng-hub-ui-stepper**](https://www.npmjs.com/package/ng-hub-ui-stepper)
|
|
42
|
+
- [**ng-hub-ui-toast**](https://www.npmjs.com/package/ng-hub-ui-toast)
|
|
43
|
+
- [**ng-hub-ui-utils**](https://www.npmjs.com/package/ng-hub-ui-utils)
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 🚀 Quick Start
|
|
48
|
+
|
|
49
|
+
### 1. Install
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
npm install ng-hub-ui-metrics
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
> **Theming (recommended):** install the shared design tokens so the metrics —
|
|
56
|
+
> and every other ng-hub-ui library — read the same palette and dark-mode colours:
|
|
57
|
+
>
|
|
58
|
+
> ```bash
|
|
59
|
+
> npm install ng-hub-ui-ds
|
|
60
|
+
> ```
|
|
61
|
+
>
|
|
62
|
+
> ```css
|
|
63
|
+
> @import 'ng-hub-ui-ds/styles/tokens/hub-tokens.css';
|
|
64
|
+
> ```
|
|
65
|
+
>
|
|
66
|
+
> It is an **optional** peer dependency: every component ships sensible CSS
|
|
67
|
+
> fallbacks and works without it.
|
|
68
|
+
|
|
69
|
+
### 2. Import the standalone components
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
import { HubProgressComponent, HubMeterComponent, HubRingComponent } from 'ng-hub-ui-metrics';
|
|
73
|
+
|
|
74
|
+
@Component({
|
|
75
|
+
standalone: true,
|
|
76
|
+
imports: [HubProgressComponent, HubMeterComponent, HubRingComponent],
|
|
77
|
+
template: `
|
|
78
|
+
<hub-progress [value]="72" label="Upload" [showValue]="true" color="info" />
|
|
79
|
+
|
|
80
|
+
<hub-meter [value]="0.82" [low]="0.3" [high]="0.7" [optimum]="0.9" />
|
|
81
|
+
|
|
82
|
+
<hub-ring [value]="0.86" [thresholds]="{ low: 0.4, high: 0.75 }">Score</hub-ring>
|
|
83
|
+
`
|
|
84
|
+
})
|
|
85
|
+
export class DashboardComponent {}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## 📦 Description
|
|
91
|
+
|
|
92
|
+
`ng-hub-ui-metrics` closes a common gap in product dashboards: read-only value
|
|
93
|
+
visualizations that every app otherwise hand-rolls. The three primitives cover
|
|
94
|
+
the recurring shapes — a linear bar, a graded gauge and a circular ring — with a
|
|
95
|
+
consistent, token-driven look and a correct ARIA contract, so you pay the
|
|
96
|
+
ceremony once.
|
|
97
|
+
|
|
98
|
+
## 🎯 Components
|
|
99
|
+
|
|
100
|
+
### `<hub-progress>` — linear bar
|
|
101
|
+
|
|
102
|
+
A determinate or indeterminate progress bar. Host role `progressbar`.
|
|
103
|
+
|
|
104
|
+
| Input | Type | Default | Description |
|
|
105
|
+
|---|---|---|---|
|
|
106
|
+
| `value` | `number` | `0` | Current value on the `[0, max]` scale. |
|
|
107
|
+
| `max` | `number` | `100` | Upper bound of the scale. |
|
|
108
|
+
| `indeterminate` | `boolean` | `false` | Loops the bar and drops `aria-valuenow`. |
|
|
109
|
+
| `color` | `HubMetricsColor` | `'primary'` | Semantic accent (`primary`, `success`, `neutral`, …). |
|
|
110
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Bar thickness. |
|
|
111
|
+
| `showValue` | `boolean` | `false` | Render the rounded percentage. |
|
|
112
|
+
| `label` | `string` | `''` | Accessible label (`aria-label`) and leading caption. |
|
|
113
|
+
|
|
114
|
+
### `<hub-meter>` — graded gauge
|
|
115
|
+
|
|
116
|
+
A gauge following HTML `<meter>` semantics; the fill colour reflects the band
|
|
117
|
+
the value falls in. Host role `meter`.
|
|
118
|
+
|
|
119
|
+
| Input | Type | Default | Description |
|
|
120
|
+
|---|---|---|---|
|
|
121
|
+
| `value` | `number` | `0` | Current measurement. |
|
|
122
|
+
| `min` | `number` | `0` | Lower bound of the scale. |
|
|
123
|
+
| `max` | `number` | `1` | Upper bound of the scale. |
|
|
124
|
+
| `low` | `number \| undefined` | `undefined` | Upper limit of the "low" region (defaults to `min`). |
|
|
125
|
+
| `high` | `number \| undefined` | `undefined` | Lower limit of the "high" region (defaults to `max`). |
|
|
126
|
+
| `optimum` | `number \| undefined` | `undefined` | Preferred point (defaults to the midpoint). |
|
|
127
|
+
|
|
128
|
+
The computed band is exposed as `data-band` (`low` / `optimum` / `high`) and
|
|
129
|
+
maps to `--hub-meter-low-bg` / `--hub-meter-optimum-bg` / `--hub-meter-high-bg`.
|
|
130
|
+
|
|
131
|
+
### `<hub-ring>` — circular gauge (alias `hubGauge`)
|
|
132
|
+
|
|
133
|
+
A normalized score drawn as an SVG arc, with an optional centre caption
|
|
134
|
+
projected via `<ng-content>`. Host role `img`.
|
|
135
|
+
|
|
136
|
+
| Input | Type | Default | Description |
|
|
137
|
+
|---|---|---|---|
|
|
138
|
+
| `value` | `number` | `0` | Score as a `0..1` ratio or a `0..max` figure. |
|
|
139
|
+
| `max` | `number` | `1` | Value is normalized against this. |
|
|
140
|
+
| `size` | `number \| string` | `'4rem'` | Outer diameter (number → px). |
|
|
141
|
+
| `thickness` | `number \| string` | `'0.5rem'` | Stroke width (number → px). |
|
|
142
|
+
| `thresholds` | `{ low?: number; high?: number }` | `undefined` | Recolours the arc by band. |
|
|
143
|
+
| `showValue` | `boolean` | `true` | Render the rounded percentage in the centre. |
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## 🎨 Styling
|
|
148
|
+
|
|
149
|
+
Every visual detail is a `--hub-*` CSS custom property. Set them on the host,
|
|
150
|
+
on any ancestor, or in `:root`.
|
|
151
|
+
|
|
152
|
+
### `hub-progress`
|
|
153
|
+
|
|
154
|
+
| Token | Default | Description |
|
|
155
|
+
|---|---|---|
|
|
156
|
+
| `--hub-progress-track-bg` | tint of the accent | Track background. |
|
|
157
|
+
| `--hub-progress-indicator-bg` | `--hub-progress-accent` | Filled indicator colour. |
|
|
158
|
+
| `--hub-progress-height` | `0.5rem` | Bar thickness. |
|
|
159
|
+
| `--hub-progress-radius` | `50rem` | Corner radius. |
|
|
160
|
+
|
|
161
|
+
### `hub-meter`
|
|
162
|
+
|
|
163
|
+
| Token | Default | Description |
|
|
164
|
+
|---|---|---|
|
|
165
|
+
| `--hub-meter-track-bg` | subtle neutral | Track background. |
|
|
166
|
+
| `--hub-meter-low-bg` | `--hub-sys-color-danger` | "Below target" fill. |
|
|
167
|
+
| `--hub-meter-optimum-bg` | `--hub-sys-color-success` | "On target" fill. |
|
|
168
|
+
| `--hub-meter-high-bg` | `--hub-sys-color-warning` | "Above target" fill. |
|
|
169
|
+
| `--hub-meter-height` | `0.5rem` | Bar thickness. |
|
|
170
|
+
| `--hub-meter-radius` | `50rem` | Corner radius. |
|
|
171
|
+
|
|
172
|
+
### `hub-ring`
|
|
173
|
+
|
|
174
|
+
| Token | Default | Description |
|
|
175
|
+
|---|---|---|
|
|
176
|
+
| `--hub-ring-size` | `4rem` | Outer diameter. |
|
|
177
|
+
| `--hub-ring-thickness` | `0.5rem` | Stroke width. |
|
|
178
|
+
| `--hub-ring-track` | subtle neutral | Track (unfilled) stroke. |
|
|
179
|
+
| `--hub-ring-indicator` | `--hub-sys-color-primary` | Indicator stroke. |
|
|
180
|
+
| `--hub-ring-caption-color` | `--hub-sys-text-primary` | Centre caption colour. |
|
|
181
|
+
| `--hub-ring-low-color` | `--hub-sys-color-danger` | Stroke below the low threshold. |
|
|
182
|
+
| `--hub-ring-high-color` | `--hub-sys-color-success` | Stroke at/above the high threshold. |
|
|
183
|
+
|
|
184
|
+
### One-call Sass theming
|
|
185
|
+
|
|
186
|
+
```scss
|
|
187
|
+
@use 'ng-hub-ui-metrics/styles' as hub;
|
|
188
|
+
|
|
189
|
+
.app-dashboard {
|
|
190
|
+
@include hub.hub-metrics-theme($accent: var(--hub-sys-color-info), $radius: 0.25rem);
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## 📄 License
|
|
197
|
+
|
|
198
|
+
MIT © [Carlos Morcillo](https://www.carlosmorcillo.com)
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { input, booleanAttribute, computed, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Linear progress bar for a determinate or indeterminate read-only value.
|
|
6
|
+
*
|
|
7
|
+
* The component owns no hard-coded colour values: the semantic `color` input
|
|
8
|
+
* maps to the host application's `--hub-sys-color-*` token family and drives the
|
|
9
|
+
* indicator through the local `--hub-progress-accent` slot. When
|
|
10
|
+
* {@link indeterminate} is set the bar loops a looping animation and drops
|
|
11
|
+
* `aria-valuenow`, matching the ARIA `progressbar` contract for an unknown value.
|
|
12
|
+
*/
|
|
13
|
+
class HubProgressComponent {
|
|
14
|
+
/** Current progress value, expressed on the `[0, max]` scale. */
|
|
15
|
+
value = input(0, /* @ts-ignore */
|
|
16
|
+
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
17
|
+
/** Upper bound of the progress scale. */
|
|
18
|
+
max = input(100, /* @ts-ignore */
|
|
19
|
+
...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
|
|
20
|
+
/** Renders a looping bar for work of unknown duration; drops `aria-valuenow`. */
|
|
21
|
+
indeterminate = input(false, { ...(ngDevMode ? { debugName: "indeterminate" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
22
|
+
/** Semantic accent driving the indicator colour. */
|
|
23
|
+
color = input('primary', /* @ts-ignore */
|
|
24
|
+
...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
|
|
25
|
+
/** Size token controlling the bar thickness. */
|
|
26
|
+
size = input('md', /* @ts-ignore */
|
|
27
|
+
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
28
|
+
/** Whether the rounded percentage is rendered next to the bar. */
|
|
29
|
+
showValue = input(false, { ...(ngDevMode ? { debugName: "showValue" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
30
|
+
/** Accessible label describing what the progress bar measures. */
|
|
31
|
+
label = input('', /* @ts-ignore */
|
|
32
|
+
...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
33
|
+
/** Value clamped to the `[0, max]` range; `0` when `max` is not positive. */
|
|
34
|
+
clampedValue = computed(() => {
|
|
35
|
+
const max = this.max();
|
|
36
|
+
if (max <= 0) {
|
|
37
|
+
return 0;
|
|
38
|
+
}
|
|
39
|
+
return Math.min(max, Math.max(0, this.value()));
|
|
40
|
+
}, /* @ts-ignore */
|
|
41
|
+
...(ngDevMode ? [{ debugName: "clampedValue" }] : /* istanbul ignore next */ []));
|
|
42
|
+
/** Completion ratio as a `0..100` percentage; `0` while indeterminate. */
|
|
43
|
+
percent = computed(() => {
|
|
44
|
+
const max = this.max();
|
|
45
|
+
if (this.indeterminate() || max <= 0) {
|
|
46
|
+
return 0;
|
|
47
|
+
}
|
|
48
|
+
return (this.clampedValue() / max) * 100;
|
|
49
|
+
}, /* @ts-ignore */
|
|
50
|
+
...(ngDevMode ? [{ debugName: "percent" }] : /* istanbul ignore next */ []));
|
|
51
|
+
/** Indicator width as a CSS length consumed by `--hub-progress-value`. */
|
|
52
|
+
valueCss = computed(() => `${this.percent()}%`, /* @ts-ignore */
|
|
53
|
+
...(ngDevMode ? [{ debugName: "valueCss" }] : /* istanbul ignore next */ []));
|
|
54
|
+
/** Rounded percentage label shown when {@link showValue} is enabled. */
|
|
55
|
+
displayValue = computed(() => `${Math.round(this.percent())}%`, /* @ts-ignore */
|
|
56
|
+
...(ngDevMode ? [{ debugName: "displayValue" }] : /* istanbul ignore next */ []));
|
|
57
|
+
/** `aria-valuenow`, omitted (null) while the bar is {@link indeterminate}. */
|
|
58
|
+
ariaValueNow = computed(() => (this.indeterminate() ? null : this.clampedValue()), /* @ts-ignore */
|
|
59
|
+
...(ngDevMode ? [{ debugName: "ariaValueNow" }] : /* istanbul ignore next */ []));
|
|
60
|
+
/** Local accent slot resolved from the semantic {@link color} input. */
|
|
61
|
+
accentVar = computed(() => `var(--hub-sys-color-${this.color()}, var(--hub-sys-color-primary, #0d6efd))`, /* @ts-ignore */
|
|
62
|
+
...(ngDevMode ? [{ debugName: "accentVar" }] : /* istanbul ignore next */ []));
|
|
63
|
+
/** Host modifier classes derived from the signal inputs. */
|
|
64
|
+
hostClasses = computed(() => ['hub-progress', `hub-progress--${this.size()}`, this.indeterminate() ? 'hub-progress--indeterminate' : '']
|
|
65
|
+
.filter(Boolean)
|
|
66
|
+
.join(' '), /* @ts-ignore */
|
|
67
|
+
...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
68
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: HubProgressComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
69
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.1", type: HubProgressComponent, isStandalone: true, selector: "hub-progress", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, indeterminate: { classPropertyName: "indeterminate", publicName: "indeterminate", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, showValue: { classPropertyName: "showValue", publicName: "showValue", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "progressbar" }, properties: { "class": "hostClasses()", "style.--hub-progress-accent": "accentVar()", "style.--hub-progress-value": "valueCss()", "attr.aria-valuemin": "0", "attr.aria-valuemax": "max()", "attr.aria-valuenow": "ariaValueNow()", "attr.aria-label": "label() || null", "attr.aria-busy": "indeterminate() || null" }, classAttribute: "hub-progress" }, ngImport: i0, template: "@if (label()) {\n\t<span class=\"hub-progress__label\">{{ label() }}</span>\n}\n\n<span class=\"hub-progress__track\">\n\t<span class=\"hub-progress__indicator\"></span>\n</span>\n\n@if (showValue() && !indeterminate()) {\n\t<span class=\"hub-progress__value\">{{ displayValue() }}</span>\n}\n", styles: [":where(.hub-progress){--hub-progress-accent: var(--hub-sys-color-primary, #0d6efd);--hub-progress-track-bg: color-mix(in oklch, var(--hub-progress-accent) 16%, transparent);--hub-progress-indicator-bg: var(--hub-progress-accent);--hub-progress-height: var(--hub-ref-space-2, .5rem);--hub-progress-radius: var(--hub-ref-radius-pill, 50rem)}.hub-progress{display:flex;align-items:center;gap:var(--hub-ref-space-2, .5rem);inline-size:100%}.hub-progress__label{flex:0 0 auto;color:var(--hub-sys-text-muted, #6c757d);font-size:var(--hub-ref-font-size-sm, .875rem)}.hub-progress__track{position:relative;flex:1 1 auto;block-size:var(--hub-progress-height);overflow:hidden;background:var(--hub-progress-track-bg);border-radius:var(--hub-progress-radius)}.hub-progress__indicator{display:block;inline-size:var(--hub-progress-value, 0%);block-size:100%;background:var(--hub-progress-indicator-bg);border-radius:inherit;transition:inline-size .3s ease}.hub-progress__value{flex:0 0 auto;min-inline-size:3ch;color:var(--hub-sys-text-primary, #212529);font-size:var(--hub-ref-font-size-sm, .875rem);font-weight:var(--hub-ref-font-weight-semibold, 600);text-align:end;font-variant-numeric:tabular-nums}.hub-progress--sm{--hub-progress-height: var(--hub-ref-space-1, .25rem)}.hub-progress--md{--hub-progress-height: var(--hub-ref-space-2, .5rem)}.hub-progress--lg{--hub-progress-height: var(--hub-ref-space-3, .75rem)}.hub-progress--indeterminate .hub-progress__indicator{inline-size:40%;transition:none;animation:hub-progress-indeterminate 1.4s ease-in-out infinite}@keyframes hub-progress-indeterminate{0%{transform:translate(-100%)}to{transform:translate(300%)}}@media(prefers-reduced-motion:reduce){.hub-progress--indeterminate .hub-progress__indicator{animation-duration:3s}.hub-progress__indicator{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
70
|
+
}
|
|
71
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: HubProgressComponent, decorators: [{
|
|
72
|
+
type: Component,
|
|
73
|
+
args: [{ selector: 'hub-progress', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
|
|
74
|
+
class: 'hub-progress',
|
|
75
|
+
role: 'progressbar',
|
|
76
|
+
'[class]': 'hostClasses()',
|
|
77
|
+
'[style.--hub-progress-accent]': 'accentVar()',
|
|
78
|
+
'[style.--hub-progress-value]': 'valueCss()',
|
|
79
|
+
'[attr.aria-valuemin]': '0',
|
|
80
|
+
'[attr.aria-valuemax]': 'max()',
|
|
81
|
+
'[attr.aria-valuenow]': 'ariaValueNow()',
|
|
82
|
+
'[attr.aria-label]': 'label() || null',
|
|
83
|
+
'[attr.aria-busy]': 'indeterminate() || null'
|
|
84
|
+
}, template: "@if (label()) {\n\t<span class=\"hub-progress__label\">{{ label() }}</span>\n}\n\n<span class=\"hub-progress__track\">\n\t<span class=\"hub-progress__indicator\"></span>\n</span>\n\n@if (showValue() && !indeterminate()) {\n\t<span class=\"hub-progress__value\">{{ displayValue() }}</span>\n}\n", styles: [":where(.hub-progress){--hub-progress-accent: var(--hub-sys-color-primary, #0d6efd);--hub-progress-track-bg: color-mix(in oklch, var(--hub-progress-accent) 16%, transparent);--hub-progress-indicator-bg: var(--hub-progress-accent);--hub-progress-height: var(--hub-ref-space-2, .5rem);--hub-progress-radius: var(--hub-ref-radius-pill, 50rem)}.hub-progress{display:flex;align-items:center;gap:var(--hub-ref-space-2, .5rem);inline-size:100%}.hub-progress__label{flex:0 0 auto;color:var(--hub-sys-text-muted, #6c757d);font-size:var(--hub-ref-font-size-sm, .875rem)}.hub-progress__track{position:relative;flex:1 1 auto;block-size:var(--hub-progress-height);overflow:hidden;background:var(--hub-progress-track-bg);border-radius:var(--hub-progress-radius)}.hub-progress__indicator{display:block;inline-size:var(--hub-progress-value, 0%);block-size:100%;background:var(--hub-progress-indicator-bg);border-radius:inherit;transition:inline-size .3s ease}.hub-progress__value{flex:0 0 auto;min-inline-size:3ch;color:var(--hub-sys-text-primary, #212529);font-size:var(--hub-ref-font-size-sm, .875rem);font-weight:var(--hub-ref-font-weight-semibold, 600);text-align:end;font-variant-numeric:tabular-nums}.hub-progress--sm{--hub-progress-height: var(--hub-ref-space-1, .25rem)}.hub-progress--md{--hub-progress-height: var(--hub-ref-space-2, .5rem)}.hub-progress--lg{--hub-progress-height: var(--hub-ref-space-3, .75rem)}.hub-progress--indeterminate .hub-progress__indicator{inline-size:40%;transition:none;animation:hub-progress-indeterminate 1.4s ease-in-out infinite}@keyframes hub-progress-indeterminate{0%{transform:translate(-100%)}to{transform:translate(300%)}}@media(prefers-reduced-motion:reduce){.hub-progress--indeterminate .hub-progress__indicator{animation-duration:3s}.hub-progress__indicator{transition:none}}\n"] }]
|
|
85
|
+
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], indeterminate: [{ type: i0.Input, args: [{ isSignal: true, alias: "indeterminate", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], showValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValue", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }] } });
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Graded gauge bar following HTML `<meter>` semantics for a scalar measurement
|
|
89
|
+
* within a known range (disk usage, score, capacity…).
|
|
90
|
+
*
|
|
91
|
+
* The filled colour reflects which band the value falls in relative to the
|
|
92
|
+
* `optimum` point: inside the `[low, high]` plateau it uses the optimum fill,
|
|
93
|
+
* below `optimum` and outside the plateau the low fill, above it the high fill.
|
|
94
|
+
* Every band colour derives from a `--hub-meter-*-bg` token so no colour is
|
|
95
|
+
* hard-coded.
|
|
96
|
+
*/
|
|
97
|
+
class HubMeterComponent {
|
|
98
|
+
/** Current measurement, expressed on the `[min, max]` scale. */
|
|
99
|
+
value = input(0, /* @ts-ignore */
|
|
100
|
+
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
101
|
+
/** Lower bound of the scale. */
|
|
102
|
+
min = input(0, /* @ts-ignore */
|
|
103
|
+
...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
|
|
104
|
+
/** Upper bound of the scale. */
|
|
105
|
+
max = input(1, /* @ts-ignore */
|
|
106
|
+
...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
|
|
107
|
+
/** Upper limit of the "low" region; defaults to {@link min} when omitted. */
|
|
108
|
+
low = input(undefined, /* @ts-ignore */
|
|
109
|
+
...(ngDevMode ? [{ debugName: "low" }] : /* istanbul ignore next */ []));
|
|
110
|
+
/** Lower limit of the "high" region; defaults to {@link max} when omitted. */
|
|
111
|
+
high = input(undefined, /* @ts-ignore */
|
|
112
|
+
...(ngDevMode ? [{ debugName: "high" }] : /* istanbul ignore next */ []));
|
|
113
|
+
/** Preferred point of the range; defaults to the midpoint when omitted. */
|
|
114
|
+
optimum = input(undefined, /* @ts-ignore */
|
|
115
|
+
...(ngDevMode ? [{ debugName: "optimum" }] : /* istanbul ignore next */ []));
|
|
116
|
+
/** Fully resolved, clamped bounds derived from the raw inputs. */
|
|
117
|
+
resolved = computed(() => {
|
|
118
|
+
const min = this.min();
|
|
119
|
+
const max = Math.max(min, this.max());
|
|
120
|
+
const clamp = (candidate) => Math.min(max, Math.max(min, candidate));
|
|
121
|
+
const value = clamp(this.value());
|
|
122
|
+
const low = this.low() === undefined ? min : clamp(this.low());
|
|
123
|
+
const high = this.high() === undefined ? max : Math.max(low, clamp(this.high()));
|
|
124
|
+
const optimum = this.optimum() === undefined ? (min + max) / 2 : clamp(this.optimum());
|
|
125
|
+
const span = max - min;
|
|
126
|
+
const percent = span <= 0 ? 0 : ((value - min) / span) * 100;
|
|
127
|
+
return { min, max, value, low, high, optimum, percent };
|
|
128
|
+
}, /* @ts-ignore */
|
|
129
|
+
...(ngDevMode ? [{ debugName: "resolved" }] : /* istanbul ignore next */ []));
|
|
130
|
+
/**
|
|
131
|
+
* The band the value falls in: `optimum` inside the `[low, high]` plateau,
|
|
132
|
+
* otherwise `low`/`high` depending on which side of `optimum` the value sits.
|
|
133
|
+
*/
|
|
134
|
+
band = computed(() => {
|
|
135
|
+
const { value, low, high, optimum } = this.resolved();
|
|
136
|
+
if (value >= low && value <= high) {
|
|
137
|
+
return 'optimum';
|
|
138
|
+
}
|
|
139
|
+
return value < optimum ? 'low' : 'high';
|
|
140
|
+
}, /* @ts-ignore */
|
|
141
|
+
...(ngDevMode ? [{ debugName: "band" }] : /* istanbul ignore next */ []));
|
|
142
|
+
/** Fill width as a CSS length consumed by `--hub-meter-value`. */
|
|
143
|
+
valueCss = computed(() => `${this.resolved().percent}%`, /* @ts-ignore */
|
|
144
|
+
...(ngDevMode ? [{ debugName: "valueCss" }] : /* istanbul ignore next */ []));
|
|
145
|
+
/** Human-readable `aria-valuetext` (rounded percentage plus band). */
|
|
146
|
+
valueText = computed(() => `${Math.round(this.resolved().percent)}% (${this.band()})`, /* @ts-ignore */
|
|
147
|
+
...(ngDevMode ? [{ debugName: "valueText" }] : /* istanbul ignore next */ []));
|
|
148
|
+
/** Host modifier classes derived from the computed band. */
|
|
149
|
+
hostClasses = computed(() => ['hub-meter', `hub-meter--${this.band()}`].join(' '), /* @ts-ignore */
|
|
150
|
+
...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
151
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: HubMeterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
152
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.1", type: HubMeterComponent, isStandalone: true, selector: "hub-meter", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, low: { classPropertyName: "low", publicName: "low", isSignal: true, isRequired: false, transformFunction: null }, high: { classPropertyName: "high", publicName: "high", isSignal: true, isRequired: false, transformFunction: null }, optimum: { classPropertyName: "optimum", publicName: "optimum", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "meter" }, properties: { "class": "hostClasses()", "attr.data-band": "band()", "style.--hub-meter-value": "valueCss()", "attr.aria-valuemin": "resolved().min", "attr.aria-valuemax": "resolved().max", "attr.aria-valuenow": "resolved().value", "attr.aria-valuetext": "valueText()" }, classAttribute: "hub-meter" }, ngImport: i0, template: "<span class=\"hub-meter__track\">\n\t<span class=\"hub-meter__indicator\"></span>\n</span>\n", styles: [":where(.hub-meter){--hub-meter-track-bg: color-mix(in oklch, var(--hub-sys-color-neutral, #6c757d) 16%, transparent);--hub-meter-low-bg: var(--hub-sys-color-danger, #dc3545);--hub-meter-optimum-bg: var(--hub-sys-color-success, #198754);--hub-meter-high-bg: var(--hub-sys-color-warning, #ffc107);--hub-meter-height: var(--hub-ref-space-2, .5rem);--hub-meter-radius: var(--hub-ref-radius-pill, 50rem);--hub-meter-fill: var(--hub-meter-optimum-bg)}.hub-meter{display:block;inline-size:100%}.hub-meter__track{position:relative;display:block;block-size:var(--hub-meter-height);overflow:hidden;background:var(--hub-meter-track-bg);border-radius:var(--hub-meter-radius)}.hub-meter__indicator{display:block;inline-size:var(--hub-meter-value, 0%);block-size:100%;background:var(--hub-meter-fill);border-radius:inherit;transition:inline-size .3s ease,background-color .3s ease}.hub-meter--low{--hub-meter-fill: var(--hub-meter-low-bg)}.hub-meter--optimum{--hub-meter-fill: var(--hub-meter-optimum-bg)}.hub-meter--high{--hub-meter-fill: var(--hub-meter-high-bg)}@media(prefers-reduced-motion:reduce){.hub-meter__indicator{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
153
|
+
}
|
|
154
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: HubMeterComponent, decorators: [{
|
|
155
|
+
type: Component,
|
|
156
|
+
args: [{ selector: 'hub-meter', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
|
|
157
|
+
class: 'hub-meter',
|
|
158
|
+
role: 'meter',
|
|
159
|
+
'[class]': 'hostClasses()',
|
|
160
|
+
'[attr.data-band]': 'band()',
|
|
161
|
+
'[style.--hub-meter-value]': 'valueCss()',
|
|
162
|
+
'[attr.aria-valuemin]': 'resolved().min',
|
|
163
|
+
'[attr.aria-valuemax]': 'resolved().max',
|
|
164
|
+
'[attr.aria-valuenow]': 'resolved().value',
|
|
165
|
+
'[attr.aria-valuetext]': 'valueText()'
|
|
166
|
+
}, template: "<span class=\"hub-meter__track\">\n\t<span class=\"hub-meter__indicator\"></span>\n</span>\n", styles: [":where(.hub-meter){--hub-meter-track-bg: color-mix(in oklch, var(--hub-sys-color-neutral, #6c757d) 16%, transparent);--hub-meter-low-bg: var(--hub-sys-color-danger, #dc3545);--hub-meter-optimum-bg: var(--hub-sys-color-success, #198754);--hub-meter-high-bg: var(--hub-sys-color-warning, #ffc107);--hub-meter-height: var(--hub-ref-space-2, .5rem);--hub-meter-radius: var(--hub-ref-radius-pill, 50rem);--hub-meter-fill: var(--hub-meter-optimum-bg)}.hub-meter{display:block;inline-size:100%}.hub-meter__track{position:relative;display:block;block-size:var(--hub-meter-height);overflow:hidden;background:var(--hub-meter-track-bg);border-radius:var(--hub-meter-radius)}.hub-meter__indicator{display:block;inline-size:var(--hub-meter-value, 0%);block-size:100%;background:var(--hub-meter-fill);border-radius:inherit;transition:inline-size .3s ease,background-color .3s ease}.hub-meter--low{--hub-meter-fill: var(--hub-meter-low-bg)}.hub-meter--optimum{--hub-meter-fill: var(--hub-meter-optimum-bg)}.hub-meter--high{--hub-meter-fill: var(--hub-meter-high-bg)}@media(prefers-reduced-motion:reduce){.hub-meter__indicator{transition:none}}\n"] }]
|
|
167
|
+
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], low: [{ type: i0.Input, args: [{ isSignal: true, alias: "low", required: false }] }], high: [{ type: i0.Input, args: [{ isSignal: true, alias: "high", required: false }] }], optimum: [{ type: i0.Input, args: [{ isSignal: true, alias: "optimum", required: false }] }] } });
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Circular gauge (ring) rendering a normalized score as an SVG arc.
|
|
171
|
+
*
|
|
172
|
+
* The value is normalized against `max` (accepting either a `0..1` ratio or a
|
|
173
|
+
* `0..max` figure) and drawn with a `stroke-dasharray`/`stroke-dashoffset` arc
|
|
174
|
+
* over a `pathLength`-normalized circle, so the offset maps linearly to the
|
|
175
|
+
* completion (100 at 0%, 0 at 100%). Optional {@link thresholds} recolour the
|
|
176
|
+
* indicator through the `--hub-ring-low-color` / `--hub-ring-high-color` tokens;
|
|
177
|
+
* a centred caption is projected through `<ng-content>`.
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```html
|
|
181
|
+
* <hub-ring [value]="0.82" [thresholds]="{ low: 0.4, high: 0.75 }">Score</hub-ring>
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
184
|
+
class HubRingComponent {
|
|
185
|
+
/** Score value, expressed as a `0..1` ratio or a `0..max` figure. */
|
|
186
|
+
value = input(0, /* @ts-ignore */
|
|
187
|
+
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
188
|
+
/** Upper bound the {@link value} is normalized against. */
|
|
189
|
+
max = input(1, /* @ts-ignore */
|
|
190
|
+
...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
|
|
191
|
+
/** Outer diameter of the ring (number → px, or any CSS length string). */
|
|
192
|
+
size = input('4rem', /* @ts-ignore */
|
|
193
|
+
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
194
|
+
/** Stroke width of the ring (number → px, or any CSS length string). */
|
|
195
|
+
thickness = input('0.5rem', /* @ts-ignore */
|
|
196
|
+
...(ngDevMode ? [{ debugName: "thickness" }] : /* istanbul ignore next */ []));
|
|
197
|
+
/** Optional colour thresholds recolouring the indicator by band. */
|
|
198
|
+
thresholds = input(undefined, /* @ts-ignore */
|
|
199
|
+
...(ngDevMode ? [{ debugName: "thresholds" }] : /* istanbul ignore next */ []));
|
|
200
|
+
/** Whether the rounded percentage is rendered in the centre. */
|
|
201
|
+
showValue = input(true, { ...(ngDevMode ? { debugName: "showValue" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
202
|
+
/** Total normalized path length of the SVG circle (see `pathLength`). */
|
|
203
|
+
PATH_LENGTH = 100;
|
|
204
|
+
/** Completion ratio in `[0, 1]`; `0` when `max` is not positive. */
|
|
205
|
+
fraction = computed(() => {
|
|
206
|
+
const max = this.max();
|
|
207
|
+
if (max <= 0) {
|
|
208
|
+
return 0;
|
|
209
|
+
}
|
|
210
|
+
return Math.min(1, Math.max(0, this.value() / max));
|
|
211
|
+
}, /* @ts-ignore */
|
|
212
|
+
...(ngDevMode ? [{ debugName: "fraction" }] : /* istanbul ignore next */ []));
|
|
213
|
+
/** Completion as a `0..100` percentage. */
|
|
214
|
+
percent = computed(() => this.fraction() * 100, /* @ts-ignore */
|
|
215
|
+
...(ngDevMode ? [{ debugName: "percent" }] : /* istanbul ignore next */ []));
|
|
216
|
+
/** Dash pattern for the indicator (the full normalized path). */
|
|
217
|
+
dashArray = computed(() => this.PATH_LENGTH, /* @ts-ignore */
|
|
218
|
+
...(ngDevMode ? [{ debugName: "dashArray" }] : /* istanbul ignore next */ []));
|
|
219
|
+
/** Dash offset drawing the arc: `PATH_LENGTH` at 0%, `0` at 100%. */
|
|
220
|
+
dashOffset = computed(() => this.PATH_LENGTH * (1 - this.fraction()), /* @ts-ignore */
|
|
221
|
+
...(ngDevMode ? [{ debugName: "dashOffset" }] : /* istanbul ignore next */ []));
|
|
222
|
+
/** Rounded percentage label shown in the centre when {@link showValue} is on. */
|
|
223
|
+
displayValue = computed(() => `${Math.round(this.percent())}%`, /* @ts-ignore */
|
|
224
|
+
...(ngDevMode ? [{ debugName: "displayValue" }] : /* istanbul ignore next */ []));
|
|
225
|
+
/** Colour band derived from the optional {@link thresholds} against the value. */
|
|
226
|
+
band = computed(() => {
|
|
227
|
+
const thresholds = this.thresholds();
|
|
228
|
+
if (!thresholds) {
|
|
229
|
+
return 'default';
|
|
230
|
+
}
|
|
231
|
+
const value = this.value();
|
|
232
|
+
if (thresholds.low !== undefined && value < thresholds.low) {
|
|
233
|
+
return 'low';
|
|
234
|
+
}
|
|
235
|
+
if (thresholds.high !== undefined && value >= thresholds.high) {
|
|
236
|
+
return 'high';
|
|
237
|
+
}
|
|
238
|
+
return 'default';
|
|
239
|
+
}, /* @ts-ignore */
|
|
240
|
+
...(ngDevMode ? [{ debugName: "band" }] : /* istanbul ignore next */ []));
|
|
241
|
+
/** Host modifier classes derived from the computed band. */
|
|
242
|
+
hostClasses = computed(() => ['hub-ring', `hub-ring--${this.band()}`].join(' '), /* @ts-ignore */
|
|
243
|
+
...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
244
|
+
/** Ring diameter as a CSS length (numbers are treated as pixels). */
|
|
245
|
+
sizeCss = computed(() => this.toCssLength(this.size()), /* @ts-ignore */
|
|
246
|
+
...(ngDevMode ? [{ debugName: "sizeCss" }] : /* istanbul ignore next */ []));
|
|
247
|
+
/** Stroke thickness as a CSS length (numbers are treated as pixels). */
|
|
248
|
+
thicknessCss = computed(() => this.toCssLength(this.thickness()), /* @ts-ignore */
|
|
249
|
+
...(ngDevMode ? [{ debugName: "thicknessCss" }] : /* istanbul ignore next */ []));
|
|
250
|
+
/** Normalizes a number|string dimension into a CSS length string. */
|
|
251
|
+
toCssLength(dimension) {
|
|
252
|
+
return typeof dimension === 'number' ? `${dimension}px` : dimension;
|
|
253
|
+
}
|
|
254
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: HubRingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
255
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.1", type: HubRingComponent, isStandalone: true, selector: "hub-ring", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, thickness: { classPropertyName: "thickness", publicName: "thickness", isSignal: true, isRequired: false, transformFunction: null }, thresholds: { classPropertyName: "thresholds", publicName: "thresholds", isSignal: true, isRequired: false, transformFunction: null }, showValue: { classPropertyName: "showValue", publicName: "showValue", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "img" }, properties: { "class": "hostClasses()", "style.--hub-ring-size": "sizeCss()", "style.--hub-ring-thickness": "thicknessCss()", "attr.aria-valuemin": "0", "attr.aria-valuemax": "max()", "attr.aria-valuenow": "value()", "attr.aria-valuetext": "displayValue()", "attr.aria-label": "displayValue()" }, classAttribute: "hub-ring" }, exportAs: ["hubGauge"], ngImport: i0, template: "<svg class=\"hub-ring__svg\" viewBox=\"0 0 100 100\" aria-hidden=\"true\" focusable=\"false\">\n\t<circle class=\"hub-ring__track\" cx=\"50\" cy=\"50\" r=\"44\" [attr.pathLength]=\"PATH_LENGTH\" />\n\t<circle\n\t\tclass=\"hub-ring__indicator\"\n\t\tcx=\"50\"\n\t\tcy=\"50\"\n\t\tr=\"44\"\n\t\t[attr.pathLength]=\"PATH_LENGTH\"\n\t\t[attr.stroke-dasharray]=\"dashArray()\"\n\t\t[attr.stroke-dashoffset]=\"dashOffset()\"\n\t/>\n</svg>\n\n<span class=\"hub-ring__caption\">\n\t@if (showValue()) {\n\t\t<span class=\"hub-ring__value\">{{ displayValue() }}</span>\n\t}\n\t<ng-content />\n</span>\n", styles: [":where(.hub-ring){--hub-ring-size: 4rem;--hub-ring-thickness: var(--hub-ref-space-2, .5rem);--hub-ring-track: color-mix(in oklch, var(--hub-sys-color-neutral, #6c757d) 20%, transparent);--hub-ring-indicator: var(--hub-sys-color-primary, #0d6efd);--hub-ring-caption-color: var(--hub-sys-text-primary, #212529);--hub-ring-low-color: var(--hub-sys-color-danger, #dc3545);--hub-ring-high-color: var(--hub-sys-color-success, #198754)}.hub-ring{position:relative;display:inline-flex;align-items:center;justify-content:center;inline-size:var(--hub-ring-size);block-size:var(--hub-ring-size)}.hub-ring__svg{inline-size:100%;block-size:100%;transform:rotate(-90deg);overflow:visible}.hub-ring__track,.hub-ring__indicator{fill:none;stroke-width:var(--hub-ring-thickness);stroke-linecap:round}.hub-ring__track{stroke:var(--hub-ring-track)}.hub-ring__indicator{stroke:var(--hub-ring-indicator);transition:stroke-dashoffset .4s ease,stroke .3s ease}.hub-ring__caption{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.125rem;color:var(--hub-ring-caption-color);text-align:center;line-height:1.1;pointer-events:none}.hub-ring__value{font-size:calc(var(--hub-ring-size) * .24);font-weight:var(--hub-ref-font-weight-semibold, 600);font-variant-numeric:tabular-nums}.hub-ring--low{--hub-ring-indicator: var(--hub-ring-low-color)}.hub-ring--high{--hub-ring-indicator: var(--hub-ring-high-color)}@media(prefers-reduced-motion:reduce){.hub-ring__indicator{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
256
|
+
}
|
|
257
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: HubRingComponent, decorators: [{
|
|
258
|
+
type: Component,
|
|
259
|
+
args: [{ selector: 'hub-ring', exportAs: 'hubGauge', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
|
|
260
|
+
class: 'hub-ring',
|
|
261
|
+
role: 'img',
|
|
262
|
+
'[class]': 'hostClasses()',
|
|
263
|
+
'[style.--hub-ring-size]': 'sizeCss()',
|
|
264
|
+
'[style.--hub-ring-thickness]': 'thicknessCss()',
|
|
265
|
+
'[attr.aria-valuemin]': '0',
|
|
266
|
+
'[attr.aria-valuemax]': 'max()',
|
|
267
|
+
'[attr.aria-valuenow]': 'value()',
|
|
268
|
+
'[attr.aria-valuetext]': 'displayValue()',
|
|
269
|
+
'[attr.aria-label]': 'displayValue()'
|
|
270
|
+
}, template: "<svg class=\"hub-ring__svg\" viewBox=\"0 0 100 100\" aria-hidden=\"true\" focusable=\"false\">\n\t<circle class=\"hub-ring__track\" cx=\"50\" cy=\"50\" r=\"44\" [attr.pathLength]=\"PATH_LENGTH\" />\n\t<circle\n\t\tclass=\"hub-ring__indicator\"\n\t\tcx=\"50\"\n\t\tcy=\"50\"\n\t\tr=\"44\"\n\t\t[attr.pathLength]=\"PATH_LENGTH\"\n\t\t[attr.stroke-dasharray]=\"dashArray()\"\n\t\t[attr.stroke-dashoffset]=\"dashOffset()\"\n\t/>\n</svg>\n\n<span class=\"hub-ring__caption\">\n\t@if (showValue()) {\n\t\t<span class=\"hub-ring__value\">{{ displayValue() }}</span>\n\t}\n\t<ng-content />\n</span>\n", styles: [":where(.hub-ring){--hub-ring-size: 4rem;--hub-ring-thickness: var(--hub-ref-space-2, .5rem);--hub-ring-track: color-mix(in oklch, var(--hub-sys-color-neutral, #6c757d) 20%, transparent);--hub-ring-indicator: var(--hub-sys-color-primary, #0d6efd);--hub-ring-caption-color: var(--hub-sys-text-primary, #212529);--hub-ring-low-color: var(--hub-sys-color-danger, #dc3545);--hub-ring-high-color: var(--hub-sys-color-success, #198754)}.hub-ring{position:relative;display:inline-flex;align-items:center;justify-content:center;inline-size:var(--hub-ring-size);block-size:var(--hub-ring-size)}.hub-ring__svg{inline-size:100%;block-size:100%;transform:rotate(-90deg);overflow:visible}.hub-ring__track,.hub-ring__indicator{fill:none;stroke-width:var(--hub-ring-thickness);stroke-linecap:round}.hub-ring__track{stroke:var(--hub-ring-track)}.hub-ring__indicator{stroke:var(--hub-ring-indicator);transition:stroke-dashoffset .4s ease,stroke .3s ease}.hub-ring__caption{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.125rem;color:var(--hub-ring-caption-color);text-align:center;line-height:1.1;pointer-events:none}.hub-ring__value{font-size:calc(var(--hub-ring-size) * .24);font-weight:var(--hub-ref-font-weight-semibold, 600);font-variant-numeric:tabular-nums}.hub-ring--low{--hub-ring-indicator: var(--hub-ring-low-color)}.hub-ring--high{--hub-ring-indicator: var(--hub-ring-high-color)}@media(prefers-reduced-motion:reduce){.hub-ring__indicator{transition:none}}\n"] }]
|
|
271
|
+
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], thickness: [{ type: i0.Input, args: [{ isSignal: true, alias: "thickness", required: false }] }], thresholds: [{ type: i0.Input, args: [{ isSignal: true, alias: "thresholds", required: false }] }], showValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValue", required: false }] }] } });
|
|
272
|
+
|
|
273
|
+
/*
|
|
274
|
+
* Public API Surface of ng-hub-ui-metrics
|
|
275
|
+
*/
|
|
276
|
+
// Components
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Generated bundle index. Do not edit.
|
|
280
|
+
*/
|
|
281
|
+
|
|
282
|
+
export { HubMeterComponent, HubProgressComponent, HubRingComponent };
|
|
283
|
+
//# sourceMappingURL=ng-hub-ui-metrics.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ng-hub-ui-metrics.mjs","sources":["../../../projects/metrics/src/lib/components/progress/progress.component.ts","../../../projects/metrics/src/lib/components/progress/progress.component.html","../../../projects/metrics/src/lib/components/meter/meter.component.ts","../../../projects/metrics/src/lib/components/meter/meter.component.html","../../../projects/metrics/src/lib/components/ring/ring.component.ts","../../../projects/metrics/src/lib/components/ring/ring.component.html","../../../projects/metrics/src/public-api.ts","../../../projects/metrics/src/ng-hub-ui-metrics.ts"],"sourcesContent":["import { booleanAttribute, ChangeDetectionStrategy, Component, computed, input, ViewEncapsulation } from '@angular/core';\nimport { HubMetricsColor } from '../../models/metrics.types';\nimport { HubProgressSize } from './progress.types';\n\n/**\n * Linear progress bar for a determinate or indeterminate read-only value.\n *\n * The component owns no hard-coded colour values: the semantic `color` input\n * maps to the host application's `--hub-sys-color-*` token family and drives the\n * indicator through the local `--hub-progress-accent` slot. When\n * {@link indeterminate} is set the bar loops a looping animation and drops\n * `aria-valuenow`, matching the ARIA `progressbar` contract for an unknown value.\n */\n@Component({\n\tselector: 'hub-progress',\n\tstandalone: true,\n\tchangeDetection: ChangeDetectionStrategy.OnPush,\n\ttemplateUrl: './progress.component.html',\n\tstyleUrl: './progress.component.scss',\n\tencapsulation: ViewEncapsulation.None,\n\thost: {\n\t\tclass: 'hub-progress',\n\t\trole: 'progressbar',\n\t\t'[class]': 'hostClasses()',\n\t\t'[style.--hub-progress-accent]': 'accentVar()',\n\t\t'[style.--hub-progress-value]': 'valueCss()',\n\t\t'[attr.aria-valuemin]': '0',\n\t\t'[attr.aria-valuemax]': 'max()',\n\t\t'[attr.aria-valuenow]': 'ariaValueNow()',\n\t\t'[attr.aria-label]': 'label() || null',\n\t\t'[attr.aria-busy]': 'indeterminate() || null'\n\t}\n})\nexport class HubProgressComponent {\n\t/** Current progress value, expressed on the `[0, max]` scale. */\n\treadonly value = input<number>(0);\n\n\t/** Upper bound of the progress scale. */\n\treadonly max = input<number>(100);\n\n\t/** Renders a looping bar for work of unknown duration; drops `aria-valuenow`. */\n\treadonly indeterminate = input(false, { transform: booleanAttribute });\n\n\t/** Semantic accent driving the indicator colour. */\n\treadonly color = input<HubMetricsColor>('primary');\n\n\t/** Size token controlling the bar thickness. */\n\treadonly size = input<HubProgressSize>('md');\n\n\t/** Whether the rounded percentage is rendered next to the bar. */\n\treadonly showValue = input(false, { transform: booleanAttribute });\n\n\t/** Accessible label describing what the progress bar measures. */\n\treadonly label = input<string>('');\n\n\t/** Value clamped to the `[0, max]` range; `0` when `max` is not positive. */\n\tprotected readonly clampedValue = computed(() => {\n\t\tconst max = this.max();\n\t\tif (max <= 0) {\n\t\t\treturn 0;\n\t\t}\n\t\treturn Math.min(max, Math.max(0, this.value()));\n\t});\n\n\t/** Completion ratio as a `0..100` percentage; `0` while indeterminate. */\n\tprotected readonly percent = computed(() => {\n\t\tconst max = this.max();\n\t\tif (this.indeterminate() || max <= 0) {\n\t\t\treturn 0;\n\t\t}\n\t\treturn (this.clampedValue() / max) * 100;\n\t});\n\n\t/** Indicator width as a CSS length consumed by `--hub-progress-value`. */\n\tprotected readonly valueCss = computed(() => `${this.percent()}%`);\n\n\t/** Rounded percentage label shown when {@link showValue} is enabled. */\n\tprotected readonly displayValue = computed(() => `${Math.round(this.percent())}%`);\n\n\t/** `aria-valuenow`, omitted (null) while the bar is {@link indeterminate}. */\n\tprotected readonly ariaValueNow = computed(() => (this.indeterminate() ? null : this.clampedValue()));\n\n\t/** Local accent slot resolved from the semantic {@link color} input. */\n\tprotected readonly accentVar = computed(\n\t\t() => `var(--hub-sys-color-${this.color()}, var(--hub-sys-color-primary, #0d6efd))`\n\t);\n\n\t/** Host modifier classes derived from the signal inputs. */\n\tprotected readonly hostClasses = computed(() =>\n\t\t['hub-progress', `hub-progress--${this.size()}`, this.indeterminate() ? 'hub-progress--indeterminate' : '']\n\t\t\t.filter(Boolean)\n\t\t\t.join(' ')\n\t);\n}\n","@if (label()) {\n\t<span class=\"hub-progress__label\">{{ label() }}</span>\n}\n\n<span class=\"hub-progress__track\">\n\t<span class=\"hub-progress__indicator\"></span>\n</span>\n\n@if (showValue() && !indeterminate()) {\n\t<span class=\"hub-progress__value\">{{ displayValue() }}</span>\n}\n","import { ChangeDetectionStrategy, Component, computed, input, ViewEncapsulation } from '@angular/core';\nimport { HubMeterBand, HubMeterResolved } from './meter.types';\n\n/**\n * Graded gauge bar following HTML `<meter>` semantics for a scalar measurement\n * within a known range (disk usage, score, capacity…).\n *\n * The filled colour reflects which band the value falls in relative to the\n * `optimum` point: inside the `[low, high]` plateau it uses the optimum fill,\n * below `optimum` and outside the plateau the low fill, above it the high fill.\n * Every band colour derives from a `--hub-meter-*-bg` token so no colour is\n * hard-coded.\n */\n@Component({\n\tselector: 'hub-meter',\n\tstandalone: true,\n\tchangeDetection: ChangeDetectionStrategy.OnPush,\n\ttemplateUrl: './meter.component.html',\n\tstyleUrl: './meter.component.scss',\n\tencapsulation: ViewEncapsulation.None,\n\thost: {\n\t\tclass: 'hub-meter',\n\t\trole: 'meter',\n\t\t'[class]': 'hostClasses()',\n\t\t'[attr.data-band]': 'band()',\n\t\t'[style.--hub-meter-value]': 'valueCss()',\n\t\t'[attr.aria-valuemin]': 'resolved().min',\n\t\t'[attr.aria-valuemax]': 'resolved().max',\n\t\t'[attr.aria-valuenow]': 'resolved().value',\n\t\t'[attr.aria-valuetext]': 'valueText()'\n\t}\n})\nexport class HubMeterComponent {\n\t/** Current measurement, expressed on the `[min, max]` scale. */\n\treadonly value = input<number>(0);\n\n\t/** Lower bound of the scale. */\n\treadonly min = input<number>(0);\n\n\t/** Upper bound of the scale. */\n\treadonly max = input<number>(1);\n\n\t/** Upper limit of the \"low\" region; defaults to {@link min} when omitted. */\n\treadonly low = input<number | undefined>(undefined);\n\n\t/** Lower limit of the \"high\" region; defaults to {@link max} when omitted. */\n\treadonly high = input<number | undefined>(undefined);\n\n\t/** Preferred point of the range; defaults to the midpoint when omitted. */\n\treadonly optimum = input<number | undefined>(undefined);\n\n\t/** Fully resolved, clamped bounds derived from the raw inputs. */\n\tprotected readonly resolved = computed<HubMeterResolved>(() => {\n\t\tconst min = this.min();\n\t\tconst max = Math.max(min, this.max());\n\t\tconst clamp = (candidate: number): number => Math.min(max, Math.max(min, candidate));\n\n\t\tconst value = clamp(this.value());\n\t\tconst low = this.low() === undefined ? min : clamp(this.low() as number);\n\t\tconst high = this.high() === undefined ? max : Math.max(low, clamp(this.high() as number));\n\t\tconst optimum = this.optimum() === undefined ? (min + max) / 2 : clamp(this.optimum() as number);\n\t\tconst span = max - min;\n\t\tconst percent = span <= 0 ? 0 : ((value - min) / span) * 100;\n\n\t\treturn { min, max, value, low, high, optimum, percent };\n\t});\n\n\t/**\n\t * The band the value falls in: `optimum` inside the `[low, high]` plateau,\n\t * otherwise `low`/`high` depending on which side of `optimum` the value sits.\n\t */\n\tprotected readonly band = computed<HubMeterBand>(() => {\n\t\tconst { value, low, high, optimum } = this.resolved();\n\t\tif (value >= low && value <= high) {\n\t\t\treturn 'optimum';\n\t\t}\n\t\treturn value < optimum ? 'low' : 'high';\n\t});\n\n\t/** Fill width as a CSS length consumed by `--hub-meter-value`. */\n\tprotected readonly valueCss = computed(() => `${this.resolved().percent}%`);\n\n\t/** Human-readable `aria-valuetext` (rounded percentage plus band). */\n\tprotected readonly valueText = computed(() => `${Math.round(this.resolved().percent)}% (${this.band()})`);\n\n\t/** Host modifier classes derived from the computed band. */\n\tprotected readonly hostClasses = computed(() => ['hub-meter', `hub-meter--${this.band()}`].join(' '));\n}\n","<span class=\"hub-meter__track\">\n\t<span class=\"hub-meter__indicator\"></span>\n</span>\n","import { booleanAttribute, ChangeDetectionStrategy, Component, computed, input, ViewEncapsulation } from '@angular/core';\nimport { HubRingBand, HubRingThresholds } from './ring.types';\n\n/**\n * Circular gauge (ring) rendering a normalized score as an SVG arc.\n *\n * The value is normalized against `max` (accepting either a `0..1` ratio or a\n * `0..max` figure) and drawn with a `stroke-dasharray`/`stroke-dashoffset` arc\n * over a `pathLength`-normalized circle, so the offset maps linearly to the\n * completion (100 at 0%, 0 at 100%). Optional {@link thresholds} recolour the\n * indicator through the `--hub-ring-low-color` / `--hub-ring-high-color` tokens;\n * a centred caption is projected through `<ng-content>`.\n *\n * @example\n * ```html\n * <hub-ring [value]=\"0.82\" [thresholds]=\"{ low: 0.4, high: 0.75 }\">Score</hub-ring>\n * ```\n */\n@Component({\n\tselector: 'hub-ring',\n\texportAs: 'hubGauge',\n\tstandalone: true,\n\tchangeDetection: ChangeDetectionStrategy.OnPush,\n\ttemplateUrl: './ring.component.html',\n\tstyleUrl: './ring.component.scss',\n\tencapsulation: ViewEncapsulation.None,\n\thost: {\n\t\tclass: 'hub-ring',\n\t\trole: 'img',\n\t\t'[class]': 'hostClasses()',\n\t\t'[style.--hub-ring-size]': 'sizeCss()',\n\t\t'[style.--hub-ring-thickness]': 'thicknessCss()',\n\t\t'[attr.aria-valuemin]': '0',\n\t\t'[attr.aria-valuemax]': 'max()',\n\t\t'[attr.aria-valuenow]': 'value()',\n\t\t'[attr.aria-valuetext]': 'displayValue()',\n\t\t'[attr.aria-label]': 'displayValue()'\n\t}\n})\nexport class HubRingComponent {\n\t/** Score value, expressed as a `0..1` ratio or a `0..max` figure. */\n\treadonly value = input<number>(0);\n\n\t/** Upper bound the {@link value} is normalized against. */\n\treadonly max = input<number>(1);\n\n\t/** Outer diameter of the ring (number → px, or any CSS length string). */\n\treadonly size = input<number | string>('4rem');\n\n\t/** Stroke width of the ring (number → px, or any CSS length string). */\n\treadonly thickness = input<number | string>('0.5rem');\n\n\t/** Optional colour thresholds recolouring the indicator by band. */\n\treadonly thresholds = input<HubRingThresholds | undefined>(undefined);\n\n\t/** Whether the rounded percentage is rendered in the centre. */\n\treadonly showValue = input(true, { transform: booleanAttribute });\n\n\t/** Total normalized path length of the SVG circle (see `pathLength`). */\n\tprotected readonly PATH_LENGTH = 100;\n\n\t/** Completion ratio in `[0, 1]`; `0` when `max` is not positive. */\n\tprotected readonly fraction = computed(() => {\n\t\tconst max = this.max();\n\t\tif (max <= 0) {\n\t\t\treturn 0;\n\t\t}\n\t\treturn Math.min(1, Math.max(0, this.value() / max));\n\t});\n\n\t/** Completion as a `0..100` percentage. */\n\tprotected readonly percent = computed(() => this.fraction() * 100);\n\n\t/** Dash pattern for the indicator (the full normalized path). */\n\tprotected readonly dashArray = computed(() => this.PATH_LENGTH);\n\n\t/** Dash offset drawing the arc: `PATH_LENGTH` at 0%, `0` at 100%. */\n\tprotected readonly dashOffset = computed(() => this.PATH_LENGTH * (1 - this.fraction()));\n\n\t/** Rounded percentage label shown in the centre when {@link showValue} is on. */\n\tprotected readonly displayValue = computed(() => `${Math.round(this.percent())}%`);\n\n\t/** Colour band derived from the optional {@link thresholds} against the value. */\n\tprotected readonly band = computed<HubRingBand>(() => {\n\t\tconst thresholds = this.thresholds();\n\t\tif (!thresholds) {\n\t\t\treturn 'default';\n\t\t}\n\t\tconst value = this.value();\n\t\tif (thresholds.low !== undefined && value < thresholds.low) {\n\t\t\treturn 'low';\n\t\t}\n\t\tif (thresholds.high !== undefined && value >= thresholds.high) {\n\t\t\treturn 'high';\n\t\t}\n\t\treturn 'default';\n\t});\n\n\t/** Host modifier classes derived from the computed band. */\n\tprotected readonly hostClasses = computed(() => ['hub-ring', `hub-ring--${this.band()}`].join(' '));\n\n\t/** Ring diameter as a CSS length (numbers are treated as pixels). */\n\tprotected readonly sizeCss = computed(() => this.toCssLength(this.size()));\n\n\t/** Stroke thickness as a CSS length (numbers are treated as pixels). */\n\tprotected readonly thicknessCss = computed(() => this.toCssLength(this.thickness()));\n\n\t/** Normalizes a number|string dimension into a CSS length string. */\n\tprivate toCssLength(dimension: number | string): string {\n\t\treturn typeof dimension === 'number' ? `${dimension}px` : dimension;\n\t}\n}\n","<svg class=\"hub-ring__svg\" viewBox=\"0 0 100 100\" aria-hidden=\"true\" focusable=\"false\">\n\t<circle class=\"hub-ring__track\" cx=\"50\" cy=\"50\" r=\"44\" [attr.pathLength]=\"PATH_LENGTH\" />\n\t<circle\n\t\tclass=\"hub-ring__indicator\"\n\t\tcx=\"50\"\n\t\tcy=\"50\"\n\t\tr=\"44\"\n\t\t[attr.pathLength]=\"PATH_LENGTH\"\n\t\t[attr.stroke-dasharray]=\"dashArray()\"\n\t\t[attr.stroke-dashoffset]=\"dashOffset()\"\n\t/>\n</svg>\n\n<span class=\"hub-ring__caption\">\n\t@if (showValue()) {\n\t\t<span class=\"hub-ring__value\">{{ displayValue() }}</span>\n\t}\n\t<ng-content />\n</span>\n","/*\n * Public API Surface of ng-hub-ui-metrics\n */\n\n// Components\nexport { HubProgressComponent } from './lib/components/progress/progress.component';\nexport { HubMeterComponent } from './lib/components/meter/meter.component';\nexport { HubRingComponent } from './lib/components/ring/ring.component';\n\n// Types\nexport type { HubMetricsColor, HubMetricsBuiltinColor } from './lib/models/metrics.types';\nexport type { HubProgressSize } from './lib/components/progress/progress.types';\nexport type { HubMeterBand, HubMeterResolved } from './lib/components/meter/meter.types';\nexport type { HubRingBand, HubRingThresholds } from './lib/components/ring/ring.types';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ng-hub-ui-metrics",
|
|
3
|
+
"version": "22.0.0",
|
|
4
|
+
"description": "Read-only value visualizations (progress, meter, gauge/ring) for Angular 21+, part of the ng-hub-ui family.",
|
|
5
|
+
"author": "Carlos Morcillo <carlos.morcillo@me.com> (https://www.carlosmorcillo.com)",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/carlos-morcillo/ng-hub-ui-metrics.git"
|
|
9
|
+
},
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/carlos-morcillo/ng-hub-ui-metrics/issues",
|
|
12
|
+
"email": "carlos.morcillo@me.com"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://hubui.dev/",
|
|
15
|
+
"keywords": [
|
|
16
|
+
"angular",
|
|
17
|
+
"progress",
|
|
18
|
+
"meter",
|
|
19
|
+
"gauge",
|
|
20
|
+
"ring",
|
|
21
|
+
"metrics",
|
|
22
|
+
"ui-component",
|
|
23
|
+
"ng-hub-ui",
|
|
24
|
+
"signals",
|
|
25
|
+
"standalone"
|
|
26
|
+
],
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"@angular/common": ">=21.0.0",
|
|
29
|
+
"@angular/core": ">=21.0.0"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"tslib": "^2.3.0"
|
|
33
|
+
},
|
|
34
|
+
"sideEffects": false,
|
|
35
|
+
"module": "fesm2022/ng-hub-ui-metrics.mjs",
|
|
36
|
+
"typings": "types/ng-hub-ui-metrics.d.ts",
|
|
37
|
+
"exports": {
|
|
38
|
+
"./package.json": {
|
|
39
|
+
"default": "./package.json"
|
|
40
|
+
},
|
|
41
|
+
".": {
|
|
42
|
+
"types": "./types/ng-hub-ui-metrics.d.ts",
|
|
43
|
+
"default": "./fesm2022/ng-hub-ui-metrics.mjs"
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"type": "module"
|
|
47
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// ── ng-hub-ui-metrics public SCSS API ───────────────────────────────────────
|
|
2
|
+
//
|
|
3
|
+
// Import this file to theme the read-only value visualizations in one call:
|
|
4
|
+
//
|
|
5
|
+
// @use 'ng-hub-ui-metrics/styles' as hub;
|
|
6
|
+
//
|
|
7
|
+
// .app-dashboard {
|
|
8
|
+
// @include hub.hub-metrics-theme($accent: var(--hub-sys-color-brand));
|
|
9
|
+
// }
|
|
10
|
+
|
|
11
|
+
@forward 'mixins/metrics-theme';
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
2
|
+
// hub-metrics-theme — one-call theming for the metrics primitives
|
|
3
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
4
|
+
//
|
|
5
|
+
// Override the shared `--hub-progress-*`, `--hub-meter-*` and `--hub-ring-*`
|
|
6
|
+
// tokens in a single include. Every parameter is OPTIONAL and defaults to
|
|
7
|
+
// `null`: only the parameters you pass are emitted as CSS custom properties, so
|
|
8
|
+
// the rest keep each component's own defaults. Token-based and self-contained
|
|
9
|
+
// (no Bootstrap dependency).
|
|
10
|
+
//
|
|
11
|
+
// `$accent` retints the neutral surfaces shared by all three primitives (the
|
|
12
|
+
// progress indicator and the ring indicator); the graded `$low` / `$optimum` /
|
|
13
|
+
// `$high` slots feed the meter bands and the ring thresholds.
|
|
14
|
+
//
|
|
15
|
+
// @param {Color} $accent Shared indicator accent (progress + ring).
|
|
16
|
+
// @param {Color} $track Shared track/background surface.
|
|
17
|
+
// @param {Color} $low Fill for the "below target" band.
|
|
18
|
+
// @param {Color} $optimum Fill for the "on target" band.
|
|
19
|
+
// @param {Color} $high Fill for the "above target" band.
|
|
20
|
+
// @param {Length} $radius Corner radius of the linear tracks.
|
|
21
|
+
//
|
|
22
|
+
// @example
|
|
23
|
+
//
|
|
24
|
+
// @use 'ng-hub-ui-metrics/styles' as hub;
|
|
25
|
+
//
|
|
26
|
+
// .app-panel {
|
|
27
|
+
// @include hub.hub-metrics-theme($accent: var(--hub-sys-color-info), $radius: 0.25rem);
|
|
28
|
+
// }
|
|
29
|
+
//
|
|
30
|
+
// scss-docs-start hub-metrics-theme
|
|
31
|
+
@mixin hub-metrics-theme($accent: null, $track: null, $low: null, $optimum: null, $high: null, $radius: null) {
|
|
32
|
+
@if $accent != null {
|
|
33
|
+
--hub-progress-accent: #{$accent};
|
|
34
|
+
--hub-ring-indicator: #{$accent};
|
|
35
|
+
}
|
|
36
|
+
@if $track != null {
|
|
37
|
+
--hub-progress-track-bg: #{$track};
|
|
38
|
+
--hub-meter-track-bg: #{$track};
|
|
39
|
+
--hub-ring-track: #{$track};
|
|
40
|
+
}
|
|
41
|
+
@if $low != null {
|
|
42
|
+
--hub-meter-low-bg: #{$low};
|
|
43
|
+
--hub-ring-low-color: #{$low};
|
|
44
|
+
}
|
|
45
|
+
@if $optimum != null {
|
|
46
|
+
--hub-meter-optimum-bg: #{$optimum};
|
|
47
|
+
}
|
|
48
|
+
@if $high != null {
|
|
49
|
+
--hub-meter-high-bg: #{$high};
|
|
50
|
+
--hub-ring-high-color: #{$high};
|
|
51
|
+
}
|
|
52
|
+
@if $radius != null {
|
|
53
|
+
--hub-progress-radius: #{$radius};
|
|
54
|
+
--hub-meter-radius: #{$radius};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// scss-docs-end hub-metrics-theme
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import * as _angular_core from '@angular/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Built-in semantic colour families shared by the metrics primitives, backed by
|
|
5
|
+
* the design-system `--hub-sys-color-*` tokens.
|
|
6
|
+
*
|
|
7
|
+
* The list mirrors the canonical accents exposed by the ng-hub-ui design system
|
|
8
|
+
* (`primary, secondary, success, danger, warning, info` plus the neutral grey),
|
|
9
|
+
* so the type documents exactly the hues that work out of the box.
|
|
10
|
+
*/
|
|
11
|
+
type HubMetricsBuiltinColor = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'neutral';
|
|
12
|
+
/**
|
|
13
|
+
* Semantic colour name accepted by the metrics primitives.
|
|
14
|
+
*
|
|
15
|
+
* The open string branch lets host applications point a component at any custom
|
|
16
|
+
* semantic colour registered through the `--hub-sys-color-<name>` token family.
|
|
17
|
+
*/
|
|
18
|
+
type HubMetricsColor = HubMetricsBuiltinColor | (string & {});
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Size scale exposed by `hub-progress`, controlling the bar thickness.
|
|
22
|
+
*/
|
|
23
|
+
type HubProgressSize = 'sm' | 'md' | 'lg';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Linear progress bar for a determinate or indeterminate read-only value.
|
|
27
|
+
*
|
|
28
|
+
* The component owns no hard-coded colour values: the semantic `color` input
|
|
29
|
+
* maps to the host application's `--hub-sys-color-*` token family and drives the
|
|
30
|
+
* indicator through the local `--hub-progress-accent` slot. When
|
|
31
|
+
* {@link indeterminate} is set the bar loops a looping animation and drops
|
|
32
|
+
* `aria-valuenow`, matching the ARIA `progressbar` contract for an unknown value.
|
|
33
|
+
*/
|
|
34
|
+
declare class HubProgressComponent {
|
|
35
|
+
/** Current progress value, expressed on the `[0, max]` scale. */
|
|
36
|
+
readonly value: _angular_core.InputSignal<number>;
|
|
37
|
+
/** Upper bound of the progress scale. */
|
|
38
|
+
readonly max: _angular_core.InputSignal<number>;
|
|
39
|
+
/** Renders a looping bar for work of unknown duration; drops `aria-valuenow`. */
|
|
40
|
+
readonly indeterminate: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
41
|
+
/** Semantic accent driving the indicator colour. */
|
|
42
|
+
readonly color: _angular_core.InputSignal<HubMetricsColor>;
|
|
43
|
+
/** Size token controlling the bar thickness. */
|
|
44
|
+
readonly size: _angular_core.InputSignal<HubProgressSize>;
|
|
45
|
+
/** Whether the rounded percentage is rendered next to the bar. */
|
|
46
|
+
readonly showValue: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
47
|
+
/** Accessible label describing what the progress bar measures. */
|
|
48
|
+
readonly label: _angular_core.InputSignal<string>;
|
|
49
|
+
/** Value clamped to the `[0, max]` range; `0` when `max` is not positive. */
|
|
50
|
+
protected readonly clampedValue: _angular_core.Signal<number>;
|
|
51
|
+
/** Completion ratio as a `0..100` percentage; `0` while indeterminate. */
|
|
52
|
+
protected readonly percent: _angular_core.Signal<number>;
|
|
53
|
+
/** Indicator width as a CSS length consumed by `--hub-progress-value`. */
|
|
54
|
+
protected readonly valueCss: _angular_core.Signal<string>;
|
|
55
|
+
/** Rounded percentage label shown when {@link showValue} is enabled. */
|
|
56
|
+
protected readonly displayValue: _angular_core.Signal<string>;
|
|
57
|
+
/** `aria-valuenow`, omitted (null) while the bar is {@link indeterminate}. */
|
|
58
|
+
protected readonly ariaValueNow: _angular_core.Signal<number | null>;
|
|
59
|
+
/** Local accent slot resolved from the semantic {@link color} input. */
|
|
60
|
+
protected readonly accentVar: _angular_core.Signal<string>;
|
|
61
|
+
/** Host modifier classes derived from the signal inputs. */
|
|
62
|
+
protected readonly hostClasses: _angular_core.Signal<string>;
|
|
63
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<HubProgressComponent, never>;
|
|
64
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<HubProgressComponent, "hub-progress", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "indeterminate": { "alias": "indeterminate"; "required": false; "isSignal": true; }; "color": { "alias": "color"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "showValue": { "alias": "showValue"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Band a `hub-meter` value falls into, following HTML `<meter>` grading:
|
|
69
|
+
*
|
|
70
|
+
* - `low` — the value sits below the acceptable plateau (on the far side of
|
|
71
|
+
* `optimum`); rendered with `--hub-meter-low-bg`.
|
|
72
|
+
* - `optimum` — the value sits inside the acceptable `[low, high]` plateau;
|
|
73
|
+
* rendered with `--hub-meter-optimum-bg`.
|
|
74
|
+
* - `high` — the value sits above the acceptable plateau; rendered with
|
|
75
|
+
* `--hub-meter-high-bg`.
|
|
76
|
+
*/
|
|
77
|
+
type HubMeterBand = 'low' | 'optimum' | 'high';
|
|
78
|
+
/**
|
|
79
|
+
* Fully resolved, clamped meter bounds derived from the raw inputs.
|
|
80
|
+
*/
|
|
81
|
+
interface HubMeterResolved {
|
|
82
|
+
/** Lower bound of the scale. */
|
|
83
|
+
min: number;
|
|
84
|
+
/** Upper bound of the scale. */
|
|
85
|
+
max: number;
|
|
86
|
+
/** Value clamped into `[min, max]`. */
|
|
87
|
+
value: number;
|
|
88
|
+
/** Lower threshold, clamped into `[min, max]` (defaults to `min`). */
|
|
89
|
+
low: number;
|
|
90
|
+
/** Upper threshold, clamped into `[low, max]` (defaults to `max`). */
|
|
91
|
+
high: number;
|
|
92
|
+
/** Optimum point, clamped into `[min, max]` (defaults to the midpoint). */
|
|
93
|
+
optimum: number;
|
|
94
|
+
/** Fill ratio as a `0..100` percentage. */
|
|
95
|
+
percent: number;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Graded gauge bar following HTML `<meter>` semantics for a scalar measurement
|
|
100
|
+
* within a known range (disk usage, score, capacity…).
|
|
101
|
+
*
|
|
102
|
+
* The filled colour reflects which band the value falls in relative to the
|
|
103
|
+
* `optimum` point: inside the `[low, high]` plateau it uses the optimum fill,
|
|
104
|
+
* below `optimum` and outside the plateau the low fill, above it the high fill.
|
|
105
|
+
* Every band colour derives from a `--hub-meter-*-bg` token so no colour is
|
|
106
|
+
* hard-coded.
|
|
107
|
+
*/
|
|
108
|
+
declare class HubMeterComponent {
|
|
109
|
+
/** Current measurement, expressed on the `[min, max]` scale. */
|
|
110
|
+
readonly value: _angular_core.InputSignal<number>;
|
|
111
|
+
/** Lower bound of the scale. */
|
|
112
|
+
readonly min: _angular_core.InputSignal<number>;
|
|
113
|
+
/** Upper bound of the scale. */
|
|
114
|
+
readonly max: _angular_core.InputSignal<number>;
|
|
115
|
+
/** Upper limit of the "low" region; defaults to {@link min} when omitted. */
|
|
116
|
+
readonly low: _angular_core.InputSignal<number | undefined>;
|
|
117
|
+
/** Lower limit of the "high" region; defaults to {@link max} when omitted. */
|
|
118
|
+
readonly high: _angular_core.InputSignal<number | undefined>;
|
|
119
|
+
/** Preferred point of the range; defaults to the midpoint when omitted. */
|
|
120
|
+
readonly optimum: _angular_core.InputSignal<number | undefined>;
|
|
121
|
+
/** Fully resolved, clamped bounds derived from the raw inputs. */
|
|
122
|
+
protected readonly resolved: _angular_core.Signal<HubMeterResolved>;
|
|
123
|
+
/**
|
|
124
|
+
* The band the value falls in: `optimum` inside the `[low, high]` plateau,
|
|
125
|
+
* otherwise `low`/`high` depending on which side of `optimum` the value sits.
|
|
126
|
+
*/
|
|
127
|
+
protected readonly band: _angular_core.Signal<HubMeterBand>;
|
|
128
|
+
/** Fill width as a CSS length consumed by `--hub-meter-value`. */
|
|
129
|
+
protected readonly valueCss: _angular_core.Signal<string>;
|
|
130
|
+
/** Human-readable `aria-valuetext` (rounded percentage plus band). */
|
|
131
|
+
protected readonly valueText: _angular_core.Signal<string>;
|
|
132
|
+
/** Host modifier classes derived from the computed band. */
|
|
133
|
+
protected readonly hostClasses: _angular_core.Signal<string>;
|
|
134
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<HubMeterComponent, never>;
|
|
135
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<HubMeterComponent, "hub-meter", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "low": { "alias": "low"; "required": false; "isSignal": true; }; "high": { "alias": "high"; "required": false; "isSignal": true; }; "optimum": { "alias": "optimum"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Optional colour thresholds for `hub-ring`, expressed in the same units as the
|
|
140
|
+
* ring's `value` input.
|
|
141
|
+
*
|
|
142
|
+
* When the value drops below `low` the ring paints with `--hub-ring-low-color`;
|
|
143
|
+
* when it reaches `high` it paints with `--hub-ring-high-color`; otherwise it
|
|
144
|
+
* keeps the neutral `--hub-ring-indicator` colour.
|
|
145
|
+
*/
|
|
146
|
+
interface HubRingThresholds {
|
|
147
|
+
/** Value at or below which the ring is treated as "low". */
|
|
148
|
+
low?: number;
|
|
149
|
+
/** Value at or above which the ring is treated as "high". */
|
|
150
|
+
high?: number;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Colour band a `hub-ring` value falls into, driving the indicator stroke.
|
|
154
|
+
*/
|
|
155
|
+
type HubRingBand = 'low' | 'default' | 'high';
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Circular gauge (ring) rendering a normalized score as an SVG arc.
|
|
159
|
+
*
|
|
160
|
+
* The value is normalized against `max` (accepting either a `0..1` ratio or a
|
|
161
|
+
* `0..max` figure) and drawn with a `stroke-dasharray`/`stroke-dashoffset` arc
|
|
162
|
+
* over a `pathLength`-normalized circle, so the offset maps linearly to the
|
|
163
|
+
* completion (100 at 0%, 0 at 100%). Optional {@link thresholds} recolour the
|
|
164
|
+
* indicator through the `--hub-ring-low-color` / `--hub-ring-high-color` tokens;
|
|
165
|
+
* a centred caption is projected through `<ng-content>`.
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```html
|
|
169
|
+
* <hub-ring [value]="0.82" [thresholds]="{ low: 0.4, high: 0.75 }">Score</hub-ring>
|
|
170
|
+
* ```
|
|
171
|
+
*/
|
|
172
|
+
declare class HubRingComponent {
|
|
173
|
+
/** Score value, expressed as a `0..1` ratio or a `0..max` figure. */
|
|
174
|
+
readonly value: _angular_core.InputSignal<number>;
|
|
175
|
+
/** Upper bound the {@link value} is normalized against. */
|
|
176
|
+
readonly max: _angular_core.InputSignal<number>;
|
|
177
|
+
/** Outer diameter of the ring (number → px, or any CSS length string). */
|
|
178
|
+
readonly size: _angular_core.InputSignal<string | number>;
|
|
179
|
+
/** Stroke width of the ring (number → px, or any CSS length string). */
|
|
180
|
+
readonly thickness: _angular_core.InputSignal<string | number>;
|
|
181
|
+
/** Optional colour thresholds recolouring the indicator by band. */
|
|
182
|
+
readonly thresholds: _angular_core.InputSignal<HubRingThresholds | undefined>;
|
|
183
|
+
/** Whether the rounded percentage is rendered in the centre. */
|
|
184
|
+
readonly showValue: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
185
|
+
/** Total normalized path length of the SVG circle (see `pathLength`). */
|
|
186
|
+
protected readonly PATH_LENGTH = 100;
|
|
187
|
+
/** Completion ratio in `[0, 1]`; `0` when `max` is not positive. */
|
|
188
|
+
protected readonly fraction: _angular_core.Signal<number>;
|
|
189
|
+
/** Completion as a `0..100` percentage. */
|
|
190
|
+
protected readonly percent: _angular_core.Signal<number>;
|
|
191
|
+
/** Dash pattern for the indicator (the full normalized path). */
|
|
192
|
+
protected readonly dashArray: _angular_core.Signal<number>;
|
|
193
|
+
/** Dash offset drawing the arc: `PATH_LENGTH` at 0%, `0` at 100%. */
|
|
194
|
+
protected readonly dashOffset: _angular_core.Signal<number>;
|
|
195
|
+
/** Rounded percentage label shown in the centre when {@link showValue} is on. */
|
|
196
|
+
protected readonly displayValue: _angular_core.Signal<string>;
|
|
197
|
+
/** Colour band derived from the optional {@link thresholds} against the value. */
|
|
198
|
+
protected readonly band: _angular_core.Signal<HubRingBand>;
|
|
199
|
+
/** Host modifier classes derived from the computed band. */
|
|
200
|
+
protected readonly hostClasses: _angular_core.Signal<string>;
|
|
201
|
+
/** Ring diameter as a CSS length (numbers are treated as pixels). */
|
|
202
|
+
protected readonly sizeCss: _angular_core.Signal<string>;
|
|
203
|
+
/** Stroke thickness as a CSS length (numbers are treated as pixels). */
|
|
204
|
+
protected readonly thicknessCss: _angular_core.Signal<string>;
|
|
205
|
+
/** Normalizes a number|string dimension into a CSS length string. */
|
|
206
|
+
private toCssLength;
|
|
207
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<HubRingComponent, never>;
|
|
208
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<HubRingComponent, "hub-ring", ["hubGauge"], { "value": { "alias": "value"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "thickness": { "alias": "thickness"; "required": false; "isSignal": true; }; "thresholds": { "alias": "thresholds"; "required": false; "isSignal": true; }; "showValue": { "alias": "showValue"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export { HubMeterComponent, HubProgressComponent, HubRingComponent };
|
|
212
|
+
export type { HubMeterBand, HubMeterResolved, HubMetricsBuiltinColor, HubMetricsColor, HubProgressSize, HubRingBand, HubRingThresholds };
|