@timmo001/groundwork-ui 0.9.18 → 0.9.19
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/package.json +1 -1
- package/src/gw-meter.ts +66 -18
package/package.json
CHANGED
package/src/gw-meter.ts
CHANGED
|
@@ -18,12 +18,14 @@ import { base, type Tone } from "./styles.js";
|
|
|
18
18
|
* @summary A labeled bar for a value in a range.
|
|
19
19
|
*
|
|
20
20
|
* @attr {string} label - What it measures.
|
|
21
|
-
* @attr {number} value - The value. Defaults to 0.
|
|
21
|
+
* @attr {number} value - The value. Defaults to 0. Leave it unset or `NaN` for an unknown value, shown as `-` with an empty bar.
|
|
22
22
|
* @attr {number} min - The bottom of the range. Defaults to 0.
|
|
23
23
|
* @attr {number} max - The top of the range. Defaults to 100.
|
|
24
24
|
* @attr {number} high - Past this it turns warning.
|
|
25
25
|
* @attr {number} critical - Past this it turns danger.
|
|
26
|
+
* @attr {boolean} inverted - Lower is worse, such as for a battery: at or below `high` it turns warning, and at or below `critical` danger.
|
|
26
27
|
* @attr {string} display - The value as shown, such as `42 GB`. Defaults to a percentage.
|
|
28
|
+
* @attr {string} caption - A quiet line under the bar.
|
|
27
29
|
* @attr {"neutral"|"accent"|"info"|"success"|"warning"|"danger"|"important"} tone - A fixed color, overriding `high` and `critical`.
|
|
28
30
|
* @attr {boolean} loading - Pulses the track and shows a skeleton for the value.
|
|
29
31
|
*
|
|
@@ -31,6 +33,9 @@ import { base, type Tone } from "./styles.js";
|
|
|
31
33
|
* @csspart value - The value as shown.
|
|
32
34
|
* @csspart track - The bar's track.
|
|
33
35
|
* @csspart fill - The filled part of the bar.
|
|
36
|
+
* @csspart caption - The line under the bar.
|
|
37
|
+
*
|
|
38
|
+
* @cssprop --gw-meter-height - The bar's height. Defaults to `0.5rem`.
|
|
34
39
|
*/
|
|
35
40
|
export class GwMeter extends GwElement {
|
|
36
41
|
static override properties = {
|
|
@@ -40,7 +45,9 @@ export class GwMeter extends GwElement {
|
|
|
40
45
|
max: { type: "number" },
|
|
41
46
|
high: { type: "number" },
|
|
42
47
|
critical: { type: "number" },
|
|
48
|
+
inverted: { type: "boolean" },
|
|
43
49
|
display: {},
|
|
50
|
+
caption: {},
|
|
44
51
|
tone: { reflect: true },
|
|
45
52
|
loading: { type: "boolean", reflect: true },
|
|
46
53
|
} as const;
|
|
@@ -66,7 +73,7 @@ export class GwMeter extends GwElement {
|
|
|
66
73
|
}
|
|
67
74
|
|
|
68
75
|
.track {
|
|
69
|
-
height: 0.5rem;
|
|
76
|
+
height: var(--gw-meter-height, 0.5rem);
|
|
70
77
|
overflow: hidden;
|
|
71
78
|
background: var(--gw-color-surface-lower);
|
|
72
79
|
border: var(--gw-border-width) solid var(--gw-color-border-quiet);
|
|
@@ -82,19 +89,35 @@ export class GwMeter extends GwElement {
|
|
|
82
89
|
|
|
83
90
|
.bar {
|
|
84
91
|
min-height: 0;
|
|
85
|
-
height: 0.5rem;
|
|
92
|
+
height: var(--gw-meter-height, 0.5rem);
|
|
86
93
|
--gw-skeleton-radius: var(--gw-radius-pill);
|
|
87
94
|
}
|
|
95
|
+
|
|
96
|
+
.caption {
|
|
97
|
+
display: block;
|
|
98
|
+
margin-block-start: var(--gw-space-1);
|
|
99
|
+
overflow: hidden;
|
|
100
|
+
font-size: var(--gw-font-size-xs);
|
|
101
|
+
color: var(--gw-color-text-secondary);
|
|
102
|
+
text-overflow: ellipsis;
|
|
103
|
+
white-space: nowrap;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.caption[hidden] {
|
|
107
|
+
display: none;
|
|
108
|
+
}
|
|
88
109
|
`,
|
|
89
110
|
];
|
|
90
111
|
|
|
91
112
|
declare label: string;
|
|
92
|
-
declare value: number;
|
|
113
|
+
declare value: number | undefined;
|
|
93
114
|
declare min: number;
|
|
94
115
|
declare max: number;
|
|
95
116
|
declare high: number | undefined;
|
|
96
117
|
declare critical: number | undefined;
|
|
118
|
+
declare inverted: boolean;
|
|
97
119
|
declare display: string;
|
|
120
|
+
declare caption: string;
|
|
98
121
|
declare tone: Tone | undefined;
|
|
99
122
|
declare loading: boolean;
|
|
100
123
|
|
|
@@ -126,6 +149,8 @@ export class GwMeter extends GwElement {
|
|
|
126
149
|
|
|
127
150
|
readonly #bar = h("gw-skeleton", { class: "bar" });
|
|
128
151
|
|
|
152
|
+
readonly #caption = h("span", { class: "caption", part: "caption" });
|
|
153
|
+
|
|
129
154
|
#rendered = false;
|
|
130
155
|
|
|
131
156
|
constructor() {
|
|
@@ -136,21 +161,33 @@ export class GwMeter extends GwElement {
|
|
|
136
161
|
this.max = 100;
|
|
137
162
|
this.high = undefined;
|
|
138
163
|
this.critical = undefined;
|
|
164
|
+
this.inverted = false;
|
|
139
165
|
this.display = "";
|
|
166
|
+
this.caption = "";
|
|
140
167
|
this.tone = undefined;
|
|
141
168
|
this.loading = false;
|
|
142
169
|
}
|
|
143
170
|
|
|
171
|
+
get #known() {
|
|
172
|
+
return this.value !== undefined && Number.isFinite(this.value)
|
|
173
|
+
? this.value
|
|
174
|
+
: undefined;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
#worse(limit: number | undefined) {
|
|
178
|
+
const value = this.#known;
|
|
179
|
+
|
|
180
|
+
if (limit === undefined || value === undefined) return false;
|
|
181
|
+
|
|
182
|
+
return this.inverted ? value <= limit : value >= limit;
|
|
183
|
+
}
|
|
184
|
+
|
|
144
185
|
get #color() {
|
|
145
186
|
if (this.tone !== undefined) return "var(--gw-tone)";
|
|
146
187
|
|
|
147
|
-
if (this.critical
|
|
148
|
-
return "var(--gw-color-danger)";
|
|
149
|
-
}
|
|
188
|
+
if (this.#worse(this.critical)) return "var(--gw-color-danger)";
|
|
150
189
|
|
|
151
|
-
if (this.high
|
|
152
|
-
return "var(--gw-color-warning)";
|
|
153
|
-
}
|
|
190
|
+
if (this.#worse(this.high)) return "var(--gw-color-warning)";
|
|
154
191
|
|
|
155
192
|
return "var(--gw-color-fill-accent-resting)";
|
|
156
193
|
}
|
|
@@ -161,18 +198,21 @@ export class GwMeter extends GwElement {
|
|
|
161
198
|
this.#value,
|
|
162
199
|
this.#valueSkeleton,
|
|
163
200
|
);
|
|
164
|
-
root.append(this.#top, this.#track, this.#bar);
|
|
201
|
+
root.append(this.#top, this.#track, this.#bar, this.#caption);
|
|
165
202
|
}
|
|
166
203
|
|
|
167
204
|
protected override update(changed: ReadonlySet<string>) {
|
|
205
|
+
const value = this.#known;
|
|
206
|
+
|
|
168
207
|
const span = this.max - this.min || 1;
|
|
169
208
|
|
|
170
|
-
const percent =
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
209
|
+
const percent =
|
|
210
|
+
value === undefined
|
|
211
|
+
? 0
|
|
212
|
+
: Math.min(100, Math.max(0, ((value - this.min) / span) * 100));
|
|
174
213
|
|
|
175
|
-
const text =
|
|
214
|
+
const text =
|
|
215
|
+
this.display || (value === undefined ? "-" : `${Math.round(percent)}%`);
|
|
176
216
|
|
|
177
217
|
setAttribute(this.#top, "aria-busy", this.loading ? "true" : null);
|
|
178
218
|
this.#label.textContent = this.label;
|
|
@@ -182,16 +222,24 @@ export class GwMeter extends GwElement {
|
|
|
182
222
|
this.#valueSkeleton.hidden = !this.loading;
|
|
183
223
|
this.#track.hidden = this.loading;
|
|
184
224
|
this.#bar.hidden = !this.loading;
|
|
225
|
+
this.#caption.textContent = this.caption;
|
|
226
|
+
this.#caption.hidden = this.loading || this.caption === "";
|
|
185
227
|
setAttribute(this.#track, "aria-label", this.label || null);
|
|
186
228
|
setAttribute(this.#track, "aria-valuemin", this.min);
|
|
187
229
|
setAttribute(this.#track, "aria-valuemax", this.max);
|
|
188
|
-
|
|
189
|
-
setAttribute(this.#track, "aria-
|
|
230
|
+
// A meter needs a value; when it's unknown, the text says so
|
|
231
|
+
setAttribute(this.#track, "aria-valuenow", value ?? this.min);
|
|
232
|
+
setAttribute(
|
|
233
|
+
this.#track,
|
|
234
|
+
"aria-valuetext",
|
|
235
|
+
value !== undefined || this.display !== "" ? text : "Unknown",
|
|
236
|
+
);
|
|
190
237
|
this.#fill.style.width = `${percent}%`;
|
|
191
238
|
this.#fill.style.setProperty("--gw-meter-color", this.#color);
|
|
192
239
|
|
|
193
240
|
if (this.#rendered && changed.has("loading") && !this.loading) {
|
|
194
241
|
fadeIn(this.#value);
|
|
242
|
+
fadeIn(this.#caption);
|
|
195
243
|
}
|
|
196
244
|
|
|
197
245
|
this.#rendered = true;
|