@oicl/openbridge-webcomponents 2.0.0-next.112 → 2.0.0-next.113
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/bundle/openbridge-webcomponents.bundle.js +112 -13
- package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
- package/custom-elements.json +101 -14
- package/dist/building-blocks/readout-block/readout-block.d.ts +29 -5
- package/dist/building-blocks/readout-block/readout-block.d.ts.map +1 -1
- package/dist/building-blocks/readout-block/readout-block.js +21 -7
- package/dist/building-blocks/readout-block/readout-block.js.map +1 -1
- package/dist/navigation-instruments/readout/readout-formatters.d.ts +31 -0
- package/dist/navigation-instruments/readout/readout-formatters.d.ts.map +1 -1
- package/dist/navigation-instruments/readout/readout-formatters.js +55 -1
- package/dist/navigation-instruments/readout/readout-formatters.js.map +1 -1
- package/dist/navigation-instruments/readout/readout.d.ts +26 -1
- package/dist/navigation-instruments/readout/readout.d.ts.map +1 -1
- package/dist/navigation-instruments/readout/readout.js +16 -3
- package/dist/navigation-instruments/readout/readout.js.map +1 -1
- package/dist/navigation-instruments/readout-list/readout-list.d.ts +6 -1
- package/dist/navigation-instruments/readout-list/readout-list.d.ts.map +1 -1
- package/dist/navigation-instruments/readout-list/readout-list.js +21 -4
- package/dist/navigation-instruments/readout-list/readout-list.js.map +1 -1
- package/dist/navigation-instruments/readout-list-item/readout-list-item.d.ts +26 -1
- package/dist/navigation-instruments/readout-list-item/readout-list-item.d.ts.map +1 -1
- package/dist/navigation-instruments/readout-list-item/readout-list-item.js +15 -3
- package/dist/navigation-instruments/readout-list-item/readout-list-item.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,3 +1,52 @@
|
|
|
1
|
+
var ReadoutValueType = /* @__PURE__ */ ((ReadoutValueType2) => {
|
|
2
|
+
ReadoutValueType2["number"] = "number";
|
|
3
|
+
ReadoutValueType2["text"] = "text";
|
|
4
|
+
return ReadoutValueType2;
|
|
5
|
+
})(ReadoutValueType || {});
|
|
6
|
+
const READOUT_VALUE_TYPES = Object.values(ReadoutValueType);
|
|
7
|
+
function isReadoutValueType(value) {
|
|
8
|
+
return typeof value === "string" && READOUT_VALUE_TYPES.includes(value);
|
|
9
|
+
}
|
|
10
|
+
function isBlank(value) {
|
|
11
|
+
return value.trim() === "";
|
|
12
|
+
}
|
|
13
|
+
function assertReadoutValueType(tagName, value, valueType) {
|
|
14
|
+
const resolved = valueType ?? "number";
|
|
15
|
+
if (!isReadoutValueType(resolved)) {
|
|
16
|
+
throw new TypeError(
|
|
17
|
+
`<${tagName}>: valueType must be ${READOUT_VALUE_TYPES.map((t) => `"${t}"`).join(" or ")} (got ${JSON.stringify(valueType)}).`
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
if (resolved !== "number" || typeof value !== "string" || isBlank(value)) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
if (Number.isFinite(Number(value))) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
throw new TypeError(
|
|
27
|
+
`<${tagName}>: value must be a number when valueType is "number" (got ${JSON.stringify(value)}). Set valueType="text" to render text.`
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
function resolveReadoutNumericValue(value, valueType) {
|
|
31
|
+
if (valueType === "text" || value === null || value === void 0) {
|
|
32
|
+
return void 0;
|
|
33
|
+
}
|
|
34
|
+
if (typeof value === "number") {
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
if (isBlank(value)) {
|
|
38
|
+
return void 0;
|
|
39
|
+
}
|
|
40
|
+
const parsed = Number(value);
|
|
41
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
42
|
+
}
|
|
43
|
+
function resolveReadoutTextValue(value, valueType) {
|
|
44
|
+
if (valueType !== "text" || value === null || value === void 0) {
|
|
45
|
+
return void 0;
|
|
46
|
+
}
|
|
47
|
+
const text = typeof value === "number" ? String(value) : value;
|
|
48
|
+
return isBlank(text) ? void 0 : text;
|
|
49
|
+
}
|
|
1
50
|
function dashedGenerator({
|
|
2
51
|
showZeroPadding,
|
|
3
52
|
minValueLength,
|
|
@@ -40,8 +89,13 @@ function getHintZeros(value, { showZeroPadding, minValueLength, fractionDigits }
|
|
|
40
89
|
return "";
|
|
41
90
|
}
|
|
42
91
|
export {
|
|
92
|
+
ReadoutValueType,
|
|
93
|
+
assertReadoutValueType,
|
|
43
94
|
formatNumericValue,
|
|
44
95
|
getHintZeros,
|
|
45
|
-
|
|
96
|
+
isReadoutValueType,
|
|
97
|
+
readoutFormattedInteger,
|
|
98
|
+
resolveReadoutNumericValue,
|
|
99
|
+
resolveReadoutTextValue
|
|
46
100
|
};
|
|
47
101
|
//# sourceMappingURL=readout-formatters.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readout-formatters.js","sources":["../../../src/navigation-instruments/readout/readout-formatters.ts"],"sourcesContent":["export type ReadoutNumericFormatOptions = {\n showZeroPadding: boolean;\n minValueLength: number;\n fractionDigits: number;\n};\n\nfunction dashedGenerator({\n showZeroPadding,\n minValueLength,\n fractionDigits,\n}: ReadoutNumericFormatOptions): string {\n const visibleDigits = showZeroPadding ? Math.max(minValueLength, 1) : 1;\n\n if (fractionDigits < 1) {\n return '-'.repeat(visibleDigits);\n }\n\n const integerDigits = visibleDigits - fractionDigits;\n\n return (\n '-'.repeat(Math.max(integerDigits, 1)) + '.' + '-'.repeat(fractionDigits)\n );\n}\n\nexport function formatNumericValue(\n value: number | undefined,\n options: ReadoutNumericFormatOptions\n): string {\n if (value === undefined) {\n return dashedGenerator(options);\n }\n\n return value.toFixed(options.fractionDigits);\n}\n\nexport function readoutFormattedInteger(valueText: string): number {\n const t = valueText.trim();\n if (!t) {\n return 0;\n }\n\n const rest = t.startsWith('-') ? t.slice(1) : t;\n const dot = rest.indexOf('.');\n return dot === -1 ? rest.length : dot;\n}\n\nexport function getHintZeros(\n value: number | undefined,\n {showZeroPadding, minValueLength, fractionDigits}: ReadoutNumericFormatOptions\n): string {\n const formattedValue = formatNumericValue(value, {\n showZeroPadding,\n minValueLength,\n fractionDigits,\n });\n const dotLength = fractionDigits > 0 ? 1 : 0;\n const integerLength = formattedValue.length - dotLength;\n const hintedDigits = Math.max(minValueLength - integerLength, 0);\n\n if (hintedDigits > 0) {\n return '0'.repeat(hintedDigits);\n }\n\n return '';\n}\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"readout-formatters.js","sources":["../../../src/navigation-instruments/readout/readout-formatters.ts"],"sourcesContent":["export type ReadoutNumericFormatOptions = {\n showZeroPadding: boolean;\n minValueLength: number;\n fractionDigits: number;\n};\n\n/**\n * How a readout's `value` is interpreted.\n * - `number`: formatted via `fractionDigits` / `maxDigits`.\n * - `text`: rendered verbatim, with the numeric format options ignored.\n */\nexport enum ReadoutValueType {\n number = 'number',\n text = 'text',\n}\n\nconst READOUT_VALUE_TYPES: readonly string[] = Object.values(ReadoutValueType);\n\n/** Whether `value` is one of the supported {@link ReadoutValueType} values. */\nexport function isReadoutValueType(value: unknown): value is ReadoutValueType {\n return typeof value === 'string' && READOUT_VALUE_TYPES.includes(value);\n}\n\nfunction isBlank(value: string): boolean {\n return value.trim() === '';\n}\n\n/**\n * Throws when `valueType` is not a supported value, or when `value` is text but\n * `valueType` is `number`.\n *\n * `valueType` is validated first because an attribute carries an unchecked\n * string: a typo such as `valuetype=\"strng\"` matches neither mode, so every\n * mode check falls through and the readout silently renders the unavailable\n * dash — the opposite of the loud failure this contract exists to give.\n * `undefined`/`null` are allowed and mean \"use the default\".\n *\n * Attributes are always strings, so a numeric-looking string (`value=\"10.12\"`)\n * is accepted and parsed. Blank strings resolve to the unavailable dash rather\n * than throwing — `value=\"${maybeUndefined}\"` is a common template shape, and\n * `Number('')` is `0`, a silently wrong reading.\n */\nexport function assertReadoutValueType(\n tagName: string,\n value: number | string | null | undefined,\n valueType: ReadoutValueType\n): void {\n // `undefined`/`null` mean \"use the default\", matching how the components and\n // the resolvers treat an unset `valueType`.\n const resolved = valueType ?? ReadoutValueType.number;\n if (!isReadoutValueType(resolved)) {\n throw new TypeError(\n `<${tagName}>: valueType must be ` +\n `${READOUT_VALUE_TYPES.map((t) => `\"${t}\"`).join(' or ')} ` +\n `(got ${JSON.stringify(valueType)}).`\n );\n }\n if (\n resolved !== ReadoutValueType.number ||\n typeof value !== 'string' ||\n isBlank(value)\n ) {\n return;\n }\n if (Number.isFinite(Number(value))) {\n return;\n }\n throw new TypeError(\n `<${tagName}>: value must be a number when valueType is \"number\" ` +\n `(got ${JSON.stringify(value)}). Set valueType=\"text\" to render text.`\n );\n}\n\n/** The value as a number, or `undefined` when it is text / unavailable. */\nexport function resolveReadoutNumericValue(\n value: number | string | null | undefined,\n valueType: ReadoutValueType\n): number | undefined {\n if (\n valueType === ReadoutValueType.text ||\n value === null ||\n value === undefined\n ) {\n return undefined;\n }\n if (typeof value === 'number') {\n return value;\n }\n if (isBlank(value)) {\n return undefined;\n }\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : undefined;\n}\n\n/** The value as display text, or `undefined` when not in text mode / blank. */\nexport function resolveReadoutTextValue(\n value: number | string | null | undefined,\n valueType: ReadoutValueType\n): string | undefined {\n if (\n valueType !== ReadoutValueType.text ||\n value === null ||\n value === undefined\n ) {\n return undefined;\n }\n const text = typeof value === 'number' ? String(value) : value;\n return isBlank(text) ? undefined : text;\n}\n\nfunction dashedGenerator({\n showZeroPadding,\n minValueLength,\n fractionDigits,\n}: ReadoutNumericFormatOptions): string {\n const visibleDigits = showZeroPadding ? Math.max(minValueLength, 1) : 1;\n\n if (fractionDigits < 1) {\n return '-'.repeat(visibleDigits);\n }\n\n const integerDigits = visibleDigits - fractionDigits;\n\n return (\n '-'.repeat(Math.max(integerDigits, 1)) + '.' + '-'.repeat(fractionDigits)\n );\n}\n\nexport function formatNumericValue(\n value: number | undefined,\n options: ReadoutNumericFormatOptions\n): string {\n if (value === undefined) {\n return dashedGenerator(options);\n }\n\n return value.toFixed(options.fractionDigits);\n}\n\nexport function readoutFormattedInteger(valueText: string): number {\n const t = valueText.trim();\n if (!t) {\n return 0;\n }\n\n const rest = t.startsWith('-') ? t.slice(1) : t;\n const dot = rest.indexOf('.');\n return dot === -1 ? rest.length : dot;\n}\n\nexport function getHintZeros(\n value: number | undefined,\n {showZeroPadding, minValueLength, fractionDigits}: ReadoutNumericFormatOptions\n): string {\n const formattedValue = formatNumericValue(value, {\n showZeroPadding,\n minValueLength,\n fractionDigits,\n });\n const dotLength = fractionDigits > 0 ? 1 : 0;\n const integerLength = formattedValue.length - dotLength;\n const hintedDigits = Math.max(minValueLength - integerLength, 0);\n\n if (hintedDigits > 0) {\n return '0'.repeat(hintedDigits);\n }\n\n return '';\n}\n"],"names":["ReadoutValueType"],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ import { LitElement } from 'lit';
|
|
|
2
2
|
import { ReadoutBlockSize, ReadoutBlockDataQuality } from '../../building-blocks/readout-block/readout-block.js';
|
|
3
3
|
import { ReadoutListItemSetpointInteraction, ReadoutValueOptions, ReadoutSetpointOptions, ReadoutAdviceOptions, ReadoutReserverOptions, ReadoutSrcOptions } from '../readout-list-item/readout-list-item.js';
|
|
4
4
|
import { Priority } from '../types.js';
|
|
5
|
+
import { ReadoutValueType } from './readout-formatters.js';
|
|
5
6
|
import { AlertFrameConfig } from '../../components/alert-frame/alert-frame.js';
|
|
6
7
|
import '../../components/textbox/textbox.js';
|
|
7
8
|
import '../../building-blocks/readout-block/readout-block.js';
|
|
@@ -10,6 +11,7 @@ import '../../components/context-menu-input/context-menu-input.js';
|
|
|
10
11
|
import '../../icons/icon-chevron-right-google.js';
|
|
11
12
|
import '../../icons/icon-drop-down-google.js';
|
|
12
13
|
export { ObcTextboxFontWeight } from '../../components/textbox/textbox.js';
|
|
14
|
+
export { ReadoutValueType } from './readout-formatters.js';
|
|
13
15
|
export type { ReadoutBlockState, ReadoutValueOptions, ReadoutSetpointOptions, ReadoutAdviceOptions, ReadoutReserverOptions, ReadoutSrcOptions, } from '../readout-list-item/readout-list-item.js';
|
|
14
16
|
/**
|
|
15
17
|
* Density/size scale of the readout (an alias of `ReadoutBlockSize`).
|
|
@@ -137,6 +139,8 @@ export interface ReadoutSourceOptions extends ReadoutSrcOptions {
|
|
|
137
139
|
* `flyout` interactivity via `srcOptions.interaction`.
|
|
138
140
|
* - **Formatting:** shared `fractionDigits`, width reservation via
|
|
139
141
|
* `maxDigits` and per-segment `hintedZeros`; a `null` value renders a dash.
|
|
142
|
+
* - **Text values:** `valueType="text"` renders `value` verbatim (e.g.
|
|
143
|
+
* `"Auto"`) instead of formatting it as a number.
|
|
140
144
|
*
|
|
141
145
|
* ### Usage Guidelines
|
|
142
146
|
* Use for stand-alone instrument readouts and readouts embedded in
|
|
@@ -174,7 +178,17 @@ export declare class ObcReadout extends LitElement {
|
|
|
174
178
|
* value block at full size, so the layout does not shift when data arrives.
|
|
175
179
|
*/
|
|
176
180
|
hasValue: boolean;
|
|
177
|
-
|
|
181
|
+
/**
|
|
182
|
+
* The value; `null` renders a dash. A number by default, or text when
|
|
183
|
+
* {@link valueType} is `text`.
|
|
184
|
+
*/
|
|
185
|
+
value: number | string | null;
|
|
186
|
+
/**
|
|
187
|
+
* How {@link value} is interpreted. `number` (default) formats it via
|
|
188
|
+
* `fractionDigits`; `text` renders it verbatim and ignores the numeric
|
|
189
|
+
* format options. Passing text while this is `number` throws.
|
|
190
|
+
*/
|
|
191
|
+
valueType: ReadoutValueType;
|
|
178
192
|
/** Render the value as `offText` (e.g. equipment powered down). Affects the value only. */
|
|
179
193
|
off: boolean;
|
|
180
194
|
/** Text shown in place of the value when `off` is true. @availableWhen off==true */
|
|
@@ -195,7 +209,17 @@ export declare class ObcReadout extends LitElement {
|
|
|
195
209
|
hasDegree: boolean;
|
|
196
210
|
/** @availableWhen hasDegree==false */
|
|
197
211
|
hasDegreeSpacer: boolean;
|
|
212
|
+
/**
|
|
213
|
+
* Also formats the numeric setpoint / advice blocks, which stay numeric
|
|
214
|
+
* even when the value is text.
|
|
215
|
+
* @availableWhen valueType==number || hasSetpoint==true || hasAdvice==true
|
|
216
|
+
*/
|
|
198
217
|
fractionDigits: number;
|
|
218
|
+
/**
|
|
219
|
+
* Also formats the numeric setpoint / advice blocks, which stay numeric
|
|
220
|
+
* even when the value is text.
|
|
221
|
+
* @availableWhen valueType==number || hasSetpoint==true || hasAdvice==true
|
|
222
|
+
*/
|
|
199
223
|
maxDigits: number;
|
|
200
224
|
dataQuality?: ReadoutDataQuality;
|
|
201
225
|
alert: boolean | AlertFrameConfig;
|
|
@@ -361,6 +385,7 @@ export declare class ObcReadout extends LitElement {
|
|
|
361
385
|
* divider.
|
|
362
386
|
*/
|
|
363
387
|
private renderHorizontalLayout;
|
|
388
|
+
protected willUpdate(changed: Map<string, unknown>): void;
|
|
364
389
|
updated(changed: Map<string, unknown>): void;
|
|
365
390
|
private clearDeferredSetpointHide;
|
|
366
391
|
disconnectedCallback(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readout.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/readout/readout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAgD,MAAM,KAAK,CAAC;AAK9E,OAAO,qCAAqC,CAAC;AAK7C,OAAO,sDAAsD,CAAC;AAC9D,OAAO,EAEL,gBAAgB,EAChB,uBAAuB,EAExB,MAAM,sDAAsD,CAAC;AAC9D,OAAO,EACL,kCAAkC,EAElC,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACvB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"readout.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/readout/readout.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,7 @@ import { ObcTextboxFontWeight, ObcTextboxSize } from "../../components/textbox/t
|
|
|
7
7
|
import { ReadoutBlockHidePhase, ReadoutBlockSize, ReadoutBlockVariant, ReadoutBlockDataQuality } from "../../building-blocks/readout-block/readout-block.js";
|
|
8
8
|
import { ReadoutListItemSetpointInteraction } from "../readout-list-item/readout-list-item.js";
|
|
9
9
|
import { Priority } from "../types.js";
|
|
10
|
+
import { ReadoutValueType, resolveReadoutNumericValue, assertReadoutValueType } from "./readout-formatters.js";
|
|
10
11
|
import { isDisplayedAtSetpoint, readoutPrimarySize, readoutSecondarySize, readoutSetpointWeight, readoutNumericFormatOptions, readoutDataQualityClasses, resolveSetpointHidePhase } from "./readout-shared.js";
|
|
11
12
|
import { wrapWithAlertFrame, ObcAlertFrameThickness, ObcAlertFrameType, ObcAlertFrameMode } from "../../components/alert-frame/alert-frame.js";
|
|
12
13
|
import { AlertType } from "../../types.js";
|
|
@@ -55,6 +56,7 @@ let ObcReadout = class extends LitElement {
|
|
|
55
56
|
super(...arguments);
|
|
56
57
|
this.hasValue = true;
|
|
57
58
|
this.value = null;
|
|
59
|
+
this.valueType = ReadoutValueType.number;
|
|
58
60
|
this.off = false;
|
|
59
61
|
this.offText = "OFF";
|
|
60
62
|
this.hasSetpoint = false;
|
|
@@ -129,7 +131,7 @@ let ObcReadout = class extends LitElement {
|
|
|
129
131
|
return false;
|
|
130
132
|
}
|
|
131
133
|
return isDisplayedAtSetpoint(
|
|
132
|
-
this.value,
|
|
134
|
+
resolveReadoutNumericValue(this.value, this.valueType) ?? null,
|
|
133
135
|
this.setpoint,
|
|
134
136
|
this.numericFormatOptions(this.resolvedMaxDigits)
|
|
135
137
|
);
|
|
@@ -231,6 +233,7 @@ let ObcReadout = class extends LitElement {
|
|
|
231
233
|
exportparts="block, block-content, block-text, block-icon, degree"
|
|
232
234
|
.variant=${config.variant}
|
|
233
235
|
.value=${config.value ?? null}
|
|
236
|
+
.valueType=${config.valueType ?? ReadoutValueType.number}
|
|
234
237
|
.size=${this.resolvedSize}
|
|
235
238
|
.valueSize=${config.valueSize}
|
|
236
239
|
.enhanced=${config.enhanced}
|
|
@@ -371,6 +374,7 @@ let ObcReadout = class extends LitElement {
|
|
|
371
374
|
${this.renderBlock({
|
|
372
375
|
variant: ReadoutBlockVariant.value,
|
|
373
376
|
value: this.value,
|
|
377
|
+
valueType: this.valueType,
|
|
374
378
|
valueSize: this.valueSize,
|
|
375
379
|
enhanced: this.rowEnhanced,
|
|
376
380
|
weight: this.valueWeight,
|
|
@@ -649,6 +653,7 @@ let ObcReadout = class extends LitElement {
|
|
|
649
653
|
}) : html`${this.renderBlock({
|
|
650
654
|
variant: ReadoutBlockVariant.value,
|
|
651
655
|
value: this.value,
|
|
656
|
+
valueType: this.valueType,
|
|
652
657
|
valueSize: this.primarySize,
|
|
653
658
|
enhanced: false,
|
|
654
659
|
weight: this.valueWeight,
|
|
@@ -706,6 +711,10 @@ let ObcReadout = class extends LitElement {
|
|
|
706
711
|
</div>
|
|
707
712
|
`;
|
|
708
713
|
}
|
|
714
|
+
willUpdate(changed) {
|
|
715
|
+
super.willUpdate(changed);
|
|
716
|
+
assertReadoutValueType("obc-readout", this.value, this.valueType);
|
|
717
|
+
}
|
|
709
718
|
updated(changed) {
|
|
710
719
|
super.updated(changed);
|
|
711
720
|
if (changed.has("sourcePickerContentVisible")) {
|
|
@@ -799,8 +808,11 @@ __decorateClass([
|
|
|
799
808
|
property({ type: Boolean, attribute: false })
|
|
800
809
|
], ObcReadout.prototype, "hasValue", 2);
|
|
801
810
|
__decorateClass([
|
|
802
|
-
property({ type:
|
|
811
|
+
property({ type: String })
|
|
803
812
|
], ObcReadout.prototype, "value", 2);
|
|
813
|
+
__decorateClass([
|
|
814
|
+
property({ type: String })
|
|
815
|
+
], ObcReadout.prototype, "valueType", 2);
|
|
804
816
|
__decorateClass([
|
|
805
817
|
property({ type: Boolean })
|
|
806
818
|
], ObcReadout.prototype, "off", 2);
|
|
@@ -895,6 +907,7 @@ export {
|
|
|
895
907
|
ReadoutSetpointInteraction,
|
|
896
908
|
ReadoutSize,
|
|
897
909
|
ReadoutSourceInteraction,
|
|
898
|
-
ReadoutStacking
|
|
910
|
+
ReadoutStacking,
|
|
911
|
+
ReadoutValueType
|
|
899
912
|
};
|
|
900
913
|
//# sourceMappingURL=readout.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readout.js","sources":["../../../src/navigation-instruments/readout/readout.ts"],"sourcesContent":["import {LitElement, html, nothing, unsafeCSS, type TemplateResult} from 'lit';\nimport {property, query, state} from 'lit/decorators.js';\nimport {classMap} from 'lit/directives/class-map.js';\nimport componentStyle from './readout.css?inline';\nimport {customElement} from '../../decorator.js';\nimport '../../components/textbox/textbox.js';\nimport {\n ObcTextboxSize,\n ObcTextboxFontWeight,\n} from '../../components/textbox/textbox.js';\nimport '../../building-blocks/readout-block/readout-block.js';\nimport {\n ReadoutBlockVariant,\n ReadoutBlockSize,\n ReadoutBlockDataQuality,\n ReadoutBlockHidePhase,\n} from '../../building-blocks/readout-block/readout-block.js';\nimport {\n ReadoutListItemSetpointInteraction,\n type ReadoutBlockState,\n type ReadoutValueOptions,\n type ReadoutSetpointOptions,\n type ReadoutAdviceOptions,\n type ReadoutReserverOptions,\n type ReadoutSrcOptions,\n} from '../readout-list-item/readout-list-item.js';\nimport {Priority} from '../types.js';\nimport {type ReadoutNumericFormatOptions} from './readout-formatters.js';\nimport {\n isDisplayedAtSetpoint,\n readoutNumericFormatOptions,\n readoutPrimarySize,\n readoutSecondarySize,\n readoutSetpointWeight,\n readoutDataQualityClasses,\n resolveSetpointHidePhase,\n} from './readout-shared.js';\nimport {\n type AlertFrameConfig,\n wrapWithAlertFrame,\n ObcAlertFrameType,\n ObcAlertFrameThickness,\n ObcAlertFrameMode,\n} from '../../components/alert-frame/alert-frame.js';\nimport {AlertType} from '../../types.js';\nimport '../../components/button/button.js';\nimport '../../components/context-menu-input/context-menu-input.js';\nimport {\n ContextMenuType,\n type ContextMenuOption,\n type ObcContextMenuInputItemClickEvent,\n} from '../../components/context-menu-input/context-menu-input.js';\nimport '../../icons/icon-chevron-right-google.js';\nimport '../../icons/icon-drop-down-google.js';\n\n// Re-exported so consumers configure the readout without a second import path.\n// The option interfaces and enums are shared with `obc-readout-list-item` on\n// purpose: the two components are layout variants of the same primitives +\n// per-block options API and may merge in a future release.\nexport {ObcTextboxFontWeight} from '../../components/textbox/textbox.js';\nexport type {\n ReadoutBlockState,\n ReadoutValueOptions,\n ReadoutSetpointOptions,\n ReadoutAdviceOptions,\n ReadoutReserverOptions,\n ReadoutSrcOptions,\n} from '../readout-list-item/readout-list-item.js';\n\n/**\n * Density/size scale of the readout (an alias of `ReadoutBlockSize`).\n * - `small`: regular value typography (smallest, densest).\n * - `medium`: medium value typography.\n * - `large`: large value typography.\n */\nexport const ReadoutSize = ReadoutBlockSize;\nexport type ReadoutSize = ReadoutBlockSize;\n\n/**\n * Colour emphasis of the value (an alias of the shared instrument `Priority`;\n * same values as `ReadoutListItemPriority`).\n * - `regular`: neutral.\n * - `enhanced`: accented (in-command) colour.\n */\nexport const ReadoutPriority = Priority;\nexport type ReadoutPriority = Priority;\n\n/**\n * Measurement quality of the value (an alias of `ReadoutBlockDataQuality`).\n * Orthogonal to the readout-level `alert` – a low-integrity or invalid value\n * can also sit inside an alert frame.\n */\nexport const ReadoutDataQuality = ReadoutBlockDataQuality;\nexport type ReadoutDataQuality = ReadoutBlockDataQuality;\n\n/**\n * How the setpoint segment behaves relative to the value (an alias of\n * `ReadoutListItemSetpointInteraction`).\n * - `always-visible` (default): the setpoint is always shown.\n * - `flip-flop`: value and setpoint swap emphasis (size) as the value reaches\n * the setpoint.\n * - `pop-up`: the setpoint is shown only while the value has not reached it,\n * then fades out (100ms) once value === setpoint.\n */\nexport const ReadoutSetpointInteraction = ReadoutListItemSetpointInteraction;\nexport type ReadoutSetpointInteraction = ReadoutListItemSetpointInteraction;\n\n/**\n * Flow direction of the readout.\n * - `vertical` (default): advice / setpoint / value stack on top of the\n * label+unit meta zone and the source row (Figma \"Readout Group / Vertical\"\n * and \"Readout Stack\").\n * - `horizontal`: all segments flow on one cap-height-aligned row, with the\n * label stacked over the unit beside the value (Figma \"Readout Group /\n * Horizontal\").\n */\nexport enum ReadoutDirection {\n vertical = 'vertical',\n horizontal = 'horizontal',\n}\n\n/**\n * Arrangement of the label/unit meta zone in a vertical readout.\n * - `inline` (default): label and unit share one row below the value (Figma\n * \"Readout Group / Vertical\").\n * - `stacked`: label and unit render on separate rows (Figma \"Readout Stack\"),\n * arranged by `alignment`.\n */\nexport enum ReadoutStacking {\n inline = 'inline',\n stacked = 'stacked',\n}\n\n/**\n * Cross-axis alignment of a stacked vertical readout (Figma \"Readout Stack\"\n * Alignment axis).\n * - `vertical` (default): right-aligned column.\n * - `left`: left-aligned column.\n * - `center`: centered column.\n */\nexport enum ReadoutAlignment {\n vertical = 'vertical',\n left = 'left',\n center = 'center',\n}\n\n/**\n * Interactivity of the source row.\n * - `none` (default): plain source text (same rendering as\n * `obc-readout-list-item`).\n * - `picker`: a flat button with a drop-down icon that opens a context menu\n * built from the `src-picker-content` slot; selecting an option fires\n * `source-change`.\n * - `flyout`: a flat button with a chevron icon that fires\n * `source-flyout-click`.\n */\nexport enum ReadoutSourceInteraction {\n none = 'none',\n picker = 'picker',\n flyout = 'flyout',\n}\n\n/**\n * Per-source options. Extends the shared per-block state (data quality, alert,\n * space reserver) with the readout's source interactivity.\n */\nexport interface ReadoutSourceOptions extends ReadoutSrcOptions {\n /** Interactivity of the source row (default `none`). */\n interaction?: ReadoutSourceInteraction;\n}\n\n/**\n * `<obc-readout>` – An instrument readout: a value with optional setpoint,\n * advice, label, unit, and source, arranged vertically or horizontally.\n *\n * A layout sibling of `<obc-readout-list-item>` built from the same\n * cap-height \"readout building blocks\" (`obc-readout-block`): dynamic data is\n * passed as top-level primitives (`value`, `setpoint`, `advice`, `label`,\n * `unit`, `src`), global layout/format via top-level props (`size`,\n * `priority`, `direction`, `stacking`, `alignment`, `hasDegree`,\n * `dataQuality`, `alert`, …) and per-block tweaks via one object per block\n * (`valueOptions`, `setpointOptions`, `adviceOptions`, `unitOptions`,\n * `srcOptions`).\n *\n * ### Features\n * - **Building blocks:** value, optional setpoint, and optional advice\n * segments, each cap-height-aligned and able to reserve a stable width.\n * - **Sizes:** `small`, `medium`, `large` density scales.\n * - **Direction:** `vertical` (blocks above a label+unit meta zone and source\n * row) or `horizontal` (all segments on one row).\n * - **Stacking & alignment:** vertical readouts arrange label/unit `inline`\n * or `stacked`; stacked readouts align `vertical` (right), `left`, or\n * `center`.\n * - **Priority:** `regular`/`enhanced` colour emphasis; per-value `weight`\n * is independent of colour.\n * - **Setpoint interactions:** `always-visible`, `flip-flop` (emphasis swap),\n * and `pop-up` (fade-out at setpoint), plus the `touching` focus state.\n * - **Data quality:** `low-integrity`/`invalid` styling, per block or for the\n * whole readout, combinable with `alert`.\n * - **Alert frame:** optional `alert` wrapper (caution/warning/alarm/level).\n * - **Source:** plain text by default; opt-in `picker` (context menu) or\n * `flyout` interactivity via `srcOptions.interaction`.\n * - **Formatting:** shared `fractionDigits`, width reservation via\n * `maxDigits` and per-segment `hintedZeros`; a `null` value renders a dash.\n *\n * ### Usage Guidelines\n * Use for stand-alone instrument readouts and readouts embedded in\n * instruments. Prefer `<obc-readout-list-item>` for dense rows in\n * lists/tables (label left, value right) and `<obc-readout-list>` for\n * auto-aligned groups of rows.\n *\n * @experimental Part of the primitives + per-block options Readout API pilot;\n * the API may change in a future release.\n *\n * ### Slots\n * | Slot Name | Renders When | Purpose |\n * |--------------------|---------------------------------------|--------------------------------------|\n * | value-icon | `valueOptions.hasIcon` | Icon before the value. |\n * | setpoint-icon | `hasSetpoint` | Overrides the default setpoint icon. |\n * | advice-icon | `hasAdvice` | Overrides the default advice icon. |\n * | src-picker-content | `srcOptions.interaction == 'picker'` | Source picker context-menu content. |\n *\n * @fires source-change {CustomEvent<{value: string, label?: string}>} Fired when a source picker option is selected.\n * @fires source-flyout-click {CustomEvent<{src: string}>} Fired when the source row is clicked while `srcOptions.interaction == 'flyout'`.\n *\n * @slot value-icon - Icon before the value.\n * @slot setpoint-icon - Overrides the default setpoint icon.\n * @slot advice-icon - Overrides the default advice icon.\n * @slot src-picker-content - Provides the source picker context menu content.\n */\n@customElement('obc-readout')\nexport class ObcReadout extends LitElement {\n // Primitives (dynamic data)\n @property({type: String}) label?: string;\n @property({type: String}) unit?: string;\n @property({type: String}) src?: string;\n\n /**\n * Layout switch: `false` renders a deliberately value-less (label-only)\n * readout that hugs its remaining parts. For a temporarily missing value\n * keep `hasValue` and set `value` to `null` instead — the dash keeps the\n * value block at full size, so the layout does not shift when data arrives.\n */\n @property({type: Boolean, attribute: false}) hasValue = true;\n @property({type: Number}) value: number | null = null;\n /** Render the value as `offText` (e.g. equipment powered down). Affects the value only. */\n @property({type: Boolean}) off = false;\n /** Text shown in place of the value when `off` is true. @availableWhen off==true */\n @property({type: String}) offText = 'OFF';\n\n @property({type: Boolean}) hasSetpoint = false;\n /** @availableWhen hasSetpoint==true */\n @property({type: Number}) setpoint?: number;\n\n @property({type: Boolean}) hasAdvice = false;\n /** @availableWhen hasAdvice==true */\n @property({type: Number}) advice?: number;\n\n // Global layout/format (each defaults via its `resolved*` getter where useful).\n @property({type: String}) size?: ReadoutSize;\n @property({type: String}) priority?: ReadoutPriority;\n @property({type: String}) direction?: ReadoutDirection;\n /** @availableWhen direction==vertical */\n @property({type: String}) stacking?: ReadoutStacking;\n /** @availableWhen direction==vertical && stacking==stacked */\n @property({type: String}) alignment?: ReadoutAlignment;\n @property({type: Boolean}) hasDegree = false;\n /** @availableWhen hasDegree==false */\n @property({type: Boolean}) hasDegreeSpacer = false;\n @property({type: Number}) fractionDigits = 0;\n @property({type: Number}) maxDigits = 0;\n @property({type: String}) dataQuality?: ReadoutDataQuality;\n // `boolean | …` (not `false | …`): the generated Angular wrapper widens a\n // literal-`false` union to `boolean`, which then won't assign back to a\n // `false`-typed element property. `wrapWithAlertFrame` treats any non-object\n // (incl. `true`) as \"no frame\", so accepting `boolean` is harmless.\n @property({type: Object}) alert: boolean | AlertFrameConfig = false;\n\n // Per-block configuration — one object per block (see the Readout*Options types).\n /** @availableWhen hasValue==true */\n @property({type: Object}) valueOptions?: ReadoutValueOptions;\n /** @availableWhen hasSetpoint==true */\n @property({type: Object}) setpointOptions?: ReadoutSetpointOptions;\n /** @availableWhen hasAdvice==true */\n @property({type: Object}) adviceOptions?: ReadoutAdviceOptions;\n /** @availableWhen unit!='' */\n @property({type: Object}) unitOptions?: ReadoutReserverOptions;\n /** @availableWhen src!='' */\n @property({type: Object}) srcOptions?: ReadoutSourceOptions;\n\n /**\n * Development aid: outline the readout building blocks (red), the degree\n * columns (blue) and the degree spacer (green) so reserver widths / alignment\n * are visible. Off by default.\n */\n @property({type: Boolean, reflect: true}) showDebugOverlay = false;\n\n /** Pop-up deferred-hide phase for the setpoint (see {@link updated}). */\n @state() private deferredSetpointHidePhase: ReadoutBlockHidePhase =\n ReadoutBlockHidePhase.none;\n private deferredSetpointHideTimer?: number;\n private hasCompletedFirstUpdate = false;\n\n @state() private sourcePickerContentVisible = false;\n @state() private sourcePickerOptions: ContextMenuOption[] = [];\n\n @query('slot[name=\"src-picker-content\"]')\n private sourcePickerSlot?: HTMLSlotElement;\n\n private readonly onWindowPointerDown = (event: PointerEvent) => {\n if (!this.sourcePickerContentVisible) {\n return;\n }\n if (event.composedPath().includes(this)) {\n return;\n }\n this.sourcePickerContentVisible = false;\n };\n\n private get resolvedSize(): ReadoutSize {\n return this.size ?? ReadoutSize.small;\n }\n\n private get resolvedPriority(): ReadoutPriority {\n return this.priority ?? ReadoutPriority.regular;\n }\n\n private get resolvedDirection(): ReadoutDirection {\n return this.direction ?? ReadoutDirection.vertical;\n }\n\n private get resolvedStacking(): ReadoutStacking {\n return this.stacking ?? ReadoutStacking.inline;\n }\n\n private get resolvedAlignment(): ReadoutAlignment {\n return this.alignment ?? ReadoutAlignment.vertical;\n }\n\n private get isHorizontal(): boolean {\n return this.resolvedDirection === ReadoutDirection.horizontal;\n }\n\n private get resolvedFractionDigits(): number {\n return this.fractionDigits ?? 0;\n }\n\n private get resolvedMaxDigits(): number {\n return this.maxDigits ?? 0;\n }\n\n private get hasSrc(): boolean {\n return this.src !== undefined && this.src.trim() !== '';\n }\n\n private get resolvedSourceInteraction(): ReadoutSourceInteraction {\n return this.srcOptions?.interaction ?? ReadoutSourceInteraction.none;\n }\n\n private get isAtSetpoint(): boolean {\n if (!this.hasSetpoint) {\n return false;\n }\n return isDisplayedAtSetpoint(\n this.value,\n this.setpoint,\n this.numericFormatOptions(this.resolvedMaxDigits)\n );\n }\n\n private get resolvedSetpointInteraction(): ReadoutSetpointInteraction {\n return (\n this.setpointOptions?.interaction ??\n ReadoutSetpointInteraction.alwaysVisible\n );\n }\n\n private get isFlipFlop(): boolean {\n return (\n this.resolvedSetpointInteraction === ReadoutSetpointInteraction.flipFlop\n );\n }\n\n private get isPopUp(): boolean {\n return (\n this.resolvedSetpointInteraction === ReadoutSetpointInteraction.popUp\n );\n }\n\n private get setpointTouching(): boolean {\n return this.setpointOptions?.touching ?? false;\n }\n\n /**\n * Whether the setpoint interaction re-sizes or hides blocks at runtime —\n * flip-flop (emphasis swap) and pop-up (touch swap + fade-out) — the modes\n * that need the width/height reservation so the readout never shifts (see\n * {@link renderSetpointWidthReserve}).\n */\n private get hasDynamicSetpoint(): boolean {\n return this.hasSetpoint && (this.isFlipFlop || this.isPopUp);\n }\n\n /**\n * The setpoint is rendered \"emphasised\" (primary size + SemiBold weight) when\n * it is the focus of attention: while actively adjusting (`touching`), or while\n * a flip-flop has the value away from the setpoint. Otherwise it is a secondary\n * (smaller, regular-weight) reference next to the value.\n */\n private get isSetpointEmphasized(): boolean {\n if (!this.hasSetpoint) {\n return false;\n }\n if (this.setpointTouching) {\n return true;\n }\n return this.isFlipFlop && !this.isAtSetpoint;\n }\n\n /**\n * The readout's enhanced (in-command) colour state, applied uniformly to BOTH\n * the value and the setpoint — they are always either both neutral or both\n * enhanced (never a blue setpoint next to a grey value). Driven by `priority`\n * only; `valueOptions.weight` changes weight, not colour.\n */\n private get rowEnhanced(): boolean {\n return this.resolvedPriority === ReadoutPriority.enhanced;\n }\n\n /** Primary value-typography size for the current density tier. */\n private get primarySize(): ObcTextboxSize {\n return readoutPrimarySize(this.resolvedSize);\n }\n\n /** Secondary (de-emphasised) value-typography size for the current density tier. */\n private get secondarySize(): ObcTextboxSize {\n return readoutSecondarySize(this.resolvedSize);\n }\n\n private get valueSize(): ObcTextboxSize {\n // The value de-emphasises (secondary size) whenever the setpoint is the\n // focus — while actively adjusting (`touching`) or while a flip-flop holds\n // the value away from the setpoint — mirroring the flip-flop convention.\n if (this.isSetpointEmphasized) {\n return this.secondarySize;\n }\n return this.primarySize;\n }\n\n private get setpointSize(): ObcTextboxSize {\n return this.isSetpointEmphasized ? this.primarySize : this.secondarySize;\n }\n\n /** Value font weight passes straight to obc-textbox; regular when unset. Colour is separate. */\n private get valueWeight(): ObcTextboxFontWeight {\n return this.valueOptions?.weight ?? ObcTextboxFontWeight.regular;\n }\n\n /** Setpoint is SemiBold only while emphasised, otherwise regular weight. */\n private get setpointWeight(): ObcTextboxFontWeight {\n return readoutSetpointWeight(this.isSetpointEmphasized);\n }\n\n private numericFormatOptions(maxDigits: number): ReadoutNumericFormatOptions {\n return readoutNumericFormatOptions(maxDigits, this.resolvedFractionDigits);\n }\n\n /** classMap fragment for a block / source carrying per-block data quality. */\n private dataQualityClasses(\n dataQuality: ReadoutDataQuality | undefined\n ): Record<string, boolean> {\n return readoutDataQualityClasses(dataQuality);\n }\n\n /**\n * Forward the matching readout icon slot into the block's single `icon`\n * slot. The variant's default marker lives in `obc-readout-block` and shows\n * when nothing is assigned here (an empty forwarded slot flattens to nothing).\n */\n private renderForwardedIcon(variant: ReadoutBlockVariant): TemplateResult {\n if (variant === ReadoutBlockVariant.setpoint) {\n return html`<slot name=\"setpoint-icon\" slot=\"icon\"></slot>`;\n }\n if (variant === ReadoutBlockVariant.advice) {\n return html`<slot name=\"advice-icon\" slot=\"icon\"></slot>`;\n }\n return html`<slot name=\"value-icon\" slot=\"icon\"></slot>`;\n }\n\n private renderBlock(config: {\n variant: ReadoutBlockVariant;\n value: number | null | undefined;\n valueSize: ObcTextboxSize;\n enhanced: boolean;\n weight: ObcTextboxFontWeight;\n hintedZeros: boolean;\n spaceReserver?: string;\n off?: boolean;\n hasDegree?: boolean;\n hasIcon?: boolean;\n touching?: boolean;\n hidePhase?: ReadoutBlockHidePhase;\n dataQuality?: ReadoutBlockDataQuality;\n alert?: false | AlertFrameConfig;\n /**\n * Invisible width-reserving duplicate (see\n * {@link renderSetpointWidthReserve}): skips the forwarded icon slot so\n * the visible block keeps the slotted content — the block's default\n * marker has the same fixed tier width.\n */\n ghost?: boolean;\n }): TemplateResult {\n // The block owns the formatting, hinted zeros, reserver, degree and icon; the\n // readout keeps the density tier (`size`) and the resolved per-block number\n // size (`valueSize`) so flip-flop/pop-up emphasis stays a readout decision.\n return html`\n <obc-readout-block\n exportparts=\"block, block-content, block-text, block-icon, degree\"\n .variant=${config.variant}\n .value=${config.value ?? null}\n .size=${this.resolvedSize}\n .valueSize=${config.valueSize}\n .enhanced=${config.enhanced}\n .weight=${config.weight}\n .hasDegree=${config.hasDegree ?? false}\n .hasIcon=${config.hasIcon ?? false}\n .fractionDigits=${this.resolvedFractionDigits}\n .maxDigits=${this.resolvedMaxDigits}\n .hintedZeros=${config.hintedZeros}\n .spaceReserver=${config.spaceReserver}\n .off=${config.off ?? false}\n .offText=${this.offText}\n .touching=${config.touching ?? false}\n .hidePhase=${config.hidePhase ?? ReadoutBlockHidePhase.none}\n .dataQuality=${config.dataQuality}\n .alert=${config.alert ?? false}\n >\n ${config.ghost ? nothing : this.renderForwardedIcon(config.variant)}\n </obc-readout-block>\n `;\n }\n\n /**\n * A cap-height `°` column whose width scales with the value size, rendered\n * after the value block. Setpoint / advice blocks render their own degree via\n * `obc-readout-block`.\n */\n private renderDegreeGlyph(size: ObcTextboxSize): TemplateResult {\n return html`\n <span\n class=${classMap({\n 'degree-column': true,\n [`degree-${size}`]: true,\n 'tone-enhanced': this.rowEnhanced,\n })}\n part=\"degree\"\n >\n <obc-textbox class=\"degree-glyph\" .size=${size} alignment=\"center\"\n >°</obc-textbox\n >\n </span>\n `;\n }\n\n /**\n * The column rendered after the value digits:\n *\n * - `hasDegree`: a cap-height `°` column whose width scales with the value size.\n * - `hasDegreeSpacer` (non-degree readouts): an invisible reserve of the same\n * width, so this readout's value digits stay aligned with degree readouts\n * in the same column.\n */\n private renderDegreeColumn(\n size: ObcTextboxSize = this.valueSize\n ): TemplateResult | typeof nothing {\n if ((this.hasDegree ?? false) && !this.off) {\n return this.renderDegreeGlyph(size);\n }\n if (this.hasDegreeSpacer ?? false) {\n return html`<span\n class=\"degree-spacer\"\n part=\"degree-spacer\"\n aria-hidden=\"true\"\n ></span>`;\n }\n return nothing;\n }\n\n private renderTextbox(\n role: 'label' | 'unit' | 'source',\n text: string,\n reserver?: string,\n blockState?: ReadoutBlockState\n ): TemplateResult {\n const weight =\n role === 'label'\n ? ObcTextboxFontWeight.semibold\n : ObcTextboxFontWeight.regular;\n const box = html`\n <obc-textbox\n class=${classMap({\n [role]: true,\n ...this.dataQualityClasses(blockState?.dataQuality),\n })}\n part=${role}\n .size=${ObcTextboxSize.xs}\n .fontWeight=${weight}\n alignment=\"left\"\n >\n ${text}\n ${reserver ? html`<span slot=\"length\">${reserver}</span>` : nothing}\n </obc-textbox>\n `;\n return wrapWithAlertFrame(blockState?.alert ?? false, box);\n }\n\n private get setpointHidePhase(): ReadoutBlockHidePhase {\n const popUpAtSetpoint =\n this.isPopUp && this.isAtSetpoint && !this.setpointTouching;\n return resolveSetpointHidePhase(\n popUpAtSetpoint,\n this.deferredSetpointHidePhase\n );\n }\n\n private renderAdviceBlock(): TemplateResult {\n return this.renderBlock({\n variant: ReadoutBlockVariant.advice,\n value: this.advice,\n valueSize: this.secondarySize,\n enhanced: false,\n weight: ObcTextboxFontWeight.regular,\n hintedZeros: this.adviceOptions?.hintedZeros ?? false,\n spaceReserver: this.adviceOptions?.spaceReserver,\n hasDegree: this.hasDegree ?? false,\n dataQuality: this.adviceOptions?.dataQuality,\n alert: this.adviceOptions?.alert,\n });\n }\n\n private renderSetpointBlock(): TemplateResult {\n return this.renderBlock({\n variant: ReadoutBlockVariant.setpoint,\n value: this.setpoint,\n valueSize: this.setpointSize,\n // Value and setpoint share the enhanced colour state (both neutral\n // or both enhanced); the setpoint is bold only while emphasised.\n enhanced: this.rowEnhanced,\n weight: this.setpointWeight,\n hintedZeros: this.setpointOptions?.hintedZeros ?? false,\n spaceReserver: this.setpointOptions?.spaceReserver,\n hasDegree: this.hasDegree ?? false,\n touching: this.setpointTouching,\n hidePhase: this.setpointHidePhase,\n dataQuality: this.setpointOptions?.dataQuality,\n alert: this.setpointOptions?.alert,\n });\n }\n\n /**\n * The value reading: the value block and its degree column (or spacer)\n * grouped in one relatively-positioned wrapper so the value alert frame AND\n * the value data-quality chip can wrap both together. Unlike\n * `obc-readout-list-item` the unit is not part of the reading — it lives in\n * the label/unit meta zone.\n */\n private renderValueReading(): TemplateResult {\n return html`\n <div\n class=${classMap({\n 'value-reading': true,\n ...this.dataQualityClasses(this.valueOptions?.dataQuality),\n })}\n part=\"value-reading\"\n >\n ${this.renderBlock({\n variant: ReadoutBlockVariant.value,\n value: this.value,\n valueSize: this.valueSize,\n enhanced: this.rowEnhanced,\n weight: this.valueWeight,\n hintedZeros: this.valueOptions?.hintedZeros ?? false,\n spaceReserver: this.valueOptions?.spaceReserver,\n off: this.off,\n hasIcon: this.valueOptions?.hasIcon ?? false,\n })}\n ${this.renderDegreeColumn()} ${this.renderValueAlertOverlay()}\n </div>\n `;\n }\n\n /**\n * The value alert frame, drawn as a pure overlay around the value reading\n * (value + degree). It reserves no space — the `obc-alert-frame` sits in an\n * absolutely-positioned box offset outward (see `.value-alert-overlay` in the\n * CSS) so its stroke is centred on the 4px/2px padding line and toggling it\n * never shifts content. Renders only when `valueOptions.alert` is a config\n * object.\n */\n private renderValueAlertOverlay(): TemplateResult | typeof nothing {\n const alert = this.valueOptions?.alert;\n if (typeof alert !== 'object' || alert === null) {\n return nothing;\n }\n const thickness = alert.thickness ?? ObcAlertFrameThickness.Small;\n return html`\n <div\n class=${classMap({\n 'value-alert-overlay': true,\n // The outward offset is thickness-dependent (see the CSS): large frames\n // draw a wider outline, so the box must sit further out to stay centred.\n 'thickness-large': thickness === ObcAlertFrameThickness.Large,\n })}\n aria-hidden=\"true\"\n >\n <obc-alert-frame\n part=\"value-alert-frame\"\n .type=${alert.type ?? ObcAlertFrameType.Regular}\n .thickness=${thickness}\n .status=${alert.status ?? AlertType.Alarm}\n .mode=${alert.mode ?? ObcAlertFrameMode.ackedActive}\n .showIcon=${alert.showIcon ?? false}\n .showAlertCategoryIcon=${alert.showAlertCategoryIcon ?? true}\n .wrapContent=${false}\n .fullWidth=${false}\n ></obc-alert-frame>\n </div>\n `;\n }\n\n /** The label/unit meta zone; `stacking` picks the inline or stacked arrangement. */\n private renderMetaZone(): TemplateResult | typeof nothing {\n if (!this.label && !this.unit) {\n return nothing;\n }\n // Horizontal readouts always stack the label over the unit beside the value.\n const stacked =\n this.isHorizontal || this.resolvedStacking === ReadoutStacking.stacked;\n return html`\n <div\n class=${classMap({\n meta: true,\n 'meta-inline': !stacked,\n 'meta-stacked': stacked,\n 'label-only': !!this.label && !this.unit,\n 'unit-only': !!this.unit && !this.label,\n })}\n part=\"meta-wrapper\"\n >\n ${this.label ? this.renderTextbox('label', this.label) : nothing}\n ${this.unit\n ? this.renderTextbox(\n 'unit',\n this.unit,\n this.unitOptions?.spaceReserver\n )\n : nothing}\n </div>\n `;\n }\n\n private renderSourceContent(): TemplateResult {\n const interaction = this.resolvedSourceInteraction;\n const src = this.src ?? '';\n\n // The interactive variants keep the source's per-block state: the\n // data-quality chip moves onto the button and the alert frame wraps it,\n // matching the plain-text branch (renderTextbox) below.\n const buttonClasses = classMap({\n 'source-button': true,\n ...this.dataQualityClasses(this.srcOptions?.dataQuality),\n });\n\n if (interaction === ReadoutSourceInteraction.picker) {\n const button = html`\n <obc-button\n class=${buttonClasses}\n variant=\"flat\"\n .fullWidth=${false}\n showTrailingIcon\n @click=${() => {\n this.sourcePickerContentVisible = !this.sourcePickerContentVisible;\n }}\n >\n <obi-drop-down-google slot=\"trailing-icon\"></obi-drop-down-google>\n ${src}\n </obc-button>\n `;\n return wrapWithAlertFrame(this.srcOptions?.alert ?? false, button);\n }\n\n if (interaction === ReadoutSourceInteraction.flyout) {\n const button = html`\n <obc-button\n class=${buttonClasses}\n variant=\"flat\"\n .fullWidth=${false}\n showTrailingIcon\n @click=${() => {\n this.dispatchEvent(\n new CustomEvent('source-flyout-click', {\n bubbles: true,\n composed: true,\n detail: {src},\n })\n );\n }}\n >\n <obi-chevron-right-google\n slot=\"trailing-icon\"\n ></obi-chevron-right-google>\n ${src}\n </obc-button>\n `;\n return wrapWithAlertFrame(this.srcOptions?.alert ?? false, button);\n }\n\n return this.renderTextbox(\n 'source',\n src,\n this.srcOptions?.spaceReserver,\n this.srcOptions\n );\n }\n\n /** The source row (vertical) / segment (horizontal), with its auto divider. */\n private renderSource(): TemplateResult | typeof nothing {\n if (!this.hasSrc) {\n return nothing;\n }\n return html`\n <div\n class=${classMap({\n divider: true,\n 'divider-horizontal': !this.isHorizontal,\n 'divider-vertical': this.isHorizontal,\n })}\n part=\"divider\"\n aria-hidden=\"true\"\n ></div>\n <div class=\"source-row\" part=\"source-wrapper\">\n ${this.renderSourceContent()}\n </div>\n `;\n }\n\n // ---------- Source picker (context menu built from src-picker-content) ----------\n\n private getSourcePickerNavigationItems(): HTMLElement[] {\n const assignedElements =\n this.sourcePickerSlot?.assignedElements({flatten: true}) ?? [];\n\n return assignedElements.flatMap((element) => {\n if (!(element instanceof HTMLElement)) {\n return [];\n }\n if (element.localName === 'obc-navigation-item') {\n return [element];\n }\n return Array.from(\n element.querySelectorAll<HTMLElement>('obc-navigation-item')\n );\n });\n }\n\n private createSourcePickerOptionIcon(element: HTMLElement) {\n const iconElement = element.querySelector('[slot=\"icon\"]');\n if (!(iconElement instanceof HTMLElement)) {\n return undefined;\n }\n return html`${iconElement.cloneNode(true)}`;\n }\n\n private getSourcePickerItemInfo(item: HTMLElement, index: number) {\n const itemWithValues = item as HTMLElement & {\n label?: string;\n value?: string;\n };\n const itemLabel = itemWithValues.label || item.getAttribute('label') || '';\n const itemValue =\n item.getAttribute('data-value') ||\n itemWithValues.value ||\n item.getAttribute('value') ||\n itemLabel ||\n `source-option-${index}`;\n\n return {itemLabel, itemValue};\n }\n\n private findSourcePickerOptionElement(value: string) {\n const navigationItems = this.getSourcePickerNavigationItems();\n for (const [index, item] of navigationItems.entries()) {\n const {itemValue} = this.getSourcePickerItemInfo(item, index);\n if (itemValue === value) {\n return item;\n }\n }\n return undefined;\n }\n\n private syncSourcePickerOptions = () => {\n this.sourcePickerOptions = this.getSourcePickerNavigationItems().map(\n (item, index) => {\n const {itemLabel, itemValue} = this.getSourcePickerItemInfo(\n item,\n index\n );\n return {\n value: itemValue,\n label: itemLabel,\n icon: this.createSourcePickerOptionIcon(item),\n };\n }\n );\n };\n\n private handleSourcePickerItemClick(\n event: ObcContextMenuInputItemClickEvent\n ) {\n this.dispatchEvent(\n new CustomEvent('source-change', {\n bubbles: true,\n composed: true,\n detail: {\n value: event.detail.value,\n label: event.detail.option?.label,\n },\n })\n );\n this.findSourcePickerOptionElement(event.detail.value)?.click();\n this.sourcePickerContentVisible = false;\n }\n\n /**\n * The context menu highlights options by their VALUE, while `src` holds the\n * displayed source text — which may be an option's label when the two\n * differ (e.g. `data-value=\"gps-1\"` with label \"GPS 1\"). Resolve the current\n * source to the matching option's value (by value or label) so the open\n * picker always highlights the active source.\n */\n private get selectedSourceValues(): string[] {\n if (!this.src) {\n return [];\n }\n const match = this.sourcePickerOptions.find(\n (option) => option.value === this.src || option.label === this.src\n );\n return [match?.value ?? this.src];\n }\n\n private renderSourcePickerContent(): TemplateResult | typeof nothing {\n if (\n this.resolvedSourceInteraction !== ReadoutSourceInteraction.picker ||\n !this.sourcePickerContentVisible\n ) {\n return nothing;\n }\n return html`\n <obc-context-menu-input\n .type=${ContextMenuType.Regular}\n .options=${this.sourcePickerOptions}\n .selectedValues=${this.selectedSourceValues}\n class=\"source-picker-content\"\n @item-click=${this.handleSourcePickerItemClick}\n @close=${() => {\n this.sourcePickerContentVisible = false;\n }}\n ></obc-context-menu-input>\n `;\n }\n\n private renderSourcePickerSlot(): TemplateResult {\n return html`\n <slot\n name=\"src-picker-content\"\n hidden\n @slotchange=${this.syncSourcePickerOptions}\n ></slot>\n `;\n }\n\n // ---------- Layouts ----------\n\n /**\n * An invisible primary-size duplicate of a dynamic setpoint row's content,\n * stacked under the visible block in the same grid cell purely to reserve\n * width. With both rows permanently holding their emphasised width, the\n * widest row — and therefore the readout's total width — stays constant\n * while a flip-flop swaps the value/setpoint sizes, while a touch swap\n * runs, and while a pop-up setpoint fades out, so the meta zone and source\n * never shift. This is the vertical analogue of the horizontal arrangement,\n * where the swapped pair sits on one row and its summed width is constant\n * by construction (the designer's flip-flop invariant). Only the vertical\n * direction needs it; `always-visible` layouts are untouched.\n */\n private renderSetpointWidthReserve(\n kind: 'setpoint' | 'value'\n ): TemplateResult | typeof nothing {\n if (!this.hasDynamicSetpoint || this.isHorizontal) {\n return nothing;\n }\n const content =\n kind === 'setpoint'\n ? this.renderBlock({\n variant: ReadoutBlockVariant.setpoint,\n value: this.setpoint,\n valueSize: this.primarySize,\n enhanced: false,\n // The emphasised setpoint is SemiBold — reserve its widest form.\n weight: ObcTextboxFontWeight.semibold,\n hintedZeros: this.setpointOptions?.hintedZeros ?? false,\n spaceReserver: this.setpointOptions?.spaceReserver,\n hasDegree: this.hasDegree ?? false,\n alert: this.setpointOptions?.alert,\n ghost: true,\n })\n : html`${this.renderBlock({\n variant: ReadoutBlockVariant.value,\n value: this.value,\n valueSize: this.primarySize,\n enhanced: false,\n weight: this.valueWeight,\n hintedZeros: this.valueOptions?.hintedZeros ?? false,\n spaceReserver: this.valueOptions?.spaceReserver,\n off: this.off,\n hasIcon: this.valueOptions?.hasIcon ?? false,\n ghost: true,\n })}${this.renderDegreeColumn(this.primarySize)}`;\n return html`<div class=\"setpoint-width-reserve\" aria-hidden=\"true\">\n ${content}\n </div>`;\n }\n\n /**\n * Vertical: advice / setpoint / value rows right-aligned in a cluster, the\n * label+unit meta zone below, then the source row under an auto divider.\n * `alignment` re-aligns the whole column for stacked readouts.\n */\n private renderVerticalLayout(): TemplateResult {\n return html`\n <div class=\"value-cluster\" part=\"value-cluster\">\n ${this.hasAdvice\n ? html`<div class=\"advice-row\" part=\"advice-wrapper\">\n ${this.renderAdviceBlock()}\n </div>`\n : nothing}\n ${this.hasSetpoint\n ? html`<div class=\"setpoint-row\" part=\"setpoint-wrapper\">\n ${this.renderSetpointBlock()}\n ${this.renderSetpointWidthReserve('setpoint')}\n </div>`\n : nothing}\n ${this.hasValue\n ? html`<div class=\"value-row\" part=\"value-wrapper\">\n ${this.renderValueReading()}\n ${this.renderSetpointWidthReserve('value')}\n </div>`\n : nothing}\n </div>\n ${this.renderMetaZone()} ${this.renderSource()}\n `;\n }\n\n /**\n * Horizontal: advice, setpoint, value and the stacked label/unit meta flow on\n * one cap-height-aligned row, with the source at the end after an auto\n * divider.\n */\n private renderHorizontalLayout(): TemplateResult {\n return html`\n <div class=\"inline-row\" part=\"value-cluster\">\n ${this.hasAdvice\n ? html`<div class=\"advice-row\" part=\"advice-wrapper\">\n ${this.renderAdviceBlock()}\n </div>`\n : nothing}\n ${this.hasSetpoint\n ? html`<div class=\"setpoint-row\" part=\"setpoint-wrapper\">\n ${this.renderSetpointBlock()}\n </div>`\n : nothing}\n ${this.hasValue\n ? html`<div class=\"value-row\" part=\"value-wrapper\">\n ${this.renderValueReading()}\n </div>`\n : nothing}\n ${this.renderMetaZone()} ${this.renderSource()}\n </div>\n `;\n }\n\n override updated(changed: Map<string, unknown>): void {\n super.updated(changed);\n\n if (changed.has('sourcePickerContentVisible')) {\n if (this.sourcePickerContentVisible) {\n window.addEventListener('pointerdown', this.onWindowPointerDown, true);\n } else {\n window.removeEventListener(\n 'pointerdown',\n this.onWindowPointerDown,\n true\n );\n }\n }\n\n const firstUpdate = !this.hasCompletedFirstUpdate;\n this.hasCompletedFirstUpdate = true;\n\n // Pop-up: hide the setpoint shortly after the value reaches it. `touching`\n // and the non-pop-up modes keep the setpoint visible.\n if (!this.isPopUp || this.setpointTouching) {\n this.clearDeferredSetpointHide();\n return;\n }\n\n const shouldHide = this.hasSetpoint && this.isAtSetpoint;\n\n if (firstUpdate) {\n // Settle to the resting state on mount without animating.\n this.deferredSetpointHidePhase = shouldHide\n ? ReadoutBlockHidePhase.hidden\n : ReadoutBlockHidePhase.none;\n return;\n }\n\n if (!shouldHide) {\n this.clearDeferredSetpointHide();\n return;\n }\n\n if (this.deferredSetpointHidePhase !== ReadoutBlockHidePhase.none) {\n return;\n }\n\n this.deferredSetpointHidePhase = ReadoutBlockHidePhase.hiding;\n window.clearTimeout(this.deferredSetpointHideTimer);\n this.deferredSetpointHideTimer = window.setTimeout(() => {\n this.deferredSetpointHidePhase = ReadoutBlockHidePhase.hidden;\n this.deferredSetpointHideTimer = undefined;\n }, 100);\n }\n\n private clearDeferredSetpointHide(): void {\n if (this.deferredSetpointHidePhase !== ReadoutBlockHidePhase.none) {\n this.deferredSetpointHidePhase = ReadoutBlockHidePhase.none;\n }\n window.clearTimeout(this.deferredSetpointHideTimer);\n this.deferredSetpointHideTimer = undefined;\n }\n\n override disconnectedCallback(): void {\n window.removeEventListener('pointerdown', this.onWindowPointerDown, true);\n window.clearTimeout(this.deferredSetpointHideTimer);\n this.deferredSetpointHideTimer = undefined;\n // Settle a mid-flight hide to its end state. Without this, disconnecting\n // during the 100ms window leaves the phase stuck at 'hiding' (the timer that\n // would advance it to 'hidden' is gone), so a later reconnect never resolves.\n if (this.deferredSetpointHidePhase === ReadoutBlockHidePhase.hiding) {\n this.deferredSetpointHidePhase = ReadoutBlockHidePhase.hidden;\n }\n super.disconnectedCallback();\n }\n\n override render() {\n const dataQuality = this.dataQuality;\n const classes = classMap({\n readout: true,\n [`size-${this.resolvedSize}`]: true,\n [`direction-${this.resolvedDirection}`]: true,\n [`stacking-${this.resolvedStacking}`]: true,\n [`alignment-${this.resolvedAlignment}`]: true,\n [`priority-${this.resolvedPriority}`]: true,\n 'data-low-integrity': dataQuality === ReadoutDataQuality.lowIntegrity,\n 'data-invalid': dataQuality === ReadoutDataQuality.invalid,\n 'flip-flop': this.isFlipFlop,\n 'setpoint-dynamic': this.hasDynamicSetpoint,\n });\n\n const root = html`\n <div class=${classes} part=\"root\">\n ${this.isHorizontal\n ? this.renderHorizontalLayout()\n : this.renderVerticalLayout()}\n ${this.renderSourcePickerSlot()}\n </div>\n ${this.renderSourcePickerContent()}\n `;\n\n // `alert` accepts `boolean` (so the generated Angular wrapper's widened\n // `boolean` type assigns cleanly), but `wrapWithAlertFrame` ignores\n // non-object truthy values. Normalise `true` → a default frame `{}` so it\n // isn't a silent no-op; `false`/object pass through. The frame hugs the\n // readout (no fullWidth), matching the previous behaviour.\n const alert = this.alert === true ? {} : this.alert;\n return wrapWithAlertFrame(alert, root);\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-readout': ObcReadout;\n }\n}\n"],"names":["ReadoutDirection","ReadoutStacking","ReadoutAlignment","ReadoutSourceInteraction"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"readout.js","sources":["../../../src/navigation-instruments/readout/readout.ts"],"sourcesContent":["import {LitElement, html, nothing, unsafeCSS, type TemplateResult} from 'lit';\nimport {property, query, state} from 'lit/decorators.js';\nimport {classMap} from 'lit/directives/class-map.js';\nimport componentStyle from './readout.css?inline';\nimport {customElement} from '../../decorator.js';\nimport '../../components/textbox/textbox.js';\nimport {\n ObcTextboxSize,\n ObcTextboxFontWeight,\n} from '../../components/textbox/textbox.js';\nimport '../../building-blocks/readout-block/readout-block.js';\nimport {\n ReadoutBlockVariant,\n ReadoutBlockSize,\n ReadoutBlockDataQuality,\n ReadoutBlockHidePhase,\n} from '../../building-blocks/readout-block/readout-block.js';\nimport {\n ReadoutListItemSetpointInteraction,\n type ReadoutBlockState,\n type ReadoutValueOptions,\n type ReadoutSetpointOptions,\n type ReadoutAdviceOptions,\n type ReadoutReserverOptions,\n type ReadoutSrcOptions,\n} from '../readout-list-item/readout-list-item.js';\nimport {Priority} from '../types.js';\nimport {\n assertReadoutValueType,\n resolveReadoutNumericValue,\n ReadoutValueType,\n type ReadoutNumericFormatOptions,\n} from './readout-formatters.js';\nimport {\n isDisplayedAtSetpoint,\n readoutNumericFormatOptions,\n readoutPrimarySize,\n readoutSecondarySize,\n readoutSetpointWeight,\n readoutDataQualityClasses,\n resolveSetpointHidePhase,\n} from './readout-shared.js';\nimport {\n type AlertFrameConfig,\n wrapWithAlertFrame,\n ObcAlertFrameType,\n ObcAlertFrameThickness,\n ObcAlertFrameMode,\n} from '../../components/alert-frame/alert-frame.js';\nimport {AlertType} from '../../types.js';\nimport '../../components/button/button.js';\nimport '../../components/context-menu-input/context-menu-input.js';\nimport {\n ContextMenuType,\n type ContextMenuOption,\n type ObcContextMenuInputItemClickEvent,\n} from '../../components/context-menu-input/context-menu-input.js';\nimport '../../icons/icon-chevron-right-google.js';\nimport '../../icons/icon-drop-down-google.js';\n\n// Re-exported so consumers configure the readout without a second import path.\n// The option interfaces and enums are shared with `obc-readout-list-item` on\n// purpose: the two components are layout variants of the same primitives +\n// per-block options API and may merge in a future release.\nexport {ObcTextboxFontWeight} from '../../components/textbox/textbox.js';\nexport {ReadoutValueType} from './readout-formatters.js';\nexport type {\n ReadoutBlockState,\n ReadoutValueOptions,\n ReadoutSetpointOptions,\n ReadoutAdviceOptions,\n ReadoutReserverOptions,\n ReadoutSrcOptions,\n} from '../readout-list-item/readout-list-item.js';\n\n/**\n * Density/size scale of the readout (an alias of `ReadoutBlockSize`).\n * - `small`: regular value typography (smallest, densest).\n * - `medium`: medium value typography.\n * - `large`: large value typography.\n */\nexport const ReadoutSize = ReadoutBlockSize;\nexport type ReadoutSize = ReadoutBlockSize;\n\n/**\n * Colour emphasis of the value (an alias of the shared instrument `Priority`;\n * same values as `ReadoutListItemPriority`).\n * - `regular`: neutral.\n * - `enhanced`: accented (in-command) colour.\n */\nexport const ReadoutPriority = Priority;\nexport type ReadoutPriority = Priority;\n\n/**\n * Measurement quality of the value (an alias of `ReadoutBlockDataQuality`).\n * Orthogonal to the readout-level `alert` – a low-integrity or invalid value\n * can also sit inside an alert frame.\n */\nexport const ReadoutDataQuality = ReadoutBlockDataQuality;\nexport type ReadoutDataQuality = ReadoutBlockDataQuality;\n\n/**\n * How the setpoint segment behaves relative to the value (an alias of\n * `ReadoutListItemSetpointInteraction`).\n * - `always-visible` (default): the setpoint is always shown.\n * - `flip-flop`: value and setpoint swap emphasis (size) as the value reaches\n * the setpoint.\n * - `pop-up`: the setpoint is shown only while the value has not reached it,\n * then fades out (100ms) once value === setpoint.\n */\nexport const ReadoutSetpointInteraction = ReadoutListItemSetpointInteraction;\nexport type ReadoutSetpointInteraction = ReadoutListItemSetpointInteraction;\n\n/**\n * Flow direction of the readout.\n * - `vertical` (default): advice / setpoint / value stack on top of the\n * label+unit meta zone and the source row (Figma \"Readout Group / Vertical\"\n * and \"Readout Stack\").\n * - `horizontal`: all segments flow on one cap-height-aligned row, with the\n * label stacked over the unit beside the value (Figma \"Readout Group /\n * Horizontal\").\n */\nexport enum ReadoutDirection {\n vertical = 'vertical',\n horizontal = 'horizontal',\n}\n\n/**\n * Arrangement of the label/unit meta zone in a vertical readout.\n * - `inline` (default): label and unit share one row below the value (Figma\n * \"Readout Group / Vertical\").\n * - `stacked`: label and unit render on separate rows (Figma \"Readout Stack\"),\n * arranged by `alignment`.\n */\nexport enum ReadoutStacking {\n inline = 'inline',\n stacked = 'stacked',\n}\n\n/**\n * Cross-axis alignment of a stacked vertical readout (Figma \"Readout Stack\"\n * Alignment axis).\n * - `vertical` (default): right-aligned column.\n * - `left`: left-aligned column.\n * - `center`: centered column.\n */\nexport enum ReadoutAlignment {\n vertical = 'vertical',\n left = 'left',\n center = 'center',\n}\n\n/**\n * Interactivity of the source row.\n * - `none` (default): plain source text (same rendering as\n * `obc-readout-list-item`).\n * - `picker`: a flat button with a drop-down icon that opens a context menu\n * built from the `src-picker-content` slot; selecting an option fires\n * `source-change`.\n * - `flyout`: a flat button with a chevron icon that fires\n * `source-flyout-click`.\n */\nexport enum ReadoutSourceInteraction {\n none = 'none',\n picker = 'picker',\n flyout = 'flyout',\n}\n\n/**\n * Per-source options. Extends the shared per-block state (data quality, alert,\n * space reserver) with the readout's source interactivity.\n */\nexport interface ReadoutSourceOptions extends ReadoutSrcOptions {\n /** Interactivity of the source row (default `none`). */\n interaction?: ReadoutSourceInteraction;\n}\n\n/**\n * `<obc-readout>` – An instrument readout: a value with optional setpoint,\n * advice, label, unit, and source, arranged vertically or horizontally.\n *\n * A layout sibling of `<obc-readout-list-item>` built from the same\n * cap-height \"readout building blocks\" (`obc-readout-block`): dynamic data is\n * passed as top-level primitives (`value`, `setpoint`, `advice`, `label`,\n * `unit`, `src`), global layout/format via top-level props (`size`,\n * `priority`, `direction`, `stacking`, `alignment`, `hasDegree`,\n * `dataQuality`, `alert`, …) and per-block tweaks via one object per block\n * (`valueOptions`, `setpointOptions`, `adviceOptions`, `unitOptions`,\n * `srcOptions`).\n *\n * ### Features\n * - **Building blocks:** value, optional setpoint, and optional advice\n * segments, each cap-height-aligned and able to reserve a stable width.\n * - **Sizes:** `small`, `medium`, `large` density scales.\n * - **Direction:** `vertical` (blocks above a label+unit meta zone and source\n * row) or `horizontal` (all segments on one row).\n * - **Stacking & alignment:** vertical readouts arrange label/unit `inline`\n * or `stacked`; stacked readouts align `vertical` (right), `left`, or\n * `center`.\n * - **Priority:** `regular`/`enhanced` colour emphasis; per-value `weight`\n * is independent of colour.\n * - **Setpoint interactions:** `always-visible`, `flip-flop` (emphasis swap),\n * and `pop-up` (fade-out at setpoint), plus the `touching` focus state.\n * - **Data quality:** `low-integrity`/`invalid` styling, per block or for the\n * whole readout, combinable with `alert`.\n * - **Alert frame:** optional `alert` wrapper (caution/warning/alarm/level).\n * - **Source:** plain text by default; opt-in `picker` (context menu) or\n * `flyout` interactivity via `srcOptions.interaction`.\n * - **Formatting:** shared `fractionDigits`, width reservation via\n * `maxDigits` and per-segment `hintedZeros`; a `null` value renders a dash.\n * - **Text values:** `valueType=\"text\"` renders `value` verbatim (e.g.\n * `\"Auto\"`) instead of formatting it as a number.\n *\n * ### Usage Guidelines\n * Use for stand-alone instrument readouts and readouts embedded in\n * instruments. Prefer `<obc-readout-list-item>` for dense rows in\n * lists/tables (label left, value right) and `<obc-readout-list>` for\n * auto-aligned groups of rows.\n *\n * @experimental Part of the primitives + per-block options Readout API pilot;\n * the API may change in a future release.\n *\n * ### Slots\n * | Slot Name | Renders When | Purpose |\n * |--------------------|---------------------------------------|--------------------------------------|\n * | value-icon | `valueOptions.hasIcon` | Icon before the value. |\n * | setpoint-icon | `hasSetpoint` | Overrides the default setpoint icon. |\n * | advice-icon | `hasAdvice` | Overrides the default advice icon. |\n * | src-picker-content | `srcOptions.interaction == 'picker'` | Source picker context-menu content. |\n *\n * @fires source-change {CustomEvent<{value: string, label?: string}>} Fired when a source picker option is selected.\n * @fires source-flyout-click {CustomEvent<{src: string}>} Fired when the source row is clicked while `srcOptions.interaction == 'flyout'`.\n *\n * @slot value-icon - Icon before the value.\n * @slot setpoint-icon - Overrides the default setpoint icon.\n * @slot advice-icon - Overrides the default advice icon.\n * @slot src-picker-content - Provides the source picker context menu content.\n */\n@customElement('obc-readout')\nexport class ObcReadout extends LitElement {\n // Primitives (dynamic data)\n @property({type: String}) label?: string;\n @property({type: String}) unit?: string;\n @property({type: String}) src?: string;\n\n /**\n * Layout switch: `false` renders a deliberately value-less (label-only)\n * readout that hugs its remaining parts. For a temporarily missing value\n * keep `hasValue` and set `value` to `null` instead — the dash keeps the\n * value block at full size, so the layout does not shift when data arrives.\n */\n @property({type: Boolean, attribute: false}) hasValue = true;\n /**\n * The value; `null` renders a dash. A number by default, or text when\n * {@link valueType} is `text`.\n */\n @property({type: String}) value: number | string | null = null;\n /**\n * How {@link value} is interpreted. `number` (default) formats it via\n * `fractionDigits`; `text` renders it verbatim and ignores the numeric\n * format options. Passing text while this is `number` throws.\n */\n @property({type: String}) valueType: ReadoutValueType =\n ReadoutValueType.number;\n /** Render the value as `offText` (e.g. equipment powered down). Affects the value only. */\n @property({type: Boolean}) off = false;\n /** Text shown in place of the value when `off` is true. @availableWhen off==true */\n @property({type: String}) offText = 'OFF';\n\n @property({type: Boolean}) hasSetpoint = false;\n /** @availableWhen hasSetpoint==true */\n @property({type: Number}) setpoint?: number;\n\n @property({type: Boolean}) hasAdvice = false;\n /** @availableWhen hasAdvice==true */\n @property({type: Number}) advice?: number;\n\n // Global layout/format (each defaults via its `resolved*` getter where useful).\n @property({type: String}) size?: ReadoutSize;\n @property({type: String}) priority?: ReadoutPriority;\n @property({type: String}) direction?: ReadoutDirection;\n /** @availableWhen direction==vertical */\n @property({type: String}) stacking?: ReadoutStacking;\n /** @availableWhen direction==vertical && stacking==stacked */\n @property({type: String}) alignment?: ReadoutAlignment;\n @property({type: Boolean}) hasDegree = false;\n /** @availableWhen hasDegree==false */\n @property({type: Boolean}) hasDegreeSpacer = false;\n /**\n * Also formats the numeric setpoint / advice blocks, which stay numeric\n * even when the value is text.\n * @availableWhen valueType==number || hasSetpoint==true || hasAdvice==true\n */\n @property({type: Number}) fractionDigits = 0;\n /**\n * Also formats the numeric setpoint / advice blocks, which stay numeric\n * even when the value is text.\n * @availableWhen valueType==number || hasSetpoint==true || hasAdvice==true\n */\n @property({type: Number}) maxDigits = 0;\n @property({type: String}) dataQuality?: ReadoutDataQuality;\n // `boolean | …` (not `false | …`): the generated Angular wrapper widens a\n // literal-`false` union to `boolean`, which then won't assign back to a\n // `false`-typed element property. `wrapWithAlertFrame` treats any non-object\n // (incl. `true`) as \"no frame\", so accepting `boolean` is harmless.\n @property({type: Object}) alert: boolean | AlertFrameConfig = false;\n\n // Per-block configuration — one object per block (see the Readout*Options types).\n /** @availableWhen hasValue==true */\n @property({type: Object}) valueOptions?: ReadoutValueOptions;\n /** @availableWhen hasSetpoint==true */\n @property({type: Object}) setpointOptions?: ReadoutSetpointOptions;\n /** @availableWhen hasAdvice==true */\n @property({type: Object}) adviceOptions?: ReadoutAdviceOptions;\n /** @availableWhen unit!='' */\n @property({type: Object}) unitOptions?: ReadoutReserverOptions;\n /** @availableWhen src!='' */\n @property({type: Object}) srcOptions?: ReadoutSourceOptions;\n\n /**\n * Development aid: outline the readout building blocks (red), the degree\n * columns (blue) and the degree spacer (green) so reserver widths / alignment\n * are visible. Off by default.\n */\n @property({type: Boolean, reflect: true}) showDebugOverlay = false;\n\n /** Pop-up deferred-hide phase for the setpoint (see {@link updated}). */\n @state() private deferredSetpointHidePhase: ReadoutBlockHidePhase =\n ReadoutBlockHidePhase.none;\n private deferredSetpointHideTimer?: number;\n private hasCompletedFirstUpdate = false;\n\n @state() private sourcePickerContentVisible = false;\n @state() private sourcePickerOptions: ContextMenuOption[] = [];\n\n @query('slot[name=\"src-picker-content\"]')\n private sourcePickerSlot?: HTMLSlotElement;\n\n private readonly onWindowPointerDown = (event: PointerEvent) => {\n if (!this.sourcePickerContentVisible) {\n return;\n }\n if (event.composedPath().includes(this)) {\n return;\n }\n this.sourcePickerContentVisible = false;\n };\n\n private get resolvedSize(): ReadoutSize {\n return this.size ?? ReadoutSize.small;\n }\n\n private get resolvedPriority(): ReadoutPriority {\n return this.priority ?? ReadoutPriority.regular;\n }\n\n private get resolvedDirection(): ReadoutDirection {\n return this.direction ?? ReadoutDirection.vertical;\n }\n\n private get resolvedStacking(): ReadoutStacking {\n return this.stacking ?? ReadoutStacking.inline;\n }\n\n private get resolvedAlignment(): ReadoutAlignment {\n return this.alignment ?? ReadoutAlignment.vertical;\n }\n\n private get isHorizontal(): boolean {\n return this.resolvedDirection === ReadoutDirection.horizontal;\n }\n\n private get resolvedFractionDigits(): number {\n return this.fractionDigits ?? 0;\n }\n\n private get resolvedMaxDigits(): number {\n return this.maxDigits ?? 0;\n }\n\n private get hasSrc(): boolean {\n return this.src !== undefined && this.src.trim() !== '';\n }\n\n private get resolvedSourceInteraction(): ReadoutSourceInteraction {\n return this.srcOptions?.interaction ?? ReadoutSourceInteraction.none;\n }\n\n private get isAtSetpoint(): boolean {\n if (!this.hasSetpoint) {\n return false;\n }\n // A text value never compares equal to a setpoint, so flip-flop / pop-up\n // stay dormant for `valueType=\"text\"`.\n return isDisplayedAtSetpoint(\n resolveReadoutNumericValue(this.value, this.valueType) ?? null,\n this.setpoint,\n this.numericFormatOptions(this.resolvedMaxDigits)\n );\n }\n\n private get resolvedSetpointInteraction(): ReadoutSetpointInteraction {\n return (\n this.setpointOptions?.interaction ??\n ReadoutSetpointInteraction.alwaysVisible\n );\n }\n\n private get isFlipFlop(): boolean {\n return (\n this.resolvedSetpointInteraction === ReadoutSetpointInteraction.flipFlop\n );\n }\n\n private get isPopUp(): boolean {\n return (\n this.resolvedSetpointInteraction === ReadoutSetpointInteraction.popUp\n );\n }\n\n private get setpointTouching(): boolean {\n return this.setpointOptions?.touching ?? false;\n }\n\n /**\n * Whether the setpoint interaction re-sizes or hides blocks at runtime —\n * flip-flop (emphasis swap) and pop-up (touch swap + fade-out) — the modes\n * that need the width/height reservation so the readout never shifts (see\n * {@link renderSetpointWidthReserve}).\n */\n private get hasDynamicSetpoint(): boolean {\n return this.hasSetpoint && (this.isFlipFlop || this.isPopUp);\n }\n\n /**\n * The setpoint is rendered \"emphasised\" (primary size + SemiBold weight) when\n * it is the focus of attention: while actively adjusting (`touching`), or while\n * a flip-flop has the value away from the setpoint. Otherwise it is a secondary\n * (smaller, regular-weight) reference next to the value.\n */\n private get isSetpointEmphasized(): boolean {\n if (!this.hasSetpoint) {\n return false;\n }\n if (this.setpointTouching) {\n return true;\n }\n return this.isFlipFlop && !this.isAtSetpoint;\n }\n\n /**\n * The readout's enhanced (in-command) colour state, applied uniformly to BOTH\n * the value and the setpoint — they are always either both neutral or both\n * enhanced (never a blue setpoint next to a grey value). Driven by `priority`\n * only; `valueOptions.weight` changes weight, not colour.\n */\n private get rowEnhanced(): boolean {\n return this.resolvedPriority === ReadoutPriority.enhanced;\n }\n\n /** Primary value-typography size for the current density tier. */\n private get primarySize(): ObcTextboxSize {\n return readoutPrimarySize(this.resolvedSize);\n }\n\n /** Secondary (de-emphasised) value-typography size for the current density tier. */\n private get secondarySize(): ObcTextboxSize {\n return readoutSecondarySize(this.resolvedSize);\n }\n\n private get valueSize(): ObcTextboxSize {\n // The value de-emphasises (secondary size) whenever the setpoint is the\n // focus — while actively adjusting (`touching`) or while a flip-flop holds\n // the value away from the setpoint — mirroring the flip-flop convention.\n if (this.isSetpointEmphasized) {\n return this.secondarySize;\n }\n return this.primarySize;\n }\n\n private get setpointSize(): ObcTextboxSize {\n return this.isSetpointEmphasized ? this.primarySize : this.secondarySize;\n }\n\n /** Value font weight passes straight to obc-textbox; regular when unset. Colour is separate. */\n private get valueWeight(): ObcTextboxFontWeight {\n return this.valueOptions?.weight ?? ObcTextboxFontWeight.regular;\n }\n\n /** Setpoint is SemiBold only while emphasised, otherwise regular weight. */\n private get setpointWeight(): ObcTextboxFontWeight {\n return readoutSetpointWeight(this.isSetpointEmphasized);\n }\n\n private numericFormatOptions(maxDigits: number): ReadoutNumericFormatOptions {\n return readoutNumericFormatOptions(maxDigits, this.resolvedFractionDigits);\n }\n\n /** classMap fragment for a block / source carrying per-block data quality. */\n private dataQualityClasses(\n dataQuality: ReadoutDataQuality | undefined\n ): Record<string, boolean> {\n return readoutDataQualityClasses(dataQuality);\n }\n\n /**\n * Forward the matching readout icon slot into the block's single `icon`\n * slot. The variant's default marker lives in `obc-readout-block` and shows\n * when nothing is assigned here (an empty forwarded slot flattens to nothing).\n */\n private renderForwardedIcon(variant: ReadoutBlockVariant): TemplateResult {\n if (variant === ReadoutBlockVariant.setpoint) {\n return html`<slot name=\"setpoint-icon\" slot=\"icon\"></slot>`;\n }\n if (variant === ReadoutBlockVariant.advice) {\n return html`<slot name=\"advice-icon\" slot=\"icon\"></slot>`;\n }\n return html`<slot name=\"value-icon\" slot=\"icon\"></slot>`;\n }\n\n private renderBlock(config: {\n variant: ReadoutBlockVariant;\n value: number | string | null | undefined;\n /** Only the value block is ever text; setpoint / advice stay numeric. */\n valueType?: ReadoutValueType;\n valueSize: ObcTextboxSize;\n enhanced: boolean;\n weight: ObcTextboxFontWeight;\n hintedZeros: boolean;\n spaceReserver?: string;\n off?: boolean;\n hasDegree?: boolean;\n hasIcon?: boolean;\n touching?: boolean;\n hidePhase?: ReadoutBlockHidePhase;\n dataQuality?: ReadoutBlockDataQuality;\n alert?: false | AlertFrameConfig;\n /**\n * Invisible width-reserving duplicate (see\n * {@link renderSetpointWidthReserve}): skips the forwarded icon slot so\n * the visible block keeps the slotted content — the block's default\n * marker has the same fixed tier width.\n */\n ghost?: boolean;\n }): TemplateResult {\n // The block owns the formatting, hinted zeros, reserver, degree and icon; the\n // readout keeps the density tier (`size`) and the resolved per-block number\n // size (`valueSize`) so flip-flop/pop-up emphasis stays a readout decision.\n return html`\n <obc-readout-block\n exportparts=\"block, block-content, block-text, block-icon, degree\"\n .variant=${config.variant}\n .value=${config.value ?? null}\n .valueType=${config.valueType ?? ReadoutValueType.number}\n .size=${this.resolvedSize}\n .valueSize=${config.valueSize}\n .enhanced=${config.enhanced}\n .weight=${config.weight}\n .hasDegree=${config.hasDegree ?? false}\n .hasIcon=${config.hasIcon ?? false}\n .fractionDigits=${this.resolvedFractionDigits}\n .maxDigits=${this.resolvedMaxDigits}\n .hintedZeros=${config.hintedZeros}\n .spaceReserver=${config.spaceReserver}\n .off=${config.off ?? false}\n .offText=${this.offText}\n .touching=${config.touching ?? false}\n .hidePhase=${config.hidePhase ?? ReadoutBlockHidePhase.none}\n .dataQuality=${config.dataQuality}\n .alert=${config.alert ?? false}\n >\n ${config.ghost ? nothing : this.renderForwardedIcon(config.variant)}\n </obc-readout-block>\n `;\n }\n\n /**\n * A cap-height `°` column whose width scales with the value size, rendered\n * after the value block. Setpoint / advice blocks render their own degree via\n * `obc-readout-block`.\n */\n private renderDegreeGlyph(size: ObcTextboxSize): TemplateResult {\n return html`\n <span\n class=${classMap({\n 'degree-column': true,\n [`degree-${size}`]: true,\n 'tone-enhanced': this.rowEnhanced,\n })}\n part=\"degree\"\n >\n <obc-textbox class=\"degree-glyph\" .size=${size} alignment=\"center\"\n >°</obc-textbox\n >\n </span>\n `;\n }\n\n /**\n * The column rendered after the value digits:\n *\n * - `hasDegree`: a cap-height `°` column whose width scales with the value size.\n * - `hasDegreeSpacer` (non-degree readouts): an invisible reserve of the same\n * width, so this readout's value digits stay aligned with degree readouts\n * in the same column.\n */\n private renderDegreeColumn(\n size: ObcTextboxSize = this.valueSize\n ): TemplateResult | typeof nothing {\n if ((this.hasDegree ?? false) && !this.off) {\n return this.renderDegreeGlyph(size);\n }\n if (this.hasDegreeSpacer ?? false) {\n return html`<span\n class=\"degree-spacer\"\n part=\"degree-spacer\"\n aria-hidden=\"true\"\n ></span>`;\n }\n return nothing;\n }\n\n private renderTextbox(\n role: 'label' | 'unit' | 'source',\n text: string,\n reserver?: string,\n blockState?: ReadoutBlockState\n ): TemplateResult {\n const weight =\n role === 'label'\n ? ObcTextboxFontWeight.semibold\n : ObcTextboxFontWeight.regular;\n const box = html`\n <obc-textbox\n class=${classMap({\n [role]: true,\n ...this.dataQualityClasses(blockState?.dataQuality),\n })}\n part=${role}\n .size=${ObcTextboxSize.xs}\n .fontWeight=${weight}\n alignment=\"left\"\n >\n ${text}\n ${reserver ? html`<span slot=\"length\">${reserver}</span>` : nothing}\n </obc-textbox>\n `;\n return wrapWithAlertFrame(blockState?.alert ?? false, box);\n }\n\n private get setpointHidePhase(): ReadoutBlockHidePhase {\n const popUpAtSetpoint =\n this.isPopUp && this.isAtSetpoint && !this.setpointTouching;\n return resolveSetpointHidePhase(\n popUpAtSetpoint,\n this.deferredSetpointHidePhase\n );\n }\n\n private renderAdviceBlock(): TemplateResult {\n return this.renderBlock({\n variant: ReadoutBlockVariant.advice,\n value: this.advice,\n valueSize: this.secondarySize,\n enhanced: false,\n weight: ObcTextboxFontWeight.regular,\n hintedZeros: this.adviceOptions?.hintedZeros ?? false,\n spaceReserver: this.adviceOptions?.spaceReserver,\n hasDegree: this.hasDegree ?? false,\n dataQuality: this.adviceOptions?.dataQuality,\n alert: this.adviceOptions?.alert,\n });\n }\n\n private renderSetpointBlock(): TemplateResult {\n return this.renderBlock({\n variant: ReadoutBlockVariant.setpoint,\n value: this.setpoint,\n valueSize: this.setpointSize,\n // Value and setpoint share the enhanced colour state (both neutral\n // or both enhanced); the setpoint is bold only while emphasised.\n enhanced: this.rowEnhanced,\n weight: this.setpointWeight,\n hintedZeros: this.setpointOptions?.hintedZeros ?? false,\n spaceReserver: this.setpointOptions?.spaceReserver,\n hasDegree: this.hasDegree ?? false,\n touching: this.setpointTouching,\n hidePhase: this.setpointHidePhase,\n dataQuality: this.setpointOptions?.dataQuality,\n alert: this.setpointOptions?.alert,\n });\n }\n\n /**\n * The value reading: the value block and its degree column (or spacer)\n * grouped in one relatively-positioned wrapper so the value alert frame AND\n * the value data-quality chip can wrap both together. Unlike\n * `obc-readout-list-item` the unit is not part of the reading — it lives in\n * the label/unit meta zone.\n */\n private renderValueReading(): TemplateResult {\n return html`\n <div\n class=${classMap({\n 'value-reading': true,\n ...this.dataQualityClasses(this.valueOptions?.dataQuality),\n })}\n part=\"value-reading\"\n >\n ${this.renderBlock({\n variant: ReadoutBlockVariant.value,\n value: this.value,\n valueType: this.valueType,\n valueSize: this.valueSize,\n enhanced: this.rowEnhanced,\n weight: this.valueWeight,\n hintedZeros: this.valueOptions?.hintedZeros ?? false,\n spaceReserver: this.valueOptions?.spaceReserver,\n off: this.off,\n hasIcon: this.valueOptions?.hasIcon ?? false,\n })}\n ${this.renderDegreeColumn()} ${this.renderValueAlertOverlay()}\n </div>\n `;\n }\n\n /**\n * The value alert frame, drawn as a pure overlay around the value reading\n * (value + degree). It reserves no space — the `obc-alert-frame` sits in an\n * absolutely-positioned box offset outward (see `.value-alert-overlay` in the\n * CSS) so its stroke is centred on the 4px/2px padding line and toggling it\n * never shifts content. Renders only when `valueOptions.alert` is a config\n * object.\n */\n private renderValueAlertOverlay(): TemplateResult | typeof nothing {\n const alert = this.valueOptions?.alert;\n if (typeof alert !== 'object' || alert === null) {\n return nothing;\n }\n const thickness = alert.thickness ?? ObcAlertFrameThickness.Small;\n return html`\n <div\n class=${classMap({\n 'value-alert-overlay': true,\n // The outward offset is thickness-dependent (see the CSS): large frames\n // draw a wider outline, so the box must sit further out to stay centred.\n 'thickness-large': thickness === ObcAlertFrameThickness.Large,\n })}\n aria-hidden=\"true\"\n >\n <obc-alert-frame\n part=\"value-alert-frame\"\n .type=${alert.type ?? ObcAlertFrameType.Regular}\n .thickness=${thickness}\n .status=${alert.status ?? AlertType.Alarm}\n .mode=${alert.mode ?? ObcAlertFrameMode.ackedActive}\n .showIcon=${alert.showIcon ?? false}\n .showAlertCategoryIcon=${alert.showAlertCategoryIcon ?? true}\n .wrapContent=${false}\n .fullWidth=${false}\n ></obc-alert-frame>\n </div>\n `;\n }\n\n /** The label/unit meta zone; `stacking` picks the inline or stacked arrangement. */\n private renderMetaZone(): TemplateResult | typeof nothing {\n if (!this.label && !this.unit) {\n return nothing;\n }\n // Horizontal readouts always stack the label over the unit beside the value.\n const stacked =\n this.isHorizontal || this.resolvedStacking === ReadoutStacking.stacked;\n return html`\n <div\n class=${classMap({\n meta: true,\n 'meta-inline': !stacked,\n 'meta-stacked': stacked,\n 'label-only': !!this.label && !this.unit,\n 'unit-only': !!this.unit && !this.label,\n })}\n part=\"meta-wrapper\"\n >\n ${this.label ? this.renderTextbox('label', this.label) : nothing}\n ${this.unit\n ? this.renderTextbox(\n 'unit',\n this.unit,\n this.unitOptions?.spaceReserver\n )\n : nothing}\n </div>\n `;\n }\n\n private renderSourceContent(): TemplateResult {\n const interaction = this.resolvedSourceInteraction;\n const src = this.src ?? '';\n\n // The interactive variants keep the source's per-block state: the\n // data-quality chip moves onto the button and the alert frame wraps it,\n // matching the plain-text branch (renderTextbox) below.\n const buttonClasses = classMap({\n 'source-button': true,\n ...this.dataQualityClasses(this.srcOptions?.dataQuality),\n });\n\n if (interaction === ReadoutSourceInteraction.picker) {\n const button = html`\n <obc-button\n class=${buttonClasses}\n variant=\"flat\"\n .fullWidth=${false}\n showTrailingIcon\n @click=${() => {\n this.sourcePickerContentVisible = !this.sourcePickerContentVisible;\n }}\n >\n <obi-drop-down-google slot=\"trailing-icon\"></obi-drop-down-google>\n ${src}\n </obc-button>\n `;\n return wrapWithAlertFrame(this.srcOptions?.alert ?? false, button);\n }\n\n if (interaction === ReadoutSourceInteraction.flyout) {\n const button = html`\n <obc-button\n class=${buttonClasses}\n variant=\"flat\"\n .fullWidth=${false}\n showTrailingIcon\n @click=${() => {\n this.dispatchEvent(\n new CustomEvent('source-flyout-click', {\n bubbles: true,\n composed: true,\n detail: {src},\n })\n );\n }}\n >\n <obi-chevron-right-google\n slot=\"trailing-icon\"\n ></obi-chevron-right-google>\n ${src}\n </obc-button>\n `;\n return wrapWithAlertFrame(this.srcOptions?.alert ?? false, button);\n }\n\n return this.renderTextbox(\n 'source',\n src,\n this.srcOptions?.spaceReserver,\n this.srcOptions\n );\n }\n\n /** The source row (vertical) / segment (horizontal), with its auto divider. */\n private renderSource(): TemplateResult | typeof nothing {\n if (!this.hasSrc) {\n return nothing;\n }\n return html`\n <div\n class=${classMap({\n divider: true,\n 'divider-horizontal': !this.isHorizontal,\n 'divider-vertical': this.isHorizontal,\n })}\n part=\"divider\"\n aria-hidden=\"true\"\n ></div>\n <div class=\"source-row\" part=\"source-wrapper\">\n ${this.renderSourceContent()}\n </div>\n `;\n }\n\n // ---------- Source picker (context menu built from src-picker-content) ----------\n\n private getSourcePickerNavigationItems(): HTMLElement[] {\n const assignedElements =\n this.sourcePickerSlot?.assignedElements({flatten: true}) ?? [];\n\n return assignedElements.flatMap((element) => {\n if (!(element instanceof HTMLElement)) {\n return [];\n }\n if (element.localName === 'obc-navigation-item') {\n return [element];\n }\n return Array.from(\n element.querySelectorAll<HTMLElement>('obc-navigation-item')\n );\n });\n }\n\n private createSourcePickerOptionIcon(element: HTMLElement) {\n const iconElement = element.querySelector('[slot=\"icon\"]');\n if (!(iconElement instanceof HTMLElement)) {\n return undefined;\n }\n return html`${iconElement.cloneNode(true)}`;\n }\n\n private getSourcePickerItemInfo(item: HTMLElement, index: number) {\n const itemWithValues = item as HTMLElement & {\n label?: string;\n value?: string;\n };\n const itemLabel = itemWithValues.label || item.getAttribute('label') || '';\n const itemValue =\n item.getAttribute('data-value') ||\n itemWithValues.value ||\n item.getAttribute('value') ||\n itemLabel ||\n `source-option-${index}`;\n\n return {itemLabel, itemValue};\n }\n\n private findSourcePickerOptionElement(value: string) {\n const navigationItems = this.getSourcePickerNavigationItems();\n for (const [index, item] of navigationItems.entries()) {\n const {itemValue} = this.getSourcePickerItemInfo(item, index);\n if (itemValue === value) {\n return item;\n }\n }\n return undefined;\n }\n\n private syncSourcePickerOptions = () => {\n this.sourcePickerOptions = this.getSourcePickerNavigationItems().map(\n (item, index) => {\n const {itemLabel, itemValue} = this.getSourcePickerItemInfo(\n item,\n index\n );\n return {\n value: itemValue,\n label: itemLabel,\n icon: this.createSourcePickerOptionIcon(item),\n };\n }\n );\n };\n\n private handleSourcePickerItemClick(\n event: ObcContextMenuInputItemClickEvent\n ) {\n this.dispatchEvent(\n new CustomEvent('source-change', {\n bubbles: true,\n composed: true,\n detail: {\n value: event.detail.value,\n label: event.detail.option?.label,\n },\n })\n );\n this.findSourcePickerOptionElement(event.detail.value)?.click();\n this.sourcePickerContentVisible = false;\n }\n\n /**\n * The context menu highlights options by their VALUE, while `src` holds the\n * displayed source text — which may be an option's label when the two\n * differ (e.g. `data-value=\"gps-1\"` with label \"GPS 1\"). Resolve the current\n * source to the matching option's value (by value or label) so the open\n * picker always highlights the active source.\n */\n private get selectedSourceValues(): string[] {\n if (!this.src) {\n return [];\n }\n const match = this.sourcePickerOptions.find(\n (option) => option.value === this.src || option.label === this.src\n );\n return [match?.value ?? this.src];\n }\n\n private renderSourcePickerContent(): TemplateResult | typeof nothing {\n if (\n this.resolvedSourceInteraction !== ReadoutSourceInteraction.picker ||\n !this.sourcePickerContentVisible\n ) {\n return nothing;\n }\n return html`\n <obc-context-menu-input\n .type=${ContextMenuType.Regular}\n .options=${this.sourcePickerOptions}\n .selectedValues=${this.selectedSourceValues}\n class=\"source-picker-content\"\n @item-click=${this.handleSourcePickerItemClick}\n @close=${() => {\n this.sourcePickerContentVisible = false;\n }}\n ></obc-context-menu-input>\n `;\n }\n\n private renderSourcePickerSlot(): TemplateResult {\n return html`\n <slot\n name=\"src-picker-content\"\n hidden\n @slotchange=${this.syncSourcePickerOptions}\n ></slot>\n `;\n }\n\n // ---------- Layouts ----------\n\n /**\n * An invisible primary-size duplicate of a dynamic setpoint row's content,\n * stacked under the visible block in the same grid cell purely to reserve\n * width. With both rows permanently holding their emphasised width, the\n * widest row — and therefore the readout's total width — stays constant\n * while a flip-flop swaps the value/setpoint sizes, while a touch swap\n * runs, and while a pop-up setpoint fades out, so the meta zone and source\n * never shift. This is the vertical analogue of the horizontal arrangement,\n * where the swapped pair sits on one row and its summed width is constant\n * by construction (the designer's flip-flop invariant). Only the vertical\n * direction needs it; `always-visible` layouts are untouched.\n */\n private renderSetpointWidthReserve(\n kind: 'setpoint' | 'value'\n ): TemplateResult | typeof nothing {\n if (!this.hasDynamicSetpoint || this.isHorizontal) {\n return nothing;\n }\n const content =\n kind === 'setpoint'\n ? this.renderBlock({\n variant: ReadoutBlockVariant.setpoint,\n value: this.setpoint,\n valueSize: this.primarySize,\n enhanced: false,\n // The emphasised setpoint is SemiBold — reserve its widest form.\n weight: ObcTextboxFontWeight.semibold,\n hintedZeros: this.setpointOptions?.hintedZeros ?? false,\n spaceReserver: this.setpointOptions?.spaceReserver,\n hasDegree: this.hasDegree ?? false,\n alert: this.setpointOptions?.alert,\n ghost: true,\n })\n : html`${this.renderBlock({\n variant: ReadoutBlockVariant.value,\n value: this.value,\n valueType: this.valueType,\n valueSize: this.primarySize,\n enhanced: false,\n weight: this.valueWeight,\n hintedZeros: this.valueOptions?.hintedZeros ?? false,\n spaceReserver: this.valueOptions?.spaceReserver,\n off: this.off,\n hasIcon: this.valueOptions?.hasIcon ?? false,\n ghost: true,\n })}${this.renderDegreeColumn(this.primarySize)}`;\n return html`<div class=\"setpoint-width-reserve\" aria-hidden=\"true\">\n ${content}\n </div>`;\n }\n\n /**\n * Vertical: advice / setpoint / value rows right-aligned in a cluster, the\n * label+unit meta zone below, then the source row under an auto divider.\n * `alignment` re-aligns the whole column for stacked readouts.\n */\n private renderVerticalLayout(): TemplateResult {\n return html`\n <div class=\"value-cluster\" part=\"value-cluster\">\n ${this.hasAdvice\n ? html`<div class=\"advice-row\" part=\"advice-wrapper\">\n ${this.renderAdviceBlock()}\n </div>`\n : nothing}\n ${this.hasSetpoint\n ? html`<div class=\"setpoint-row\" part=\"setpoint-wrapper\">\n ${this.renderSetpointBlock()}\n ${this.renderSetpointWidthReserve('setpoint')}\n </div>`\n : nothing}\n ${this.hasValue\n ? html`<div class=\"value-row\" part=\"value-wrapper\">\n ${this.renderValueReading()}\n ${this.renderSetpointWidthReserve('value')}\n </div>`\n : nothing}\n </div>\n ${this.renderMetaZone()} ${this.renderSource()}\n `;\n }\n\n /**\n * Horizontal: advice, setpoint, value and the stacked label/unit meta flow on\n * one cap-height-aligned row, with the source at the end after an auto\n * divider.\n */\n private renderHorizontalLayout(): TemplateResult {\n return html`\n <div class=\"inline-row\" part=\"value-cluster\">\n ${this.hasAdvice\n ? html`<div class=\"advice-row\" part=\"advice-wrapper\">\n ${this.renderAdviceBlock()}\n </div>`\n : nothing}\n ${this.hasSetpoint\n ? html`<div class=\"setpoint-row\" part=\"setpoint-wrapper\">\n ${this.renderSetpointBlock()}\n </div>`\n : nothing}\n ${this.hasValue\n ? html`<div class=\"value-row\" part=\"value-wrapper\">\n ${this.renderValueReading()}\n </div>`\n : nothing}\n ${this.renderMetaZone()} ${this.renderSource()}\n </div>\n `;\n }\n\n protected override willUpdate(changed: Map<string, unknown>): void {\n super.willUpdate(changed);\n // Validated on EVERY update, deliberately NOT gated on `value`/`valueType`\n // appearing in `changed`. When this assertion throws, Lit's `performUpdate`\n // catch calls `__markUpdated()`, which clears the changed-properties map. A\n // later update driven by any OTHER property — inside `obc-readout-list`,\n // `align()` writing the shared reservers — would then see no `value` in\n // `changed`, skip the check, and render the invalid value as a plain dash:\n // exactly the silent failure this assertion exists to prevent.\n assertReadoutValueType('obc-readout', this.value, this.valueType);\n }\n\n override updated(changed: Map<string, unknown>): void {\n super.updated(changed);\n\n if (changed.has('sourcePickerContentVisible')) {\n if (this.sourcePickerContentVisible) {\n window.addEventListener('pointerdown', this.onWindowPointerDown, true);\n } else {\n window.removeEventListener(\n 'pointerdown',\n this.onWindowPointerDown,\n true\n );\n }\n }\n\n const firstUpdate = !this.hasCompletedFirstUpdate;\n this.hasCompletedFirstUpdate = true;\n\n // Pop-up: hide the setpoint shortly after the value reaches it. `touching`\n // and the non-pop-up modes keep the setpoint visible.\n if (!this.isPopUp || this.setpointTouching) {\n this.clearDeferredSetpointHide();\n return;\n }\n\n const shouldHide = this.hasSetpoint && this.isAtSetpoint;\n\n if (firstUpdate) {\n // Settle to the resting state on mount without animating.\n this.deferredSetpointHidePhase = shouldHide\n ? ReadoutBlockHidePhase.hidden\n : ReadoutBlockHidePhase.none;\n return;\n }\n\n if (!shouldHide) {\n this.clearDeferredSetpointHide();\n return;\n }\n\n if (this.deferredSetpointHidePhase !== ReadoutBlockHidePhase.none) {\n return;\n }\n\n this.deferredSetpointHidePhase = ReadoutBlockHidePhase.hiding;\n window.clearTimeout(this.deferredSetpointHideTimer);\n this.deferredSetpointHideTimer = window.setTimeout(() => {\n this.deferredSetpointHidePhase = ReadoutBlockHidePhase.hidden;\n this.deferredSetpointHideTimer = undefined;\n }, 100);\n }\n\n private clearDeferredSetpointHide(): void {\n if (this.deferredSetpointHidePhase !== ReadoutBlockHidePhase.none) {\n this.deferredSetpointHidePhase = ReadoutBlockHidePhase.none;\n }\n window.clearTimeout(this.deferredSetpointHideTimer);\n this.deferredSetpointHideTimer = undefined;\n }\n\n override disconnectedCallback(): void {\n window.removeEventListener('pointerdown', this.onWindowPointerDown, true);\n window.clearTimeout(this.deferredSetpointHideTimer);\n this.deferredSetpointHideTimer = undefined;\n // Settle a mid-flight hide to its end state. Without this, disconnecting\n // during the 100ms window leaves the phase stuck at 'hiding' (the timer that\n // would advance it to 'hidden' is gone), so a later reconnect never resolves.\n if (this.deferredSetpointHidePhase === ReadoutBlockHidePhase.hiding) {\n this.deferredSetpointHidePhase = ReadoutBlockHidePhase.hidden;\n }\n super.disconnectedCallback();\n }\n\n override render() {\n const dataQuality = this.dataQuality;\n const classes = classMap({\n readout: true,\n [`size-${this.resolvedSize}`]: true,\n [`direction-${this.resolvedDirection}`]: true,\n [`stacking-${this.resolvedStacking}`]: true,\n [`alignment-${this.resolvedAlignment}`]: true,\n [`priority-${this.resolvedPriority}`]: true,\n 'data-low-integrity': dataQuality === ReadoutDataQuality.lowIntegrity,\n 'data-invalid': dataQuality === ReadoutDataQuality.invalid,\n 'flip-flop': this.isFlipFlop,\n 'setpoint-dynamic': this.hasDynamicSetpoint,\n });\n\n const root = html`\n <div class=${classes} part=\"root\">\n ${this.isHorizontal\n ? this.renderHorizontalLayout()\n : this.renderVerticalLayout()}\n ${this.renderSourcePickerSlot()}\n </div>\n ${this.renderSourcePickerContent()}\n `;\n\n // `alert` accepts `boolean` (so the generated Angular wrapper's widened\n // `boolean` type assigns cleanly), but `wrapWithAlertFrame` ignores\n // non-object truthy values. Normalise `true` → a default frame `{}` so it\n // isn't a silent no-op; `false`/object pass through. The frame hugs the\n // readout (no fullWidth), matching the previous behaviour.\n const alert = this.alert === true ? {} : this.alert;\n return wrapWithAlertFrame(alert, root);\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-readout': ObcReadout;\n }\n}\n"],"names":["ReadoutDirection","ReadoutStacking","ReadoutAlignment","ReadoutSourceInteraction"],"mappings":"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"}
|
|
@@ -16,7 +16,12 @@ import '../readout-list-item/readout-list-item.js';
|
|
|
16
16
|
* - **Value / setpoint / advice:** the widest numeric width (max integer digits +
|
|
17
17
|
* max fraction digits across rows, derived from each row's `maxDigits` /
|
|
18
18
|
* `fractionDigits` / current values) is reserved on every row's numeric blocks.
|
|
19
|
-
* Reserving off digit counts keeps it stable as live values update.
|
|
19
|
+
* Reserving off digit counts keeps it stable as live values update. A row with
|
|
20
|
+
* `valueType="text"` is excluded in both directions — it neither contributes
|
|
21
|
+
* to the reserve (so a long text value cannot inflate the numeric column) nor
|
|
22
|
+
* receives it (so short text is not padded to a digit width); its value block
|
|
23
|
+
* sizes to its own content. Its setpoint / advice blocks stay numeric and are
|
|
24
|
+
* reserved normally.
|
|
20
25
|
* - **Source:** the longest `src` becomes every row's source space-reserver.
|
|
21
26
|
* - **Degree:** if any row has a degree, non-degree rows reserve the degree column
|
|
22
27
|
* (`hasDegreeSpacer`) so their digits line up with the degree rows; the spacer is
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readout-list.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/readout-list/readout-list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAmB,KAAK,cAAc,EAAC,MAAM,KAAK,CAAC;AAIrE,OAAO,2CAA2C,CAAC;
|
|
1
|
+
{"version":3,"file":"readout-list.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/readout-list/readout-list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAmB,KAAK,cAAc,EAAC,MAAM,KAAK,CAAC;AAIrE,OAAO,2CAA2C,CAAC;AA+CnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,qBACa,cAAe,SAAQ,UAAU;IAC5C;;;;OAIG;IACuC,gBAAgB,UAAS;IAEnE,OAAO,CAAC,gBAAgB,CAAC,CAAmB;cAEzB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAShD,oBAAoB,IAAI,IAAI;IAMrC,oFAAoF;IACpF,OAAO,KAAK,KAAK,GAQhB;IAED;;;;OAIG;IACH,KAAK,IAAI,IAAI;IA+Fb,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,gBAAgB,CAGtB;IAEO,MAAM;IAQf,OAAgB,MAAM,0BAA6B;CACpD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,kBAAkB,EAAE,cAAc,CAAC;KACpC;CACF"}
|