ng-hub-ui-metrics 22.2.4 → 22.4.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 +14 -7
- package/fesm2022/ng-hub-ui-metrics.mjs +52 -21
- package/fesm2022/ng-hub-ui-metrics.mjs.map +1 -1
- package/package.json +7 -1
- package/types/ng-hub-ui-metrics.d.ts +37 -12
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
[](https://angular.dev)
|
|
7
7
|
[](LICENSE)
|
|
8
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.
|
|
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. Its only runtime dependency is `ng-hub-ui-utils` (a required peer, where the shared accent resolver lives); every colour and dimension is a `--hub-*` CSS custom property derived from the shared design-system tokens.
|
|
10
10
|
|
|
11
11
|
## Documentation and Live Examples
|
|
12
12
|
|
|
@@ -49,9 +49,14 @@ This library is part of the **ng-hub-ui** ecosystem:
|
|
|
49
49
|
### 1. Install
|
|
50
50
|
|
|
51
51
|
```bash
|
|
52
|
-
npm install ng-hub-ui-metrics
|
|
52
|
+
npm install ng-hub-ui-metrics ng-hub-ui-utils
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
+
> **`ng-hub-ui-utils` is a required peer dependency** (`>=22.7.0`): `<hub-progress>`
|
|
56
|
+
> resolves its `color` input through the shared `resolveHubAccent` helper that lives
|
|
57
|
+
> there. Installing `ng-hub-ui-metrics` alone leaves an unresolved import. `ng add ng-hub-ui`
|
|
58
|
+
> pulls it in for you.
|
|
59
|
+
|
|
55
60
|
> **Theming (recommended):** install the shared design tokens so the metrics —
|
|
56
61
|
> and every other ng-hub-ui library — read the same palette and dark-mode colours:
|
|
57
62
|
>
|
|
@@ -124,6 +129,7 @@ the value falls in. Host role `meter`.
|
|
|
124
129
|
| `low` | `number \| undefined` | `undefined` | Upper limit of the "low" region (defaults to `min`). |
|
|
125
130
|
| `high` | `number \| undefined` | `undefined` | Lower limit of the "high" region (defaults to `max`). |
|
|
126
131
|
| `optimum` | `number \| undefined` | `undefined` | Preferred point (defaults to the midpoint). |
|
|
132
|
+
| `label` | `string` | `''` | Accessible label (`aria-label`). `role="meter"` is named by the author only, so set it. |
|
|
127
133
|
|
|
128
134
|
The computed band is exposed as `data-band` (`low` / `optimum` / `high`) and
|
|
129
135
|
maps to `--hub-meter-low-bg` / `--hub-meter-optimum-bg` / `--hub-meter-high-bg`.
|
|
@@ -137,19 +143,19 @@ projected via `<ng-content>`. Host role `meter`.
|
|
|
137
143
|
|---|---|---|---|
|
|
138
144
|
| `value` | `number` | `0` | Score as a `0..1` ratio or a `0..max` figure. |
|
|
139
145
|
| `max` | `number` | `1` | Value is normalized against this. |
|
|
140
|
-
| `size` | `number \| string` | `
|
|
141
|
-
| `thickness` | `number \| string` | `
|
|
146
|
+
| `size` | `number \| string \| undefined` | `undefined` | Outer diameter (number → px), applied inline when set. Omit it to let the `--hub-ring-size` token drive the diameter — it defaults to `4rem`. |
|
|
147
|
+
| `thickness` | `number \| string \| undefined` | `undefined` | Stroke width (number → px), applied inline when set. Omit it to let the `--hub-ring-thickness` token drive the stroke — it defaults to `0.5rem`. |
|
|
142
148
|
| `thresholds` | `{ low?: number; high?: number }` | `undefined` | Recolours the arc by band. |
|
|
143
149
|
| `showValue` | `boolean` | `true` | Render the rounded percentage in the centre. |
|
|
150
|
+
| `label` | `string` | `''` | Accessible label (`aria-label`). Neither the caption nor the percentage can name a `role="meter"`, so set it. |
|
|
144
151
|
|
|
145
152
|
---
|
|
146
153
|
|
|
147
154
|
## 🎨 Styling
|
|
148
155
|
|
|
149
156
|
Every visual detail is a `--hub-*` CSS custom property. Each component declares
|
|
150
|
-
its defaults on its own element (`:where(
|
|
151
|
-
|
|
152
|
-
from a bare ancestor. Set the tokens on the component element, or on a wrapper that
|
|
157
|
+
its defaults on its own host element, at zero specificity (`:where(:host)`), so a
|
|
158
|
+
value set **on the element** wins over one inherited from a bare ancestor. Set the tokens on the component element, or on a wrapper that
|
|
153
159
|
*targets the components as descendants* (`.wrapper :where(.hub-ring) { … }`) — which
|
|
154
160
|
is exactly what the `hub-metrics-theme()` mixin emits. For `<hub-progress>` prefer the
|
|
155
161
|
per-instance `color` input for one-off semantic tints.
|
|
@@ -158,6 +164,7 @@ per-instance `color` input for one-off semantic tints.
|
|
|
158
164
|
|
|
159
165
|
| Token | Default | Description |
|
|
160
166
|
|---|---|---|
|
|
167
|
+
| `--hub-progress-accent` | `--hub-sys-color-primary` | Root accent the other slots derive from; what the `color` input and the mixin's `$accent` write. |
|
|
161
168
|
| `--hub-progress-track-bg` | tint of the accent | Track background. |
|
|
162
169
|
| `--hub-progress-indicator-bg` | `--hub-progress-accent` | Filled indicator colour. |
|
|
163
170
|
| `--hub-progress-height` | `0.5rem` | Bar thickness. |
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, booleanAttribute, computed,
|
|
2
|
+
import { input, booleanAttribute, computed, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
3
|
import { resolveHubAccent } from 'ng-hub-ui-utils';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -82,11 +82,11 @@ class HubProgressComponent {
|
|
|
82
82
|
.join(' '), /* @ts-ignore */
|
|
83
83
|
...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
84
84
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: HubProgressComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
85
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", 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(
|
|
85
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", 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(:host){--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)}:host{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}:host(.hub-progress--sm){--hub-progress-height: var(--hub-ref-space-1, .25rem)}:host(.hub-progress--md){--hub-progress-height: var(--hub-ref-space-2, .5rem)}:host(.hub-progress--lg){--hub-progress-height: var(--hub-ref-space-3, .75rem)}:host(.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){:host(.hub-progress--indeterminate) .hub-progress__indicator{animation-duration:3s}.hub-progress__indicator{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
86
86
|
}
|
|
87
87
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: HubProgressComponent, decorators: [{
|
|
88
88
|
type: Component,
|
|
89
|
-
args: [{ selector: 'hub-progress', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush,
|
|
89
|
+
args: [{ selector: 'hub-progress', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
90
90
|
class: 'hub-progress',
|
|
91
91
|
role: 'progressbar',
|
|
92
92
|
'[class]': 'hostClasses()',
|
|
@@ -97,7 +97,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
97
97
|
'[attr.aria-valuenow]': 'ariaValueNow()',
|
|
98
98
|
'[attr.aria-label]': 'label() || null',
|
|
99
99
|
'[attr.aria-busy]': 'indeterminate() || null'
|
|
100
|
-
}, 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(
|
|
100
|
+
}, 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(:host){--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)}:host{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}:host(.hub-progress--sm){--hub-progress-height: var(--hub-ref-space-1, .25rem)}:host(.hub-progress--md){--hub-progress-height: var(--hub-ref-space-2, .5rem)}:host(.hub-progress--lg){--hub-progress-height: var(--hub-ref-space-3, .75rem)}:host(.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){:host(.hub-progress--indeterminate) .hub-progress__indicator{animation-duration:3s}.hub-progress__indicator{transition:none}}\n"] }]
|
|
101
101
|
}], 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 }] }] } });
|
|
102
102
|
|
|
103
103
|
/**
|
|
@@ -129,6 +129,13 @@ class HubMeterComponent {
|
|
|
129
129
|
/** Preferred point of the range; defaults to the midpoint when omitted. */
|
|
130
130
|
optimum = input(undefined, /* @ts-ignore */
|
|
131
131
|
...(ngDevMode ? [{ debugName: "optimum" }] : /* istanbul ignore next */ []));
|
|
132
|
+
/**
|
|
133
|
+
* Accessible label describing what is being measured. `role="meter"` takes its
|
|
134
|
+
* name from the author only, so without it the gauge reaches assistive
|
|
135
|
+
* technology unnamed — the component renders no text of its own.
|
|
136
|
+
*/
|
|
137
|
+
label = input('', /* @ts-ignore */
|
|
138
|
+
...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
132
139
|
/** Fully resolved, clamped bounds derived from the raw inputs. */
|
|
133
140
|
resolved = computed(() => {
|
|
134
141
|
const min = this.min();
|
|
@@ -165,11 +172,11 @@ class HubMeterComponent {
|
|
|
165
172
|
hostClasses = computed(() => ['hub-meter', `hub-meter--${this.band()}`].join(' '), /* @ts-ignore */
|
|
166
173
|
...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
167
174
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: HubMeterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
168
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.8", 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(
|
|
175
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.8", 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 }, label: { classPropertyName: "label", publicName: "label", 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()", "attr.aria-label": "label() || null" }, classAttribute: "hub-meter" }, ngImport: i0, template: "<span class=\"hub-meter__track\">\n\t<span class=\"hub-meter__indicator\"></span>\n</span>\n", styles: [":where(:host){--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)}:host{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}:host(.hub-meter--low){--hub-meter-fill: var(--hub-meter-low-bg)}:host(.hub-meter--optimum){--hub-meter-fill: var(--hub-meter-optimum-bg)}:host(.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 });
|
|
169
176
|
}
|
|
170
177
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: HubMeterComponent, decorators: [{
|
|
171
178
|
type: Component,
|
|
172
|
-
args: [{ selector: 'hub-meter', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush,
|
|
179
|
+
args: [{ selector: 'hub-meter', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
173
180
|
class: 'hub-meter',
|
|
174
181
|
role: 'meter',
|
|
175
182
|
'[class]': 'hostClasses()',
|
|
@@ -178,9 +185,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
178
185
|
'[attr.aria-valuemin]': 'resolved().min',
|
|
179
186
|
'[attr.aria-valuemax]': 'resolved().max',
|
|
180
187
|
'[attr.aria-valuenow]': 'resolved().value',
|
|
181
|
-
'[attr.aria-valuetext]': 'valueText()'
|
|
182
|
-
|
|
183
|
-
|
|
188
|
+
'[attr.aria-valuetext]': 'valueText()',
|
|
189
|
+
'[attr.aria-label]': 'label() || null'
|
|
190
|
+
}, template: "<span class=\"hub-meter__track\">\n\t<span class=\"hub-meter__indicator\"></span>\n</span>\n", styles: [":where(:host){--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)}:host{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}:host(.hub-meter--low){--hub-meter-fill: var(--hub-meter-low-bg)}:host(.hub-meter--optimum){--hub-meter-fill: var(--hub-meter-optimum-bg)}:host(.hub-meter--high){--hub-meter-fill: var(--hub-meter-high-bg)}@media(prefers-reduced-motion:reduce){.hub-meter__indicator{transition:none}}\n"] }]
|
|
191
|
+
}], 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 }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }] } });
|
|
184
192
|
|
|
185
193
|
/**
|
|
186
194
|
* Circular gauge (ring) rendering a normalized score as an SVG arc.
|
|
@@ -190,11 +198,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
190
198
|
* over a `pathLength`-normalized circle, so the offset maps linearly to the
|
|
191
199
|
* completion (100 at 0%, 0 at 100%). Optional {@link thresholds} recolour the
|
|
192
200
|
* indicator through the `--hub-ring-low-color` / `--hub-ring-high-color` tokens;
|
|
193
|
-
* a centred caption is projected through `<ng-content>`.
|
|
201
|
+
* a centred caption is projected through `<ng-content>`. That caption is decoration:
|
|
202
|
+
* `role="meter"` is named by the author, so pass {@link label} to name the gauge.
|
|
194
203
|
*
|
|
195
204
|
* @example
|
|
196
205
|
* ```html
|
|
197
|
-
* <hub-ring [value]="0.82" [thresholds]="{ low: 0.4, high: 0.75 }">Score</hub-ring>
|
|
206
|
+
* <hub-ring [value]="0.82" [thresholds]="{ low: 0.4, high: 0.75 }" label="Quality score">Score</hub-ring>
|
|
198
207
|
* ```
|
|
199
208
|
*/
|
|
200
209
|
class HubRingComponent {
|
|
@@ -204,17 +213,32 @@ class HubRingComponent {
|
|
|
204
213
|
/** Upper bound the {@link value} is normalized against. */
|
|
205
214
|
max = input(1, /* @ts-ignore */
|
|
206
215
|
...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
|
|
207
|
-
/**
|
|
208
|
-
|
|
216
|
+
/**
|
|
217
|
+
* Outer diameter of the ring (number → px, or any CSS length string), applied
|
|
218
|
+
* inline as a per-instance override. Omit it to let the `--hub-ring-size`
|
|
219
|
+
* token (default or theme override) drive the diameter.
|
|
220
|
+
*/
|
|
221
|
+
size = input(undefined, /* @ts-ignore */
|
|
209
222
|
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
210
|
-
/**
|
|
211
|
-
|
|
223
|
+
/**
|
|
224
|
+
* Stroke width of the ring (number → px, or any CSS length string), applied
|
|
225
|
+
* inline as a per-instance override. Omit it to let the
|
|
226
|
+
* `--hub-ring-thickness` token (default or theme override) drive the stroke.
|
|
227
|
+
*/
|
|
228
|
+
thickness = input(undefined, /* @ts-ignore */
|
|
212
229
|
...(ngDevMode ? [{ debugName: "thickness" }] : /* istanbul ignore next */ []));
|
|
213
230
|
/** Optional colour thresholds recolouring the indicator by band. */
|
|
214
231
|
thresholds = input(undefined, /* @ts-ignore */
|
|
215
232
|
...(ngDevMode ? [{ debugName: "thresholds" }] : /* istanbul ignore next */ []));
|
|
216
233
|
/** Whether the rounded percentage is rendered in the centre. */
|
|
217
234
|
showValue = input(true, { ...(ngDevMode ? { debugName: "showValue" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
235
|
+
/**
|
|
236
|
+
* Accessible label describing what the ring scores. `role="meter"` takes its
|
|
237
|
+
* name from the author only, so neither the projected caption nor the centred
|
|
238
|
+
* percentage can name the gauge — this input is the only way to do it.
|
|
239
|
+
*/
|
|
240
|
+
label = input('', /* @ts-ignore */
|
|
241
|
+
...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
218
242
|
/** Total normalized path length of the SVG circle (see `pathLength`). */
|
|
219
243
|
PATH_LENGTH = 100;
|
|
220
244
|
/** Completion ratio in `[0, 1]`; `0` when `max` is not positive. */
|
|
@@ -263,16 +287,23 @@ class HubRingComponent {
|
|
|
263
287
|
/** Stroke thickness as a CSS length (numbers are treated as pixels). */
|
|
264
288
|
thicknessCss = computed(() => this.toCssLength(this.thickness()), /* @ts-ignore */
|
|
265
289
|
...(ngDevMode ? [{ debugName: "thicknessCss" }] : /* istanbul ignore next */ []));
|
|
266
|
-
/**
|
|
290
|
+
/**
|
|
291
|
+
* Normalizes a number|string dimension into a CSS length string, returning
|
|
292
|
+
* `null` when the input is unset so the inline binding is dropped altogether
|
|
293
|
+
* and the stylesheet token wins the cascade instead of being shadowed.
|
|
294
|
+
*/
|
|
267
295
|
toCssLength(dimension) {
|
|
296
|
+
if (dimension === undefined) {
|
|
297
|
+
return null;
|
|
298
|
+
}
|
|
268
299
|
return typeof dimension === 'number' ? `${dimension}px` : dimension;
|
|
269
300
|
}
|
|
270
301
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: HubRingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
271
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", 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": "meter" }, 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": "
|
|
302
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", 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 }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "meter" }, 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": "label() || null" }, 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(:host){--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)}:host{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}:host(.hub-ring--low){--hub-ring-indicator: var(--hub-ring-low-color)}:host(.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 });
|
|
272
303
|
}
|
|
273
304
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: HubRingComponent, decorators: [{
|
|
274
305
|
type: Component,
|
|
275
|
-
args: [{ selector: 'hub-ring', exportAs: 'hubGauge', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush,
|
|
306
|
+
args: [{ selector: 'hub-ring', exportAs: 'hubGauge', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
276
307
|
class: 'hub-ring',
|
|
277
308
|
role: 'meter',
|
|
278
309
|
'[class]': 'hostClasses()',
|
|
@@ -282,9 +313,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
282
313
|
'[attr.aria-valuemax]': 'max()',
|
|
283
314
|
'[attr.aria-valuenow]': 'value()',
|
|
284
315
|
'[attr.aria-valuetext]': 'displayValue()',
|
|
285
|
-
'[attr.aria-label]': '
|
|
286
|
-
}, 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(
|
|
287
|
-
}], 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 }] }] } });
|
|
316
|
+
'[attr.aria-label]': 'label() || null'
|
|
317
|
+
}, 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(:host){--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)}:host{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}:host(.hub-ring--low){--hub-ring-indicator: var(--hub-ring-low-color)}:host(.hub-ring--high){--hub-ring-indicator: var(--hub-ring-high-color)}@media(prefers-reduced-motion:reduce){.hub-ring__indicator{transition:none}}\n"] }]
|
|
318
|
+
}], 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 }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }] } });
|
|
288
319
|
|
|
289
320
|
/*
|
|
290
321
|
* Public API Surface of ng-hub-ui-metrics
|
|
@@ -1 +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 { resolveHubAccent } from 'ng-hub-ui-utils';\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/**\n\t * Optional accent driving the indicator colour. Accepts any colour: a bareword\n\t * (semantic name, registered accent or CSS named colour) maps to\n\t * `--hub-sys-color-<color>` with the word itself as the raw fallback, while a\n\t * literal (`#hex`, `rgb()`, `oklch()`, `var()`…) is passed through unchanged.\n\t * The resolved value is applied inline (a per-instance override); when omitted\n\t * the accent falls back to the `--hub-progress-accent` token, so a theme\n\t * (`hub-metrics-theme` mixin / ancestor override) can drive it instead.\n\t */\n\treadonly color = input<HubMetricsColor | undefined>(undefined);\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/**\n\t * Local accent slot resolved from the {@link color} input. A bareword resolves\n\t * to `var(--hub-sys-color-<color>, <color>)` — the ds token with the word as a\n\t * raw fallback — while a literal colour (`#hex`, `rgb()`, `oklch()`, `var()`…)\n\t * is passed through unchanged. Returns `null` when no colour is set so the\n\t * inline binding is dropped and the `--hub-progress-accent` token (default or\n\t * theme override) takes over.\n\t */\n\tprotected readonly accentVar = computed(() => resolveHubAccent(this.color()));\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: 'meter',\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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"}
|
|
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 } from '@angular/core';\nimport { HubMetricsColor } from '../../models/metrics.types';\nimport { resolveHubAccent } from 'ng-hub-ui-utils';\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\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/**\n\t * Optional accent driving the indicator colour. Accepts any colour: a bareword\n\t * (semantic name, registered accent or CSS named colour) maps to\n\t * `--hub-sys-color-<color>` with the word itself as the raw fallback, while a\n\t * literal (`#hex`, `rgb()`, `oklch()`, `var()`…) is passed through unchanged.\n\t * The resolved value is applied inline (a per-instance override); when omitted\n\t * the accent falls back to the `--hub-progress-accent` token, so a theme\n\t * (`hub-metrics-theme` mixin / ancestor override) can drive it instead.\n\t */\n\treadonly color = input<HubMetricsColor | undefined>(undefined);\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/**\n\t * Local accent slot resolved from the {@link color} input. A bareword resolves\n\t * to `var(--hub-sys-color-<color>, <color>)` — the ds token with the word as a\n\t * raw fallback — while a literal colour (`#hex`, `rgb()`, `oklch()`, `var()`…)\n\t * is passed through unchanged. Returns `null` when no colour is set so the\n\t * inline binding is dropped and the `--hub-progress-accent` token (default or\n\t * theme override) takes over.\n\t */\n\tprotected readonly accentVar = computed(() => resolveHubAccent(this.color()));\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 } 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\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\t'[attr.aria-label]': 'label() || null'\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/**\n\t * Accessible label describing what is being measured. `role=\"meter\"` takes its\n\t * name from the author only, so without it the gauge reaches assistive\n\t * technology unnamed — the component renders no text of its own.\n\t */\n\treadonly label = input<string>('');\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 } 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>`. That caption is decoration:\n * `role=\"meter\"` is named by the author, so pass {@link label} to name the gauge.\n *\n * @example\n * ```html\n * <hub-ring [value]=\"0.82\" [thresholds]=\"{ low: 0.4, high: 0.75 }\" label=\"Quality score\">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\thost: {\n\t\tclass: 'hub-ring',\n\t\trole: 'meter',\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]': 'label() || null'\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/**\n\t * Outer diameter of the ring (number → px, or any CSS length string), applied\n\t * inline as a per-instance override. Omit it to let the `--hub-ring-size`\n\t * token (default or theme override) drive the diameter.\n\t */\n\treadonly size = input<number | string | undefined>(undefined);\n\n\t/**\n\t * Stroke width of the ring (number → px, or any CSS length string), applied\n\t * inline as a per-instance override. Omit it to let the\n\t * `--hub-ring-thickness` token (default or theme override) drive the stroke.\n\t */\n\treadonly thickness = input<number | string | undefined>(undefined);\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/**\n\t * Accessible label describing what the ring scores. `role=\"meter\"` takes its\n\t * name from the author only, so neither the projected caption nor the centred\n\t * percentage can name the gauge — this input is the only way to do it.\n\t */\n\treadonly label = input<string>('');\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/**\n\t * Normalizes a number|string dimension into a CSS length string, returning\n\t * `null` when the input is unset so the inline binding is dropped altogether\n\t * and the stylesheet token wins the cascade instead of being shadowed.\n\t */\n\tprivate toCssLength(dimension: number | string | undefined): string | null {\n\t\tif (dimension === undefined) {\n\t\t\treturn null;\n\t\t}\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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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ng-hub-ui-metrics",
|
|
3
|
-
"version": "22.
|
|
3
|
+
"version": "22.4.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Read-only value visualizations (progress, meter, gauge/ring) for Angular 21+, part of the ng-hub-ui family.",
|
|
6
6
|
"author": "Carlos Morcillo <carlos.morcillo@me.com> (https://www.carlosmorcillo.com)",
|
|
@@ -28,8 +28,14 @@
|
|
|
28
28
|
"peerDependencies": {
|
|
29
29
|
"@angular/common": ">=21.0.0",
|
|
30
30
|
"@angular/core": ">=21.0.0",
|
|
31
|
+
"ng-hub-ui-ds": ">=22.0.0",
|
|
31
32
|
"ng-hub-ui-utils": ">=22.7.0"
|
|
32
33
|
},
|
|
34
|
+
"peerDependenciesMeta": {
|
|
35
|
+
"ng-hub-ui-ds": {
|
|
36
|
+
"optional": true
|
|
37
|
+
}
|
|
38
|
+
},
|
|
33
39
|
"dependencies": {
|
|
34
40
|
"tslib": "^2.3.0"
|
|
35
41
|
},
|
|
@@ -133,6 +133,12 @@ declare class HubMeterComponent {
|
|
|
133
133
|
readonly high: _angular_core.InputSignal<number | undefined>;
|
|
134
134
|
/** Preferred point of the range; defaults to the midpoint when omitted. */
|
|
135
135
|
readonly optimum: _angular_core.InputSignal<number | undefined>;
|
|
136
|
+
/**
|
|
137
|
+
* Accessible label describing what is being measured. `role="meter"` takes its
|
|
138
|
+
* name from the author only, so without it the gauge reaches assistive
|
|
139
|
+
* technology unnamed — the component renders no text of its own.
|
|
140
|
+
*/
|
|
141
|
+
readonly label: _angular_core.InputSignal<string>;
|
|
136
142
|
/** Fully resolved, clamped bounds derived from the raw inputs. */
|
|
137
143
|
protected readonly resolved: _angular_core.Signal<HubMeterResolved>;
|
|
138
144
|
/**
|
|
@@ -147,7 +153,7 @@ declare class HubMeterComponent {
|
|
|
147
153
|
/** Host modifier classes derived from the computed band. */
|
|
148
154
|
protected readonly hostClasses: _angular_core.Signal<string>;
|
|
149
155
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<HubMeterComponent, never>;
|
|
150
|
-
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>;
|
|
156
|
+
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; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
151
157
|
}
|
|
152
158
|
|
|
153
159
|
/**
|
|
@@ -159,7 +165,7 @@ declare class HubMeterComponent {
|
|
|
159
165
|
* keeps the neutral `--hub-ring-indicator` colour.
|
|
160
166
|
*/
|
|
161
167
|
interface HubRingThresholds {
|
|
162
|
-
/** Value
|
|
168
|
+
/** Value strictly below which the ring is treated as "low"; `low` itself is not. */
|
|
163
169
|
low?: number;
|
|
164
170
|
/** Value at or above which the ring is treated as "high". */
|
|
165
171
|
high?: number;
|
|
@@ -177,11 +183,12 @@ type HubRingBand = 'low' | 'default' | 'high';
|
|
|
177
183
|
* over a `pathLength`-normalized circle, so the offset maps linearly to the
|
|
178
184
|
* completion (100 at 0%, 0 at 100%). Optional {@link thresholds} recolour the
|
|
179
185
|
* indicator through the `--hub-ring-low-color` / `--hub-ring-high-color` tokens;
|
|
180
|
-
* a centred caption is projected through `<ng-content>`.
|
|
186
|
+
* a centred caption is projected through `<ng-content>`. That caption is decoration:
|
|
187
|
+
* `role="meter"` is named by the author, so pass {@link label} to name the gauge.
|
|
181
188
|
*
|
|
182
189
|
* @example
|
|
183
190
|
* ```html
|
|
184
|
-
* <hub-ring [value]="0.82" [thresholds]="{ low: 0.4, high: 0.75 }">Score</hub-ring>
|
|
191
|
+
* <hub-ring [value]="0.82" [thresholds]="{ low: 0.4, high: 0.75 }" label="Quality score">Score</hub-ring>
|
|
185
192
|
* ```
|
|
186
193
|
*/
|
|
187
194
|
declare class HubRingComponent {
|
|
@@ -189,14 +196,28 @@ declare class HubRingComponent {
|
|
|
189
196
|
readonly value: _angular_core.InputSignal<number>;
|
|
190
197
|
/** Upper bound the {@link value} is normalized against. */
|
|
191
198
|
readonly max: _angular_core.InputSignal<number>;
|
|
192
|
-
/**
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
199
|
+
/**
|
|
200
|
+
* Outer diameter of the ring (number → px, or any CSS length string), applied
|
|
201
|
+
* inline as a per-instance override. Omit it to let the `--hub-ring-size`
|
|
202
|
+
* token (default or theme override) drive the diameter.
|
|
203
|
+
*/
|
|
204
|
+
readonly size: _angular_core.InputSignal<string | number | undefined>;
|
|
205
|
+
/**
|
|
206
|
+
* Stroke width of the ring (number → px, or any CSS length string), applied
|
|
207
|
+
* inline as a per-instance override. Omit it to let the
|
|
208
|
+
* `--hub-ring-thickness` token (default or theme override) drive the stroke.
|
|
209
|
+
*/
|
|
210
|
+
readonly thickness: _angular_core.InputSignal<string | number | undefined>;
|
|
196
211
|
/** Optional colour thresholds recolouring the indicator by band. */
|
|
197
212
|
readonly thresholds: _angular_core.InputSignal<HubRingThresholds | undefined>;
|
|
198
213
|
/** Whether the rounded percentage is rendered in the centre. */
|
|
199
214
|
readonly showValue: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
215
|
+
/**
|
|
216
|
+
* Accessible label describing what the ring scores. `role="meter"` takes its
|
|
217
|
+
* name from the author only, so neither the projected caption nor the centred
|
|
218
|
+
* percentage can name the gauge — this input is the only way to do it.
|
|
219
|
+
*/
|
|
220
|
+
readonly label: _angular_core.InputSignal<string>;
|
|
200
221
|
/** Total normalized path length of the SVG circle (see `pathLength`). */
|
|
201
222
|
protected readonly PATH_LENGTH = 100;
|
|
202
223
|
/** Completion ratio in `[0, 1]`; `0` when `max` is not positive. */
|
|
@@ -214,13 +235,17 @@ declare class HubRingComponent {
|
|
|
214
235
|
/** Host modifier classes derived from the computed band. */
|
|
215
236
|
protected readonly hostClasses: _angular_core.Signal<string>;
|
|
216
237
|
/** Ring diameter as a CSS length (numbers are treated as pixels). */
|
|
217
|
-
protected readonly sizeCss: _angular_core.Signal<string>;
|
|
238
|
+
protected readonly sizeCss: _angular_core.Signal<string | null>;
|
|
218
239
|
/** Stroke thickness as a CSS length (numbers are treated as pixels). */
|
|
219
|
-
protected readonly thicknessCss: _angular_core.Signal<string>;
|
|
220
|
-
/**
|
|
240
|
+
protected readonly thicknessCss: _angular_core.Signal<string | null>;
|
|
241
|
+
/**
|
|
242
|
+
* Normalizes a number|string dimension into a CSS length string, returning
|
|
243
|
+
* `null` when the input is unset so the inline binding is dropped altogether
|
|
244
|
+
* and the stylesheet token wins the cascade instead of being shadowed.
|
|
245
|
+
*/
|
|
221
246
|
private toCssLength;
|
|
222
247
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<HubRingComponent, never>;
|
|
223
|
-
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>;
|
|
248
|
+
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; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
224
249
|
}
|
|
225
250
|
|
|
226
251
|
export { HubMeterComponent, HubProgressComponent, HubRingComponent };
|