@oicl/openbridge-webcomponents-full-bundle 2.0.0-next.121 → 2.0.0-next.122
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 +233 -53
- package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
- package/custom-elements.json +66 -17
- package/dist/automation/automation-tank/automation-tank.css.js +94 -14
- package/dist/automation/automation-tank/automation-tank.css.js.map +1 -1
- package/dist/automation/automation-tank/automation-tank.d.ts +53 -5
- package/dist/automation/automation-tank/automation-tank.d.ts.map +1 -1
- package/dist/automation/automation-tank/automation-tank.js +39 -20
- package/dist/automation/automation-tank/automation-tank.js.map +1 -1
- package/dist/building-blocks/readout-block/readout-block.d.ts +27 -1
- package/dist/building-blocks/readout-block/readout-block.d.ts.map +1 -1
- package/dist/building-blocks/readout-block/readout-block.js +31 -10
- package/dist/building-blocks/readout-block/readout-block.js.map +1 -1
- package/dist/navigation-instruments/readout/readout-formatters.d.ts +61 -0
- package/dist/navigation-instruments/readout/readout-formatters.d.ts.map +1 -1
- package/dist/navigation-instruments/readout/readout-formatters.js +35 -2
- package/dist/navigation-instruments/readout/readout-formatters.js.map +1 -1
- package/dist/navigation-instruments/readout/readout.d.ts +19 -2
- package/dist/navigation-instruments/readout/readout.d.ts.map +1 -1
- package/dist/navigation-instruments/readout/readout.js +18 -4
- package/dist/navigation-instruments/readout/readout.js.map +1 -1
- package/dist/navigation-instruments/readout-list/readout-list.d.ts.map +1 -1
- package/dist/navigation-instruments/readout-list/readout-list.js +6 -3
- package/dist/navigation-instruments/readout-list/readout-list.js.map +1 -1
- package/dist/navigation-instruments/readout-list-item/readout-list-item.d.ts +19 -2
- 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 +18 -4
- package/dist/navigation-instruments/readout-list-item/readout-list-item.js.map +1 -1
- package/package.json +1 -1
- package/src/automation/automation-tank/automation-tank.css +70 -3
- package/src/automation/automation-tank/automation-tank.stories.ts +140 -1
- package/src/automation/automation-tank/automation-tank.ts +106 -27
- package/src/building-blocks/readout-block/readout-block.stories.ts +20 -0
- package/src/building-blocks/readout-block/readout-block.ts +56 -10
- package/src/navigation-instruments/readout/readout-formatters.spec.ts +205 -0
- package/src/navigation-instruments/readout/readout-formatters.ts +128 -2
- package/src/navigation-instruments/readout/readout.ts +38 -5
- package/src/navigation-instruments/readout-list/readout-list.ts +10 -2
- package/src/navigation-instruments/readout-list-item/readout-list-item.ts +38 -5
|
@@ -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 {\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 {CustomEvent<{value: string, label?: string}>} source-change - Fired when a source picker option is selected.\n * @fires {CustomEvent<{src: string}>} source-flyout-click - 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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"}
|
|
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 assertReadoutFractionDigits,\n isReadoutDigitCountMissing,\n resolveReadoutDigitCount,\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 {CustomEvent<{value: string, label?: string}>} source-change - Fired when a source picker option is selected.\n * @fires {CustomEvent<{src: string}>} source-flyout-click - 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. Must be between 0 and 100 — the range\n * `Number.prototype.toFixed` accepts; outside it throws a `RangeError`.\n * A fractional count truncates (`2.7` → `2`). A count that never arrived\n * (`NaN`, `null` or unset) renders the reading as the unavailable dash —\n * formatting with a precision the author never chose would let a critical\n * `0.4` pass for a healthy `0`.\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. Bounded before use: a fractional count\n * truncates (`2.7` → `2`), anything above 100 — including `Infinity` —\n * caps at 100, and a negative count reserves nothing. A count that never\n * arrived (`NaN`, `null` or unset) renders the reading as the unavailable\n * dash, consistent with `fractionDigits`.\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 resolveReadoutDigitCount(this.maxDigits);\n }\n\n /**\n * Whether a digit knob failed to arrive (`NaN` / `null` / `undefined`).\n * The raw knobs are forwarded to the blocks, which render the reading as\n * the unavailable dash (see `obc-readout-block.digitCountsMissing`); this\n * getter only keeps the setpoint comparison in agreement with what is\n * displayed.\n */\n private get digitCountsMissing(): boolean {\n return (\n isReadoutDigitCountMissing(this.fractionDigits) ||\n isReadoutDigitCountMissing(this.maxDigits)\n );\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 missing digit knob renders every numeric block as the dash; two\n // dashes must not read as \"at the setpoint\", so the comparison stays off\n // entirely while the configuration is untrustworthy.\n if (this.digitCountsMissing) {\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.fractionDigits}\n .maxDigits=${this.maxDigits}\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 assertReadoutFractionDigits('obc-readout', this.fractionDigits);\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 +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;AAgDnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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;IAsGb,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"}
|
|
@@ -3,7 +3,7 @@ import { property } from "lit/decorators.js";
|
|
|
3
3
|
import componentStyle from "./readout-list.css.js";
|
|
4
4
|
import { customElement } from "../../decorator.js";
|
|
5
5
|
import "../readout-list-item/readout-list-item.js";
|
|
6
|
-
import { resolveReadoutNumericValue, ReadoutValueType } from "../readout/readout-formatters.js";
|
|
6
|
+
import { resolveReadoutDigitCount, resolveReadoutNumericValue, ReadoutValueType } from "../readout/readout-formatters.js";
|
|
7
7
|
var __defProp = Object.defineProperty;
|
|
8
8
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
9
9
|
var __decorateClass = (decorators, target, key, kind) => {
|
|
@@ -86,9 +86,12 @@ let ObcReadoutList = class extends LitElement {
|
|
|
86
86
|
if (hasNumericBlock) {
|
|
87
87
|
maxFractionDigits = Math.max(
|
|
88
88
|
maxFractionDigits,
|
|
89
|
-
item.fractionDigits
|
|
89
|
+
resolveReadoutDigitCount(item.fractionDigits)
|
|
90
|
+
);
|
|
91
|
+
maxIntegerDigits = Math.max(
|
|
92
|
+
maxIntegerDigits,
|
|
93
|
+
resolveReadoutDigitCount(item.maxDigits)
|
|
90
94
|
);
|
|
91
|
-
maxIntegerDigits = Math.max(maxIntegerDigits, item.maxDigits ?? 0);
|
|
92
95
|
}
|
|
93
96
|
maxIntegerDigits = Math.max(
|
|
94
97
|
maxIntegerDigits,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readout-list.js","sources":["../../../src/navigation-instruments/readout-list/readout-list.ts"],"sourcesContent":["import {LitElement, html, unsafeCSS, type PropertyValues} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport componentStyle from './readout-list.css?inline';\nimport {customElement} from '../../decorator.js';\nimport '../readout-list-item/readout-list-item.js';\nimport {ObcReadoutListItem} from '../readout-list-item/readout-list-item.js';\nimport {\n resolveReadoutNumericValue,\n ReadoutValueType,\n} from '../readout/readout-formatters.js';\n\nconst ITEM_TAG = 'obc-readout-list-item';\n\n// Lit lowercases a property name to derive its attribute (it does not\n// kebab-case), so multi-word properties are observed as one lowercase word —\n// `valueType` becomes `valuetype`.\n//\n// The kebab-cased entries below are therefore INERT: the real attributes are\n// `maxdigits`, `fractiondigits`, `hasdegree`, `hassetpoint` and `hasadvice`, so\n// changing any of them does not currently re-trigger alignment. They predate\n// this list and are left as-is rather than silently activating five code paths\n// that have never run; see the follow-up issue before adding more entries.\n/** Child attributes whose change should re-trigger alignment (HTML-attribute usage). */\nconst OBSERVED_ATTRIBUTES = [\n 'unit',\n 'src',\n 'value',\n 'valuetype',\n 'setpoint',\n 'advice',\n // ⚠ inert — see the note above; the real names have no hyphens.\n 'max-digits',\n 'fraction-digits',\n 'has-degree',\n 'has-setpoint',\n 'has-advice',\n];\n\n/** Whether a row renders its value as verbatim text rather than a number. */\nfunction isTextValueRow(item: ObcReadoutListItem): boolean {\n return item.valueType === ReadoutValueType.text;\n}\n\n/** Integer-digit count of a numeric value (sign and fraction excluded). */\nfunction integerDigitCount(value: number | null | undefined): number {\n if (value === null || value === undefined || Number.isNaN(value)) {\n return 0;\n }\n return String(Math.trunc(Math.abs(value))).length;\n}\n\n/**\n * `<obc-readout-list>` – A container that groups `<obc-readout-list-item>` rows\n * and **auto-aligns their columns**.\n *\n * Because each row is its own custom element, cross-row column alignment is not\n * automatic. This container inspects its rows and pushes shared width reservers\n * down so the unit column, the value / setpoint / advice columns and the source\n * column all line up — the same effect the `Readout List Item → ColumnAlignment`\n * story achieves by hand, done for you. Alignment is always on.\n *\n * What it equalizes — derived from each row's data and broadcast to every row, so\n * the widest value / unit / source is never clipped:\n * - **Unit:** the longest `unit` becomes every row's unit space-reserver.\n * - **Value / setpoint / advice:** the widest numeric width (max integer digits +\n * max fraction digits across rows, derived from each row's `maxDigits` /\n * `fractionDigits` / current values) is reserved on every row's numeric blocks.\n * Reserving off digit counts keeps it stable as live values update. A row with\n * `valueType=\"text\"` is excluded in both directions — it neither contributes\n * to the reserve (so a long text value cannot inflate the numeric column) nor\n * receives it (so short text is not padded to a digit width); its value block\n * sizes to its own content. Its setpoint / advice blocks stay numeric and are\n * reserved normally.\n * - **Source:** the longest `src` becomes every row's source space-reserver.\n * - **Degree:** if any row has a degree, non-degree rows reserve the degree column\n * (`hasDegreeSpacer`) so their digits line up with the degree rows; the spacer is\n * cleared once no degree rows remain.\n *\n * The list **owns** these reservers: it recomputes them from the rows' data on\n * every pass (and clears stale reservers / spacers when rows change), so a\n * `spaceReserver` set directly on a row inside the list is overwritten. Drive the\n * data (`maxDigits` / `fractionDigits` / `unit` / `src`) rather than setting a\n * manual reserver when a row lives in a list.\n *\n * Alignment runs on `slotchange` and on child mutations (added/removed rows and\n * HTML-attribute changes). When rows are updated via JS **properties** only (no\n * attribute/DOM mutation), call {@link align} to recompute.\n *\n * @experimental Pilot for the new primitives + per-block options Readout API; the\n * API may change in a future release.\n *\n * @slot - The `<obc-readout-list-item>` rows.\n *\n * @csspart list - The vertical stack container.\n */\n@customElement('obc-readout-list')\nexport class ObcReadoutList extends LitElement {\n /**\n * Development aid: outline each row's readout building blocks (red), degree\n * columns (blue) and degree spacer (green) so the reserved column widths are\n * visible. Propagated to every row. Off by default.\n */\n @property({type: Boolean, reflect: true}) showDebugOverlay = false;\n\n private mutationObserver?: MutationObserver;\n\n protected override updated(changed: PropertyValues): void {\n super.updated(changed);\n // A host-property change is not seen by the child MutationObserver, so\n // re-propagate `showDebugOverlay` (and re-align) when it toggles.\n if (changed.has('showDebugOverlay')) {\n this.align();\n }\n }\n\n override disconnectedCallback(): void {\n this.mutationObserver?.disconnect();\n this.mutationObserver = undefined;\n super.disconnectedCallback();\n }\n\n /** The `obc-readout-list-item` rows, including those nested in wrapper elements. */\n private get items(): ObcReadoutListItem[] {\n const slot = this.shadowRoot?.querySelector('slot');\n const assigned = slot?.assignedElements({flatten: true}) ?? [];\n return assigned.flatMap((el) =>\n el.tagName.toLowerCase() === ITEM_TAG\n ? [el as ObcReadoutListItem]\n : Array.from(el.querySelectorAll<ObcReadoutListItem>(ITEM_TAG))\n );\n }\n\n /**\n * Recompute and apply the shared column reservers across all rows. Call this\n * after updating rows via JS properties only (attribute/DOM changes are picked\n * up automatically).\n */\n align(): void {\n const items = this.items;\n if (items.length === 0) {\n return;\n }\n\n let maxIntegerDigits = 0;\n let maxFractionDigits = 0;\n let longestUnit = '';\n let longestSrc = '';\n let anyDegree = false;\n\n for (const item of items) {\n // A text value renders verbatim, so it contributes nothing to the numeric\n // reserve: resolving it yields `undefined` and `integerDigitCount` returns\n // 0. Its row's `maxDigits` / `fractionDigits` are skipped too — they are\n // ignored by a text block, so counting them would let a text row inflate\n // every other row's numeric column. They DO still count when the row also\n // has a setpoint or advice block, which stay numeric and are formatted by\n // them. Numeric rows driven by HTML attributes resolve back to numbers\n // here, so they take part as usual.\n const hasNumericBlock =\n !isTextValueRow(item) || item.hasSetpoint || item.hasAdvice;\n if (hasNumericBlock) {\n maxFractionDigits = Math.max(\n maxFractionDigits,\n item.fractionDigits ?? 0\n );\n maxIntegerDigits = Math.max(maxIntegerDigits, item.maxDigits ?? 0);\n }\n maxIntegerDigits = Math.max(\n maxIntegerDigits,\n integerDigitCount(\n resolveReadoutNumericValue(\n item.value,\n item.valueType ?? ReadoutValueType.number\n )\n ),\n item.hasSetpoint ? integerDigitCount(item.setpoint) : 0,\n item.hasAdvice ? integerDigitCount(item.advice) : 0\n );\n if (item.unit && item.unit.length > longestUnit.length) {\n longestUnit = item.unit;\n }\n if (item.src && item.src.length > longestSrc.length) {\n longestSrc = item.src;\n }\n if (item.hasDegree) {\n anyDegree = true;\n }\n }\n\n const numericReserver =\n maxIntegerDigits > 0\n ? '0'.repeat(maxIntegerDigits) +\n (maxFractionDigits > 0 ? `.${'0'.repeat(maxFractionDigits)}` : '')\n : undefined;\n\n // Our writes are properties (no reflected attributes), so they do not trigger\n // the MutationObserver; disconnecting around them is belt-and-suspenders.\n this.mutationObserver?.disconnect();\n for (const item of items) {\n // Recompute every reserver / spacer on every pass (do not gate on a value\n // being present), so stale state clears when rows change — e.g. when the\n // last degree row, the last unit, or the last source is removed.\n // The numeric reserve is a width in DIGITS, so applying it to a text\n // block would pad short text (\"Auto\" padded out to \"0000.0\"'s width).\n // Text rows hug their own content instead. Setpoint / advice stay\n // numeric and keep the shared reserve even on a text row.\n item.valueOptions = {\n ...item.valueOptions,\n spaceReserver: isTextValueRow(item) ? undefined : numericReserver,\n };\n item.setpointOptions = {\n ...item.setpointOptions,\n spaceReserver: numericReserver,\n };\n item.adviceOptions = {\n ...item.adviceOptions,\n spaceReserver: numericReserver,\n };\n item.unitOptions = {\n ...item.unitOptions,\n spaceReserver: longestUnit || undefined,\n };\n item.srcOptions = {\n ...item.srcOptions,\n spaceReserver: longestSrc || undefined,\n };\n item.hasDegreeSpacer = anyDegree && !item.hasDegree;\n item.showDebugOverlay = this.showDebugOverlay;\n }\n this.observeChildren();\n }\n\n private observeChildren(): void {\n if (!this.mutationObserver) {\n this.mutationObserver = new MutationObserver(() => this.align());\n }\n this.mutationObserver.observe(this, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: OBSERVED_ATTRIBUTES,\n });\n }\n\n private handleSlotChange = (): void => {\n this.align();\n this.observeChildren();\n };\n\n override render() {\n return html`\n <div class=\"list\" part=\"list\">\n <slot @slotchange=${this.handleSlotChange}></slot>\n </div>\n `;\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-readout-list': ObcReadoutList;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"readout-list.js","sources":["../../../src/navigation-instruments/readout-list/readout-list.ts"],"sourcesContent":["import {LitElement, html, unsafeCSS, type PropertyValues} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport componentStyle from './readout-list.css?inline';\nimport {customElement} from '../../decorator.js';\nimport '../readout-list-item/readout-list-item.js';\nimport {ObcReadoutListItem} from '../readout-list-item/readout-list-item.js';\nimport {resolveReadoutDigitCount} from '../readout/readout-formatters.js';\nimport {\n resolveReadoutNumericValue,\n ReadoutValueType,\n} from '../readout/readout-formatters.js';\n\nconst ITEM_TAG = 'obc-readout-list-item';\n\n// Lit lowercases a property name to derive its attribute (it does not\n// kebab-case), so multi-word properties are observed as one lowercase word —\n// `valueType` becomes `valuetype`.\n//\n// The kebab-cased entries below are therefore INERT: the real attributes are\n// `maxdigits`, `fractiondigits`, `hasdegree`, `hassetpoint` and `hasadvice`, so\n// changing any of them does not currently re-trigger alignment. They predate\n// this list and are left as-is rather than silently activating five code paths\n// that have never run; see the follow-up issue before adding more entries.\n/** Child attributes whose change should re-trigger alignment (HTML-attribute usage). */\nconst OBSERVED_ATTRIBUTES = [\n 'unit',\n 'src',\n 'value',\n 'valuetype',\n 'setpoint',\n 'advice',\n // ⚠ inert — see the note above; the real names have no hyphens.\n 'max-digits',\n 'fraction-digits',\n 'has-degree',\n 'has-setpoint',\n 'has-advice',\n];\n\n/** Whether a row renders its value as verbatim text rather than a number. */\nfunction isTextValueRow(item: ObcReadoutListItem): boolean {\n return item.valueType === ReadoutValueType.text;\n}\n\n/** Integer-digit count of a numeric value (sign and fraction excluded). */\nfunction integerDigitCount(value: number | null | undefined): number {\n if (value === null || value === undefined || Number.isNaN(value)) {\n return 0;\n }\n return String(Math.trunc(Math.abs(value))).length;\n}\n\n/**\n * `<obc-readout-list>` – A container that groups `<obc-readout-list-item>` rows\n * and **auto-aligns their columns**.\n *\n * Because each row is its own custom element, cross-row column alignment is not\n * automatic. This container inspects its rows and pushes shared width reservers\n * down so the unit column, the value / setpoint / advice columns and the source\n * column all line up — the same effect the `Readout List Item → ColumnAlignment`\n * story achieves by hand, done for you. Alignment is always on.\n *\n * What it equalizes — derived from each row's data and broadcast to every row, so\n * the widest value / unit / source is never clipped:\n * - **Unit:** the longest `unit` becomes every row's unit space-reserver.\n * - **Value / setpoint / advice:** the widest numeric width (max integer digits +\n * max fraction digits across rows, derived from each row's `maxDigits` /\n * `fractionDigits` / current values) is reserved on every row's numeric blocks.\n * Reserving off digit counts keeps it stable as live values update. A row with\n * `valueType=\"text\"` is excluded in both directions — it neither contributes\n * to the reserve (so a long text value cannot inflate the numeric column) nor\n * receives it (so short text is not padded to a digit width); its value block\n * sizes to its own content. Its setpoint / advice blocks stay numeric and are\n * reserved normally.\n * - **Source:** the longest `src` becomes every row's source space-reserver.\n * - **Degree:** if any row has a degree, non-degree rows reserve the degree column\n * (`hasDegreeSpacer`) so their digits line up with the degree rows; the spacer is\n * cleared once no degree rows remain.\n *\n * The list **owns** these reservers: it recomputes them from the rows' data on\n * every pass (and clears stale reservers / spacers when rows change), so a\n * `spaceReserver` set directly on a row inside the list is overwritten. Drive the\n * data (`maxDigits` / `fractionDigits` / `unit` / `src`) rather than setting a\n * manual reserver when a row lives in a list.\n *\n * Alignment runs on `slotchange` and on child mutations (added/removed rows and\n * HTML-attribute changes). When rows are updated via JS **properties** only (no\n * attribute/DOM mutation), call {@link align} to recompute.\n *\n * @experimental Pilot for the new primitives + per-block options Readout API; the\n * API may change in a future release.\n *\n * @slot - The `<obc-readout-list-item>` rows.\n *\n * @csspart list - The vertical stack container.\n */\n@customElement('obc-readout-list')\nexport class ObcReadoutList extends LitElement {\n /**\n * Development aid: outline each row's readout building blocks (red), degree\n * columns (blue) and degree spacer (green) so the reserved column widths are\n * visible. Propagated to every row. Off by default.\n */\n @property({type: Boolean, reflect: true}) showDebugOverlay = false;\n\n private mutationObserver?: MutationObserver;\n\n protected override updated(changed: PropertyValues): void {\n super.updated(changed);\n // A host-property change is not seen by the child MutationObserver, so\n // re-propagate `showDebugOverlay` (and re-align) when it toggles.\n if (changed.has('showDebugOverlay')) {\n this.align();\n }\n }\n\n override disconnectedCallback(): void {\n this.mutationObserver?.disconnect();\n this.mutationObserver = undefined;\n super.disconnectedCallback();\n }\n\n /** The `obc-readout-list-item` rows, including those nested in wrapper elements. */\n private get items(): ObcReadoutListItem[] {\n const slot = this.shadowRoot?.querySelector('slot');\n const assigned = slot?.assignedElements({flatten: true}) ?? [];\n return assigned.flatMap((el) =>\n el.tagName.toLowerCase() === ITEM_TAG\n ? [el as ObcReadoutListItem]\n : Array.from(el.querySelectorAll<ObcReadoutListItem>(ITEM_TAG))\n );\n }\n\n /**\n * Recompute and apply the shared column reservers across all rows. Call this\n * after updating rows via JS properties only (attribute/DOM changes are picked\n * up automatically).\n */\n align(): void {\n const items = this.items;\n if (items.length === 0) {\n return;\n }\n\n let maxIntegerDigits = 0;\n let maxFractionDigits = 0;\n let longestUnit = '';\n let longestSrc = '';\n let anyDegree = false;\n\n for (const item of items) {\n // A text value renders verbatim, so it contributes nothing to the numeric\n // reserve: resolving it yields `undefined` and `integerDigitCount` returns\n // 0. Its row's `maxDigits` / `fractionDigits` are skipped too — they are\n // ignored by a text block, so counting them would let a text row inflate\n // every other row's numeric column. They DO still count when the row also\n // has a setpoint or advice block, which stay numeric and are formatted by\n // them. Numeric rows driven by HTML attributes resolve back to numbers\n // here, so they take part as usual.\n const hasNumericBlock =\n !isTextValueRow(item) || item.hasSetpoint || item.hasAdvice;\n // Bounded per row: the list builds its own reserver string from these\n // counts, so an `Infinity` or absurdly large value on any single row\n // would otherwise throw out of `String.prototype.repeat` below — inside a\n // MutationObserver callback, where the stack says nothing useful.\n if (hasNumericBlock) {\n maxFractionDigits = Math.max(\n maxFractionDigits,\n resolveReadoutDigitCount(item.fractionDigits)\n );\n maxIntegerDigits = Math.max(\n maxIntegerDigits,\n resolveReadoutDigitCount(item.maxDigits)\n );\n }\n maxIntegerDigits = Math.max(\n maxIntegerDigits,\n integerDigitCount(\n resolveReadoutNumericValue(\n item.value,\n item.valueType ?? ReadoutValueType.number\n )\n ),\n item.hasSetpoint ? integerDigitCount(item.setpoint) : 0,\n item.hasAdvice ? integerDigitCount(item.advice) : 0\n );\n if (item.unit && item.unit.length > longestUnit.length) {\n longestUnit = item.unit;\n }\n if (item.src && item.src.length > longestSrc.length) {\n longestSrc = item.src;\n }\n if (item.hasDegree) {\n anyDegree = true;\n }\n }\n\n const numericReserver =\n maxIntegerDigits > 0\n ? '0'.repeat(maxIntegerDigits) +\n (maxFractionDigits > 0 ? `.${'0'.repeat(maxFractionDigits)}` : '')\n : undefined;\n\n // Our writes are properties (no reflected attributes), so they do not trigger\n // the MutationObserver; disconnecting around them is belt-and-suspenders.\n this.mutationObserver?.disconnect();\n for (const item of items) {\n // Recompute every reserver / spacer on every pass (do not gate on a value\n // being present), so stale state clears when rows change — e.g. when the\n // last degree row, the last unit, or the last source is removed.\n // The numeric reserve is a width in DIGITS, so applying it to a text\n // block would pad short text (\"Auto\" padded out to \"0000.0\"'s width).\n // Text rows hug their own content instead. Setpoint / advice stay\n // numeric and keep the shared reserve even on a text row.\n item.valueOptions = {\n ...item.valueOptions,\n spaceReserver: isTextValueRow(item) ? undefined : numericReserver,\n };\n item.setpointOptions = {\n ...item.setpointOptions,\n spaceReserver: numericReserver,\n };\n item.adviceOptions = {\n ...item.adviceOptions,\n spaceReserver: numericReserver,\n };\n item.unitOptions = {\n ...item.unitOptions,\n spaceReserver: longestUnit || undefined,\n };\n item.srcOptions = {\n ...item.srcOptions,\n spaceReserver: longestSrc || undefined,\n };\n item.hasDegreeSpacer = anyDegree && !item.hasDegree;\n item.showDebugOverlay = this.showDebugOverlay;\n }\n this.observeChildren();\n }\n\n private observeChildren(): void {\n if (!this.mutationObserver) {\n this.mutationObserver = new MutationObserver(() => this.align());\n }\n this.mutationObserver.observe(this, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: OBSERVED_ATTRIBUTES,\n });\n }\n\n private handleSlotChange = (): void => {\n this.align();\n this.observeChildren();\n };\n\n override render() {\n return html`\n <div class=\"list\" part=\"list\">\n <slot @slotchange=${this.handleSlotChange}></slot>\n </div>\n `;\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-readout-list': ObcReadoutList;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -227,13 +227,22 @@ export declare class ObcReadoutListItem extends LitElement {
|
|
|
227
227
|
hasDegreeSpacer: boolean;
|
|
228
228
|
/**
|
|
229
229
|
* Also formats the numeric setpoint / advice blocks, which stay numeric
|
|
230
|
-
* even when the value is text.
|
|
230
|
+
* even when the value is text. Must be between 0 and 100 — the range
|
|
231
|
+
* `Number.prototype.toFixed` accepts; outside it throws a `RangeError`.
|
|
232
|
+
* A fractional count truncates (`2.7` → `2`). A count that never arrived
|
|
233
|
+
* (`NaN`, `null` or unset) renders the reading as the unavailable dash —
|
|
234
|
+
* formatting with a precision the author never chose would let a critical
|
|
235
|
+
* `0.4` pass for a healthy `0`.
|
|
231
236
|
* @availableWhen valueType==number || hasSetpoint==true || hasAdvice==true
|
|
232
237
|
*/
|
|
233
238
|
fractionDigits: number;
|
|
234
239
|
/**
|
|
235
240
|
* Also formats the numeric setpoint / advice blocks, which stay numeric
|
|
236
|
-
* even when the value is text.
|
|
241
|
+
* even when the value is text. Bounded before use: a fractional count
|
|
242
|
+
* truncates (`2.7` → `2`), anything above 100 — including `Infinity` —
|
|
243
|
+
* caps at 100, and a negative count reserves nothing. A count that never
|
|
244
|
+
* arrived (`NaN`, `null` or unset) renders the reading as the unavailable
|
|
245
|
+
* dash, consistent with `fractionDigits`.
|
|
237
246
|
* @availableWhen valueType==number || hasSetpoint==true || hasAdvice==true
|
|
238
247
|
*/
|
|
239
248
|
maxDigits: number;
|
|
@@ -259,6 +268,14 @@ export declare class ObcReadoutListItem extends LitElement {
|
|
|
259
268
|
private get resolvedPriority();
|
|
260
269
|
private get resolvedFractionDigits();
|
|
261
270
|
private get resolvedMaxDigits();
|
|
271
|
+
/**
|
|
272
|
+
* Whether a digit knob failed to arrive (`NaN` / `null` / `undefined`).
|
|
273
|
+
* The raw knobs are forwarded to the blocks, which render the reading as
|
|
274
|
+
* the unavailable dash (see `obc-readout-block.digitCountsMissing`); this
|
|
275
|
+
* getter only keeps the setpoint comparison in agreement with what is
|
|
276
|
+
* displayed.
|
|
277
|
+
*/
|
|
278
|
+
private get digitCountsMissing();
|
|
262
279
|
private get resolvedClickable();
|
|
263
280
|
private get isAtSetpoint();
|
|
264
281
|
private get resolvedSetpointInteraction();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readout-list-item.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/readout-list-item/readout-list-item.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAgD,MAAM,KAAK,CAAC;AAK9E,OAAO,qCAAqC,CAAC;AAC7C,OAAO,EAEL,oBAAoB,EACrB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,sDAAsD,CAAC;AAC9D,OAAO,EAEL,gBAAgB,EAChB,uBAAuB,EAExB,MAAM,sDAAsD,CAAC;AAC9D,OAAO,
|
|
1
|
+
{"version":3,"file":"readout-list-item.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/readout-list-item/readout-list-item.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ import componentStyle from "./readout-list-item.css.js";
|
|
|
5
5
|
import { customElement } from "../../decorator.js";
|
|
6
6
|
import { ObcTextboxFontWeight, ObcTextboxSize } from "../../components/textbox/textbox.js";
|
|
7
7
|
import { ReadoutBlockHidePhase, ReadoutBlockSize, ReadoutBlockVariant, ReadoutBlockDataQuality } from "../../building-blocks/readout-block/readout-block.js";
|
|
8
|
-
import { ReadoutValueType, resolveReadoutNumericValue, assertReadoutValueType } from "../readout/readout-formatters.js";
|
|
8
|
+
import { ReadoutValueType, resolveReadoutDigitCount, isReadoutDigitCountMissing, resolveReadoutNumericValue, assertReadoutValueType, assertReadoutFractionDigits } from "../readout/readout-formatters.js";
|
|
9
9
|
import { isDisplayedAtSetpoint, readoutPrimarySize, readoutSecondarySize, readoutSetpointWeight, readoutNumericFormatOptions, readoutDataQualityClasses, resolveSetpointHidePhase } from "../readout/readout-shared.js";
|
|
10
10
|
import { wrapWithAlertFrame, ObcAlertFrameThickness, ObcAlertFrameType, ObcAlertFrameMode } from "../../components/alert-frame/alert-frame.js";
|
|
11
11
|
import { AlertType } from "../../types.js";
|
|
@@ -78,7 +78,17 @@ let ObcReadoutListItem = class extends LitElement {
|
|
|
78
78
|
return this.fractionDigits ?? 0;
|
|
79
79
|
}
|
|
80
80
|
get resolvedMaxDigits() {
|
|
81
|
-
return this.maxDigits
|
|
81
|
+
return resolveReadoutDigitCount(this.maxDigits);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Whether a digit knob failed to arrive (`NaN` / `null` / `undefined`).
|
|
85
|
+
* The raw knobs are forwarded to the blocks, which render the reading as
|
|
86
|
+
* the unavailable dash (see `obc-readout-block.digitCountsMissing`); this
|
|
87
|
+
* getter only keeps the setpoint comparison in agreement with what is
|
|
88
|
+
* displayed.
|
|
89
|
+
*/
|
|
90
|
+
get digitCountsMissing() {
|
|
91
|
+
return isReadoutDigitCountMissing(this.fractionDigits) || isReadoutDigitCountMissing(this.maxDigits);
|
|
82
92
|
}
|
|
83
93
|
get resolvedClickable() {
|
|
84
94
|
const clickable = this.clickable;
|
|
@@ -100,6 +110,9 @@ let ObcReadoutListItem = class extends LitElement {
|
|
|
100
110
|
if (!this.hasSetpoint) {
|
|
101
111
|
return false;
|
|
102
112
|
}
|
|
113
|
+
if (this.digitCountsMissing) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
103
116
|
return isDisplayedAtSetpoint(
|
|
104
117
|
resolveReadoutNumericValue(this.value, this.valueType) ?? null,
|
|
105
118
|
this.setpoint,
|
|
@@ -201,8 +214,8 @@ let ObcReadoutListItem = class extends LitElement {
|
|
|
201
214
|
.weight=${config.weight}
|
|
202
215
|
.hasDegree=${config.hasDegree ?? false}
|
|
203
216
|
.hasIcon=${config.hasIcon ?? false}
|
|
204
|
-
.fractionDigits=${this.
|
|
205
|
-
.maxDigits=${this.
|
|
217
|
+
.fractionDigits=${this.fractionDigits}
|
|
218
|
+
.maxDigits=${this.maxDigits}
|
|
206
219
|
.hintedZeros=${config.hintedZeros}
|
|
207
220
|
.spaceReserver=${config.spaceReserver}
|
|
208
221
|
.off=${config.off ?? false}
|
|
@@ -499,6 +512,7 @@ let ObcReadoutListItem = class extends LitElement {
|
|
|
499
512
|
willUpdate(changed) {
|
|
500
513
|
super.willUpdate(changed);
|
|
501
514
|
assertReadoutValueType("obc-readout-list-item", this.value, this.valueType);
|
|
515
|
+
assertReadoutFractionDigits("obc-readout-list-item", this.fractionDigits);
|
|
502
516
|
}
|
|
503
517
|
updated(changed) {
|
|
504
518
|
super.updated(changed);
|