@oicl/openbridge-webcomponents 2.0.0-next.111 → 2.0.0-next.113
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/openbridge-webcomponents.bundle.js +185 -29
- package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
- package/custom-elements.json +180 -21
- package/dist/building-blocks/readout-block/readout-block.d.ts +29 -5
- package/dist/building-blocks/readout-block/readout-block.d.ts.map +1 -1
- package/dist/building-blocks/readout-block/readout-block.js +21 -7
- package/dist/building-blocks/readout-block/readout-block.js.map +1 -1
- package/dist/navigation-instruments/compass/compass.d.ts +1 -1
- package/dist/navigation-instruments/compass/compass.d.ts.map +1 -1
- package/dist/navigation-instruments/compass/compass.js +1 -1
- package/dist/navigation-instruments/compass/compass.js.map +1 -1
- package/dist/navigation-instruments/current/current.d.ts +25 -0
- package/dist/navigation-instruments/current/current.d.ts.map +1 -1
- package/dist/navigation-instruments/current/current.js +25 -4
- package/dist/navigation-instruments/current/current.js.map +1 -1
- package/dist/navigation-instruments/heading/heading.js +1 -1
- package/dist/navigation-instruments/heading/heading.js.map +1 -1
- package/dist/navigation-instruments/pitch-roll-heave/pitch-roll-heave.d.ts +6 -0
- package/dist/navigation-instruments/pitch-roll-heave/pitch-roll-heave.d.ts.map +1 -1
- package/dist/navigation-instruments/pitch-roll-heave/pitch-roll-heave.js +8 -1
- package/dist/navigation-instruments/pitch-roll-heave/pitch-roll-heave.js.map +1 -1
- package/dist/navigation-instruments/rate-of-turn/rate-of-turn.d.ts +5 -2
- package/dist/navigation-instruments/rate-of-turn/rate-of-turn.d.ts.map +1 -1
- package/dist/navigation-instruments/rate-of-turn/rate-of-turn.js.map +1 -1
- package/dist/navigation-instruments/readout/readout-formatters.d.ts +31 -0
- package/dist/navigation-instruments/readout/readout-formatters.d.ts.map +1 -1
- package/dist/navigation-instruments/readout/readout-formatters.js +55 -1
- package/dist/navigation-instruments/readout/readout-formatters.js.map +1 -1
- package/dist/navigation-instruments/readout/readout.d.ts +26 -1
- package/dist/navigation-instruments/readout/readout.d.ts.map +1 -1
- package/dist/navigation-instruments/readout/readout.js +16 -3
- package/dist/navigation-instruments/readout/readout.js.map +1 -1
- package/dist/navigation-instruments/readout-list/readout-list.d.ts +6 -1
- package/dist/navigation-instruments/readout-list/readout-list.d.ts.map +1 -1
- package/dist/navigation-instruments/readout-list/readout-list.js +21 -4
- package/dist/navigation-instruments/readout-list/readout-list.js.map +1 -1
- package/dist/navigation-instruments/readout-list-item/readout-list-item.d.ts +26 -1
- package/dist/navigation-instruments/readout-list-item/readout-list-item.d.ts.map +1 -1
- package/dist/navigation-instruments/readout-list-item/readout-list-item.js +15 -3
- package/dist/navigation-instruments/readout-list-item/readout-list-item.js.map +1 -1
- package/dist/navigation-instruments/top-view-propulsion/top-view-propulsion.d.ts +6 -0
- package/dist/navigation-instruments/top-view-propulsion/top-view-propulsion.d.ts.map +1 -1
- package/dist/navigation-instruments/top-view-propulsion/top-view-propulsion.js +19 -4
- package/dist/navigation-instruments/top-view-propulsion/top-view-propulsion.js.map +1 -1
- package/dist/navigation-instruments/watch/environment.d.ts +8 -0
- package/dist/navigation-instruments/watch/environment.d.ts.map +1 -1
- package/dist/navigation-instruments/watch/environment.js +3 -0
- package/dist/navigation-instruments/watch/environment.js.map +1 -1
- package/dist/navigation-instruments/watch/force-pattern.d.ts +20 -2
- package/dist/navigation-instruments/watch/force-pattern.d.ts.map +1 -1
- package/dist/navigation-instruments/watch/force-pattern.js +12 -5
- package/dist/navigation-instruments/watch/force-pattern.js.map +1 -1
- package/dist/navigation-instruments/watch/watch.d.ts.map +1 -1
- package/dist/navigation-instruments/watch/watch.js +6 -4
- package/dist/navigation-instruments/watch/watch.js.map +1 -1
- package/dist/navigation-instruments/wind/wind.d.ts +5 -2
- package/dist/navigation-instruments/wind/wind.d.ts.map +1 -1
- package/dist/navigation-instruments/wind/wind.js +5 -1
- package/dist/navigation-instruments/wind/wind.js.map +1 -1
- package/package.json +1 -1
|
@@ -200,9 +200,16 @@ let ObcPitchRollHeave = class extends LitElement {
|
|
|
200
200
|
* `obc-watch` renders its crosshair after the bands, i.e. on top of them.
|
|
201
201
|
* Drawing it here puts it under the watch layer, so the bands and the heave
|
|
202
202
|
* column mask it naturally.
|
|
203
|
+
*
|
|
204
|
+
* In `single-scale` nothing frames the segment above the vessel (the other
|
|
205
|
+
* three arms end under the pitch band, roll band and heave column), so the
|
|
206
|
+
* vertical arm stops at the centre instead of continuing upward. In
|
|
207
|
+
* `dual-scale` the top roll band gives it a natural endpoint, so the full
|
|
208
|
+
* arm is kept.
|
|
203
209
|
*/
|
|
204
210
|
renderCrosshair() {
|
|
205
211
|
const r = OUTER_RING_RADIUS;
|
|
212
|
+
const yTop = this.isDualScale ? -r : 0;
|
|
206
213
|
return svg`
|
|
207
214
|
<line
|
|
208
215
|
x1=${-r} y1="0" x2=${r} y2="0"
|
|
@@ -210,7 +217,7 @@ let ObcPitchRollHeave = class extends LitElement {
|
|
|
210
217
|
vector-effect="non-scaling-stroke"
|
|
211
218
|
/>
|
|
212
219
|
<line
|
|
213
|
-
x1="0" y1=${
|
|
220
|
+
x1="0" y1=${yTop} x2="0" y2=${r}
|
|
214
221
|
stroke="var(--instrument-frame-tertiary-color)"
|
|
215
222
|
vector-effect="non-scaling-stroke"
|
|
216
223
|
/>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pitch-roll-heave.js","sources":["../../../src/navigation-instruments/pitch-roll-heave/pitch-roll-heave.ts"],"sourcesContent":["import {LitElement, css, html, nothing, svg, type SVGTemplateResult} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport '../watch/watch.js';\nimport {\n VesselImage,\n VesselImageSize,\n WatchCircleType,\n type WatchArea,\n OUTER_RING_RADIUS,\n innerRingRadiusFor,\n vesselImages,\n} from '../watch/watch.js';\nimport {arcTickmarks, TickmarkType, type Tickmark} from '../watch/tickmark.js';\nimport {AdviceState, AdviceType, type AngleAdviceRaw} from '../watch/advice.js';\nimport {customElement} from '../../decorator.js';\nimport {Priority} from '../types.js';\nimport {\n CenterReadoutArrangement,\n centerReadoutStyles,\n renderCenterReadouts,\n} from '../readout/center-readout.js';\nimport {ReadoutSize} from '../readout/readout.js';\nimport {\n computeZoomToFitArcFrame,\n normalizeArcAngle,\n shiftArcFrameToOuterEdge,\n} from '../../svghelpers/arc-frame.js';\nimport {\n linearTickInterval,\n watchfaceLinear,\n} from '../../building-blocks/instrument-linear/instrument-linear.js';\nimport type {\n LinearAdvice,\n LinearAdviceRaw,\n} from '../../building-blocks/instrument-linear/advice.js';\n\nexport enum ObcPitchRollHeaveType {\n /** Pitch on the right, roll at the bottom, heave in the left band slot. */\n singleScale = 'single-scale',\n /** Pitch and roll mirrored onto both sides, heave centred. */\n dualScale = 'dual-scale',\n}\n\nexport enum PitchRollHeavePriorityElement {\n pitch = 'pitch',\n roll = 'roll',\n heave = 'heave',\n}\n\n/** Half-side of the centre overlay viewBox in SVG units. */\nconst CENTRE_HALF = 200;\n\n/**\n * Minimum diagonal clearance, in central-layer pixels, between the zoomed\n * heave column and the adjacent roll band. Matches the constant\n * `obc-pitch-roll` uses between its own adjacent arcs.\n */\nconst CORNER_GAP_PX = 32;\n\n/** Numerical safety floor when an axis arc has to collapse for clearance. */\nconst MIN_ARC_HALF_DEG = 2;\n\n/** Width of the tick lane inside the heave column, in SVG units. */\nconst HEAVE_SCALE_WIDTH = 24;\n\n/** Band thickness at the natural, un-zoomed radii. */\nconst NOMINAL_BAND =\n OUTER_RING_RADIUS - innerRingRadiusFor(WatchCircleType.double);\n\n/**\n * Clearance kept between the centred (`dual-scale`) heave column's corners and\n * the surrounding band, in central-layer pixels. Sized so the un-zoomed\n * default is untouched — there the corner sits 13.2 units inside the free\n * radius — while the tighter zoomed layout is pulled back off the bands.\n */\nconst HEAVE_CENTRE_GAP_PX = 10;\n\n/**\n * The band slot the heave column fills, in central-layer coordinates.\n *\n * `outerR`/`innerR` bound the slot radially; `capRadius` is the radius of the\n * pitch arc's outer edge about its own origin, which is what the column's\n * height is measured against so the two line up. Un-zoomed the two radii\n * coincide; under zoom the arc is drawn on a shifted sub-watch and they differ.\n */\ninterface HeaveBand {\n outerR: number;\n innerR: number;\n capRadius: number;\n pitchDeg: number;\n}\n\n/**\n * Natural size of the heave column: as thick as the band slot, and tall enough\n * that its top and bottom edges sit level with the pitch arc's end caps.\n */\nfunction heaveColumnSize(band: HeaveBand): {width: number; height: number} {\n return {\n width: band.outerR - band.innerR,\n height: 2 * band.capRadius * Math.sin((band.pitchDeg * Math.PI) / 180),\n };\n}\n\n/**\n * Distance from a point to an axis-aligned rectangle; 0 when the point is\n * inside. Used to keep the zoomed roll band clear of the heave column, which\n * — unlike the arc-to-arc case — is a rectangle, so a corner may clear it on\n * one axis alone.\n */\nfunction distanceToRect(\n px: number,\n py: number,\n x0: number,\n y0: number,\n x1: number,\n y1: number\n): number {\n const dx = Math.max(0, x0 - px, px - x1);\n const dy = Math.max(0, y0 - py, py - y1);\n return Math.hypot(dx, dy);\n}\n\n/**\n * `<obc-pitch-roll-heave>` — Combined pitch, roll and heave indicator.\n *\n * Places a pitch arc, a roll arc and a linear heave column around one watch\n * face. The heave column occupies the same radial slot as the arcs, and its\n * height is derived from the pitch arc so its top and bottom edges sit level\n * with the pitch arc's end caps.\n *\n * Variants (`type`):\n * - `single-scale` (default) — pitch on the right, roll at the bottom, heave in\n * the left slot, vessel silhouettes in the centre.\n * - `dual-scale` — pitch and roll mirrored onto the opposite sides, with the\n * heave column moved to the centre.\n *\n * Set `hasReadout` to replace the centre content with stacked pitch, roll and\n * heave readouts, and `zoomToFitArc` to enlarge narrow arcs so they fill the\n * available space.\n *\n * @element obc-pitch-roll-heave\n * @experimental\n */\n@customElement('obc-pitch-roll-heave')\nexport class ObcPitchRollHeave extends LitElement {\n @property({type: String}) type: ObcPitchRollHeaveType =\n ObcPitchRollHeaveType.singleScale;\n\n @property({type: Number}) pitch = 0;\n @property({type: Number}) roll = 0;\n @property({type: Number}) heave = 0;\n @property({type: Number}) minAvgPitch = 0;\n @property({type: Number}) maxAvgPitch = 0;\n @property({type: Number}) minAvgRoll = 0;\n @property({type: Number}) maxAvgRoll = 0;\n @property({type: Number}) minTrendHeave = 0;\n @property({type: Number}) maxTrendHeave = 0;\n /** Half-extent of the heave scale in metres; the column spans `±heaveRange`. */\n @property({type: Number}) heaveRange = 10;\n\n /**\n * Half-extent of the pitch arc in degrees. Also drives the heave column\n * height, which is `2 · outerRadius · sin(pitchArcAngle)` so the column's\n * edges stay level with the pitch arc's end caps.\n */\n @property({type: Number}) pitchArcAngle = 30;\n /** Half-extent of the roll arc in degrees. */\n @property({type: Number}) rollArcAngle = 45;\n @property({type: Boolean}) zoomToFitArc = false;\n\n /**\n * Replaces the centre content with stacked pitch, roll and heave readouts.\n * Ignored when `type` is `dual-scale`, where the heave column occupies the\n * centre.\n * @availableWhen type==singleScale\n */\n @property({type: Boolean}) hasReadout = false;\n /** @availableWhen hasReadout==true */\n @property({type: String}) pitchLabel = 'Pitch';\n /** @availableWhen hasReadout==true */\n @property({type: String}) rollLabel = 'Roll';\n /** @availableWhen hasReadout==true */\n @property({type: String}) heaveLabel = 'Heave';\n /**\n * Unit shown in the pitch and roll readouts.\n * @availableWhen hasReadout==true\n */\n @property({type: String}) unit = 'DEG';\n /**\n * Unit shown in the heave readout.\n * @availableWhen hasReadout==true\n */\n @property({type: String}) heaveUnit = 'm';\n /** @availableWhen hasReadout==true */\n @property({type: Number}) fractionDigits = 0;\n\n /** @availableWhen type==singleScale && hasReadout==false */\n @property({type: String}) vesselImageFore: VesselImage = VesselImage.psvFore;\n /** @availableWhen type==singleScale && hasReadout==false */\n @property({type: String}) vesselImageSide: VesselImage = VesselImage.psvSide;\n /** @availableWhen type==singleScale && hasReadout==false */\n @property({type: Number}) scaleForeImage = 1;\n\n @property({type: Number}) maxPitchAdvice: number | undefined = undefined;\n @property({type: Number}) maxRollAdvice: number | undefined = undefined;\n /** @availableWhen maxPitchAdvice!=undefined */\n @property({type: Boolean}) triggerPitchAdvice = false;\n /** @availableWhen maxRollAdvice!=undefined */\n @property({type: Boolean}) triggerRollAdvice = false;\n @property({type: Array}) heaveAdvice: LinearAdvice[] = [];\n\n @property({type: String}) priority: Priority = Priority.regular;\n @property({type: Array, attribute: false})\n priorityElements: PitchRollHeavePriorityElement[] = [\n PitchRollHeavePriorityElement.pitch,\n PitchRollHeavePriorityElement.roll,\n PitchRollHeavePriorityElement.heave,\n ];\n\n private priorityFor(element: PitchRollHeavePriorityElement): Priority {\n const selected = Array.isArray(this.priorityElements)\n ? this.priorityElements\n : [];\n return selected.includes(element) ? this.priority : Priority.regular;\n }\n\n private needleColor(element: PitchRollHeavePriorityElement): string {\n return this.priorityFor(element) === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n\n private barColor(element: PitchRollHeavePriorityElement): string {\n return this.priorityFor(element) === Priority.enhanced\n ? 'var(--instrument-enhanced-tertiary-color)'\n : 'var(--instrument-regular-tertiary-color)';\n }\n\n private get normalizedScaleForeImage(): number {\n if (!Number.isFinite(this.scaleForeImage)) {\n return 1;\n }\n return Math.max(0, Math.min(2, this.scaleForeImage));\n }\n\n private get isDualScale(): boolean {\n return this.type === ObcPitchRollHeaveType.dualScale;\n }\n\n /** The centre readouts replace the vessels; never available in dual scale. */\n private get showsReadout(): boolean {\n return this.hasReadout && !this.isDualScale;\n }\n\n /**\n * Pitch half-extent, capped so a roll arc of the minimum size still fits in\n * the remaining quadrant.\n */\n private get requestedPitchArcAngle(): number {\n return Math.min(\n 90 - MIN_ARC_HALF_DEG,\n normalizeArcAngle(this.pitchArcAngle, 30)\n );\n }\n\n /**\n * Roll half-extent, clamped so the pitch and roll arcs cannot meet: the two\n * diagonal gaps each span `90 - pitch - roll` degrees, so the pair has to\n * stay under 90° combined.\n */\n private get requestedRollArcAngle(): number {\n const roll = normalizeArcAngle(this.rollArcAngle, 45);\n const headroom = 90 - this.requestedPitchArcAngle;\n return Math.max(MIN_ARC_HALF_DEG, Math.min(roll, headroom));\n }\n\n override render() {\n const pitchReq = this.requestedPitchArcAngle;\n const rollReq = this.requestedRollArcAngle;\n const overlayViewBox = `-${CENTRE_HALF} -${CENTRE_HALF} ${CENTRE_HALF * 2} ${CENTRE_HALF * 2}`;\n\n const layout = this.zoomToFitArc\n ? this.zoomLayout(pitchReq, rollReq)\n : undefined;\n const band: HeaveBand = layout?.band ?? {\n outerR: OUTER_RING_RADIUS,\n innerR: innerRingRadiusFor(WatchCircleType.double),\n capRadius: OUTER_RING_RADIUS,\n pitchDeg: pitchReq,\n };\n\n return html`\n <div class=\"container\">\n <svg viewBox=${overlayViewBox}>\n ${this.showsReadout ? nothing : this.renderCrosshair()}\n ${this.renderOverlayVessels()}\n ${this.zoomToFitArc || this.isDualScale\n ? nothing\n : this.renderComplement(pitchReq)}\n ${this.renderHeaveColumn(band)}\n </svg>\n ${layout\n ? this.renderZoomedArcs(layout)\n : this.renderFullWatch(pitchReq, rollReq)}\n ${this.showsReadout\n ? html`<div class=\"readout\">\n ${renderCenterReadouts(\n [\n {\n value: this.pitch,\n label: this.pitchLabel,\n unit: this.unit,\n fractionDigits: this.fractionDigits,\n size: ReadoutSize.large,\n priority: this.priorityFor(\n PitchRollHeavePriorityElement.pitch\n ),\n },\n {\n value: this.roll,\n label: this.rollLabel,\n unit: this.unit,\n fractionDigits: this.fractionDigits,\n size: ReadoutSize.large,\n priority: this.priorityFor(\n PitchRollHeavePriorityElement.roll\n ),\n },\n {\n value: this.heave,\n label: this.heaveLabel,\n unit: this.heaveUnit,\n fractionDigits: this.fractionDigits,\n size: ReadoutSize.large,\n priority: this.priorityFor(\n PitchRollHeavePriorityElement.heave\n ),\n },\n ],\n CenterReadoutArrangement.stacked\n )}\n </div>`\n : nothing}\n </div>\n `;\n }\n\n /**\n * Crosshair drawn on the overlay rather than through `obc-watch`'s own\n * `crosshairEnabled`: the design has the arc bands covering the arms, but\n * `obc-watch` renders its crosshair after the bands, i.e. on top of them.\n * Drawing it here puts it under the watch layer, so the bands and the heave\n * column mask it naturally.\n */\n private renderCrosshair(): SVGTemplateResult {\n const r = OUTER_RING_RADIUS;\n return svg`\n <line\n x1=${-r} y1=\"0\" x2=${r} y2=\"0\"\n stroke=\"var(--instrument-frame-tertiary-color)\"\n vector-effect=\"non-scaling-stroke\"\n />\n <line\n x1=\"0\" y1=${-r} x2=\"0\" y2=${r}\n stroke=\"var(--instrument-frame-tertiary-color)\"\n vector-effect=\"non-scaling-stroke\"\n />\n `;\n }\n\n /**\n * Vessel silhouettes on the centre layer. Only needed under zoom — the\n * un-zoomed path hands them to `obc-watch` via `vessels`, while the zoomed\n * sub-watches have no room for them.\n */\n private renderOverlayVessels(): SVGTemplateResult | typeof nothing {\n if (!this.zoomToFitArc || this.isDualScale || this.showsReadout) {\n return nothing;\n }\n const vesselScale = 224 / 160;\n return svg`\n <g style=\"transform: rotate(${this.pitch}deg) scale(${vesselScale}) translate(-80px, -80px);\">\n ${vesselImages[this.vesselImageSide]}\n </g>\n <g style=\"transform: rotate(${this.roll}deg) scale(${vesselScale * this.normalizedScaleForeImage}) translate(-80px, -80px);\">\n ${vesselImages[this.vesselImageFore]}\n </g>\n `;\n }\n\n /**\n * Thin ring bridging the empty span across the top, from where the heave\n * column's upper edge crosses the outer ring round to the pitch arc's start.\n * Because the column height is derived from the pitch arc, both ends land at\n * `±pitchArcAngle` off the vertical, making the ring symmetric. The two\n * diagonal gaps lower down are left open by design.\n */\n private renderComplement(pitchDeg: number): SVGTemplateResult {\n const r = OUTER_RING_RADIUS;\n const rad = (pitchDeg * Math.PI) / 180;\n // Ring runs clockwise from (270 + pitchDeg) through 0 to (90 - pitchDeg).\n const x1 = -r * Math.cos(rad);\n const y1 = -r * Math.sin(rad);\n const x2 = r * Math.cos(rad);\n const y2 = -r * Math.sin(rad);\n return svg`\n <path\n d=\"M ${x1} ${y1} A ${r} ${r} 0 0 1 ${x2} ${y2}\"\n fill=\"none\"\n stroke=\"var(--instrument-frame-tertiary-color)\"\n vector-effect=\"non-scaling-stroke\"\n />\n `;\n }\n\n /**\n * Linear heave scale, built from the same building block `obc-heave` uses.\n *\n * The column fills the band's radial slot, so its width equals the band\n * thickness and its height keeps its top and bottom edges level with the\n * pitch arc's end caps. In `single-scale` it sits in the left slot and is\n * mirrored so the tick lane faces outward; in `dual-scale` it moves to the\n * centre, unmirrored, and shrinks if the zoomed bands leave too little room.\n */\n private renderHeaveColumn(band: HeaveBand): SVGTemplateResult {\n const {width, height: naturalHeight} = heaveColumnSize(band);\n let height = naturalHeight;\n let offsetX = -(band.outerR + band.innerR) / 2;\n\n if (this.isDualScale) {\n offsetX = 0;\n // The centred column has to stay inside whatever the bands leave free.\n // Only the height gives way: the column's thickness reads as a match for\n // the band thickness, and shrinking both would break that.\n const free = band.innerR - HEAVE_CENTRE_GAP_PX;\n const halfWidth = width / 2;\n const maxHalfHeight =\n free > halfWidth ? Math.sqrt(free * free - halfWidth * halfWidth) : 0;\n height = Math.min(height, 2 * maxHalfHeight);\n }\n\n const scaleWidth = HEAVE_SCALE_WIDTH * Math.min(1, width / NOMINAL_BAND);\n\n const gauge = watchfaceLinear(\n {\n height,\n width,\n scaleWidth,\n minValue: -this.heaveRange,\n maxValue: this.heaveRange,\n },\n [{min: this.minTrendHeave, max: this.maxTrendHeave}],\n {value: this.heave},\n {container: 'var(--instrument-frame-primary-color)'},\n {\n hideContainer: false,\n off: false,\n priority: this.priorityFor(PitchRollHeavePriorityElement.heave),\n },\n {\n mainTickmarks: [],\n primaryTickmarkInterval: 0,\n secondaryTickmarkInterval: linearTickInterval(height, this.heaveRange),\n },\n this.heaveAdvices\n );\n\n const mirror = this.isDualScale ? '' : ' scale(-1, 1)';\n return svg`<g transform=\"translate(${offsetX}, 0)${mirror}\">${gauge}</g>`;\n }\n\n private get heaveAdvices(): LinearAdviceRaw[] {\n return this.heaveAdvice.map((advice) => {\n const isActive =\n this.maxTrendHeave >= advice.min && this.minTrendHeave <= advice.max;\n const state = isActive\n ? AdviceState.triggered\n : advice.hinted\n ? AdviceState.hinted\n : AdviceState.regular;\n return {...advice, state} satisfies LinearAdviceRaw;\n });\n }\n\n /**\n * Zoom-fit geometry, computed once per render and shared by the arc layer\n * and the heave column.\n *\n * Frames are built at the REQUESTED half-extents with the same math as\n * `obc-pitch` / `obc-roll`, so each sub-watch matches its standalone\n * equivalent. Two clearance passes then shorten only the *rendered* arcs —\n * the frames stay untouched, so band thickness, position and zoom level are\n * preserved:\n *\n * 1. pitch vs roll at the diagonal, ratio-preserving, exactly as\n * `obc-pitch-roll` does it;\n * 2. roll vs the heave column, `single-scale` only, shortening the roll arc\n * alone. Because the column's height follows the pitch arc, pass 1 already\n * pulls the column in whenever pitch shrinks, so pitch needs no second\n * pass.\n */\n private zoomLayout(pitchReq: number, rollReq: number) {\n const ext = 48;\n const targetSize = (176 + ext) * 2;\n const innerNat = innerRingRadiusFor(WatchCircleType.double);\n const buildFrame = (halfDeg: number) => {\n const areas: WatchArea[] = [\n {\n startAngle: -halfDeg,\n endAngle: halfDeg,\n roundOutsideCut: true,\n roundInsideCut: true,\n },\n ];\n const baseFrame = computeZoomToFitArcFrame({\n areas,\n outerRadius: OUTER_RING_RADIUS,\n innerRadius: innerNat,\n extension: ext,\n targetSize,\n });\n const subArcFrame = shiftArcFrameToOuterEdge(\n baseFrame,\n OUTER_RING_RADIUS + baseFrame.radiusOffset,\n OUTER_RING_RADIUS,\n CENTRE_HALF\n );\n const scale = (CENTRE_HALF * 2) / subArcFrame.width;\n const outerR = (OUTER_RING_RADIUS + baseFrame.radiusOffset) * scale;\n const innerR = (innerNat + baseFrame.radiusOffset) * scale;\n return {subArcFrame, outerR, innerR};\n };\n const pitchFrame = buildFrame(pitchReq);\n const rollFrame = buildFrame(rollReq);\n\n const OR = OUTER_RING_RADIUS;\n const toRad = (deg: number) => (deg * Math.PI) / 180;\n const signedDist = (\n px: number,\n py: number,\n qx: number,\n qy: number\n ): number => {\n const dx = qx - px;\n const dy = qy - py;\n const mag = Math.hypot(dx, dy);\n return dx > 0 && dy > 0 ? mag : -mag;\n };\n // Diagonal gap between two adjacent cardinal bands. All such gaps in this\n // layout are congruent, so one pair stands in for the rest.\n const minGap = (apRad: number, arRad: number): number => {\n const cosP = Math.cos(apRad);\n const sinP = Math.sin(apRad);\n const cosR = Math.cos(arRad);\n const sinR = Math.sin(arRad);\n const p1x = pitchFrame.innerR * sinP;\n const p1y = pitchFrame.outerR - OR - pitchFrame.innerR * cosP;\n const p2x = pitchFrame.outerR * sinP;\n const p2y = pitchFrame.outerR - OR - pitchFrame.outerR * cosP;\n const q1x = OR - rollFrame.outerR + rollFrame.innerR * cosR;\n const q1y = -rollFrame.innerR * sinR;\n const q2x = OR - rollFrame.outerR + rollFrame.outerR * cosR;\n const q2y = -rollFrame.outerR * sinR;\n return Math.min(\n signedDist(p1x, p1y, q1x, q1y),\n signedDist(p2x, p2y, q2x, q2y)\n );\n };\n\n let aP = toRad(pitchReq);\n let aR = toRad(rollReq);\n if (minGap(aP, aR) < CORNER_GAP_PX) {\n let lo = 0;\n let hi = 1;\n for (let i = 0; i < 40; i++) {\n const mid = (lo + hi) / 2;\n if (minGap(aP * mid, aR * mid) >= CORNER_GAP_PX) {\n lo = mid;\n } else {\n hi = mid;\n }\n }\n aP *= lo;\n aR *= lo;\n }\n const pitchClampedDeg = Math.max(MIN_ARC_HALF_DEG, (aP * 180) / Math.PI);\n let rollClampedDeg = Math.max(MIN_ARC_HALF_DEG, (aR * 180) / Math.PI);\n\n const bandFor = (pitchDeg: number): HeaveBand => ({\n outerR: OR,\n innerR: OR - (pitchFrame.outerR - pitchFrame.innerR),\n capRadius: pitchFrame.outerR,\n pitchDeg,\n });\n\n if (!this.isDualScale) {\n // Roll's left end caps versus the heave column rectangle. Shrinking the\n // roll arc moves both caps toward the bottom cardinal, away from the\n // column, so the gap grows monotonically as the scalar shrinks.\n const band = bandFor(pitchClampedDeg);\n const {width, height} = heaveColumnSize(band);\n const x1 = -band.innerR;\n const x0 = x1 - width;\n const y1 = height / 2;\n const heaveGap = (arRad: number): number => {\n const cosR = Math.cos(arRad);\n const sinR = Math.sin(arRad);\n const outerX = -rollFrame.outerR * sinR;\n const outerY = OR - rollFrame.outerR + rollFrame.outerR * cosR;\n const innerX = -rollFrame.innerR * sinR;\n const innerY = OR - rollFrame.outerR + rollFrame.innerR * cosR;\n return Math.min(\n distanceToRect(outerX, outerY, x0, -y1, x1, y1),\n distanceToRect(innerX, innerY, x0, -y1, x1, y1)\n );\n };\n if (heaveGap(toRad(rollClampedDeg)) < CORNER_GAP_PX) {\n let lo = 0;\n let hi = rollClampedDeg;\n for (let i = 0; i < 40; i++) {\n const mid = (lo + hi) / 2;\n if (heaveGap(toRad(mid)) >= CORNER_GAP_PX) {\n lo = mid;\n } else {\n hi = mid;\n }\n }\n rollClampedDeg = Math.max(MIN_ARC_HALF_DEG, lo);\n }\n }\n\n return {\n pitchFrame,\n rollFrame,\n pitchClampedDeg,\n rollClampedDeg,\n band: bandFor(pitchClampedDeg),\n };\n }\n\n /**\n * Zoomed-arc layer: CSS-rotated `<obc-watch>` instances, each holding a\n * single arc rendered at the watch's natural top and rotated onto its\n * cardinal. `single-scale` places pitch right and roll bottom; `dual-scale`\n * mirrors both. The heave column lives on the centre overlay.\n */\n private renderZoomedArcs(layout: ReturnType<typeof this.zoomLayout>) {\n const {pitchFrame, rollFrame, pitchClampedDeg, rollClampedDeg} = layout;\n\n const subAreas = (halfDeg: number): WatchArea[] => [\n {\n startAngle: -halfDeg,\n endAngle: halfDeg,\n roundOutsideCut: true,\n roundInsideCut: true,\n },\n ];\n\n // Clip each sub-watch to the sector its (possibly shortened) arc covers so\n // the indicator cannot leak past the visible band.\n const sectorClip = (\n halfDeg: number,\n frame: typeof rollFrame.subArcFrame\n ): string => {\n const oxPct = (-frame.x / frame.width) * 100;\n const oyPct = (-frame.y / frame.height) * 100;\n const dxPct = oyPct * Math.tan((halfDeg * Math.PI) / 180);\n const lx = Math.max(0, oxPct - dxPct);\n const rx = Math.min(100, oxPct + dxPct);\n return `polygon(${oxPct}% ${oyPct}%, ${lx}% 0%, ${rx}% 0%)`;\n };\n\n const axis = (\n element: PitchRollHeavePriorityElement,\n frame: typeof rollFrame,\n halfDeg: number,\n value: number,\n avgMin: number,\n avgMax: number,\n max: number | undefined,\n trigger: boolean,\n cap: number\n ) => ({\n arcFrame: frame.subArcFrame,\n areas: subAreas(halfDeg),\n barAreas: [\n {\n startAngle: avgMin,\n endAngle: avgMax,\n fillColor: this.barColor(element),\n },\n ],\n needles: [\n {\n angle: value,\n fillColor: this.needleColor(element),\n strokeColor: 'var(--border-silhouette-color)',\n },\n ],\n advices: this.subAdvices(halfDeg, max, trigger, cap),\n tickmarks: [\n {angle: 0, type: TickmarkType.main},\n ...arcTickmarks(0, halfDeg),\n ],\n clipPath: sectorClip(halfDeg, frame.subArcFrame),\n });\n\n const pitchAxis = axis(\n PitchRollHeavePriorityElement.pitch,\n pitchFrame,\n pitchClampedDeg,\n this.pitch,\n this.minAvgPitch,\n this.maxAvgPitch,\n this.maxPitchAdvice,\n this.triggerPitchAdvice,\n 30\n );\n const rollAxis = axis(\n PitchRollHeavePriorityElement.roll,\n rollFrame,\n rollClampedDeg,\n this.roll,\n this.minAvgRoll,\n this.maxAvgRoll,\n this.maxRollAdvice,\n this.triggerRollAdvice,\n 45\n );\n\n const subWatch = (rotation: number, a: typeof pitchAxis) => html`\n <obc-watch\n class=\"sub-watch\"\n style=\"transform: rotate(${rotation}deg); clip-path: ${a.clipPath};\"\n .watchCircleType=${WatchCircleType.double}\n .zoomToFitArc=${true}\n .arcFrame=${a.arcFrame}\n .areas=${a.areas}\n .barAreas=${a.barAreas}\n .needles=${a.needles}\n .vessels=${[]}\n .tickmarks=${a.tickmarks}\n .advices=${a.advices}\n ></obc-watch>\n `;\n\n return html`\n ${subWatch(90, pitchAxis)} ${subWatch(180, rollAxis)}\n ${this.isDualScale\n ? html`${subWatch(270, pitchAxis)} ${subWatch(0, rollAxis)}`\n : nothing}\n `;\n }\n\n /** Caution bands for one sub-watch axis, at sub-watch-local angles. */\n private subAdvices(\n halfDeg: number,\n max: number | undefined,\n trigger: boolean,\n cap: number\n ): AngleAdviceRaw[] {\n if (max === undefined) return [];\n const outer = Math.min(halfDeg, cap);\n const inner = Math.min(max, outer);\n const state = trigger ? AdviceState.triggered : AdviceState.regular;\n return [\n {\n minAngle: -outer,\n maxAngle: -inner,\n type: AdviceType.caution,\n state,\n hideMinTickmark: true,\n },\n {\n minAngle: inner,\n maxAngle: outer,\n type: AdviceType.caution,\n state,\n hideMaxTickmark: true,\n },\n ];\n }\n\n /** Areas, tickmarks, bars and needles for the un-zoomed single watch. */\n private renderFullWatch(pitchDeg: number, rollDeg: number) {\n const arc = (center: number, half: number): WatchArea => ({\n startAngle: center - half,\n endAngle: center + half,\n roundOutsideCut: true,\n roundInsideCut: true,\n });\n\n const areas: WatchArea[] = [arc(90, pitchDeg), arc(180, rollDeg)];\n const tickmarks: Tickmark[] = [\n {angle: 90, type: TickmarkType.main},\n {angle: 180, type: TickmarkType.main},\n ...arcTickmarks(90, pitchDeg),\n ...arcTickmarks(180, rollDeg),\n ];\n const barAreas = [\n {\n startAngle: 90 + this.minAvgPitch,\n endAngle: 90 + this.maxAvgPitch,\n fillColor: this.barColor(PitchRollHeavePriorityElement.pitch),\n },\n {\n startAngle: 180 + this.minAvgRoll,\n endAngle: 180 + this.maxAvgRoll,\n fillColor: this.barColor(PitchRollHeavePriorityElement.roll),\n },\n ];\n const needles = [\n {\n angle: 90 + this.pitch,\n fillColor: this.needleColor(PitchRollHeavePriorityElement.pitch),\n strokeColor: 'var(--border-silhouette-color)',\n },\n {\n angle: 180 + this.roll,\n fillColor: this.needleColor(PitchRollHeavePriorityElement.roll),\n strokeColor: 'var(--border-silhouette-color)',\n },\n ];\n\n if (this.isDualScale) {\n areas.push(arc(270, pitchDeg), arc(0, rollDeg));\n tickmarks.push(\n {angle: 270, type: TickmarkType.main},\n {angle: 0, type: TickmarkType.main},\n ...arcTickmarks(270, pitchDeg),\n ...arcTickmarks(0, rollDeg)\n );\n barAreas.push(\n {\n startAngle: 270 + this.minAvgPitch,\n endAngle: 270 + this.maxAvgPitch,\n fillColor: this.barColor(PitchRollHeavePriorityElement.pitch),\n },\n {\n startAngle: this.minAvgRoll,\n endAngle: this.maxAvgRoll,\n fillColor: this.barColor(PitchRollHeavePriorityElement.roll),\n }\n );\n needles.push(\n {\n angle: 270 + this.pitch,\n fillColor: this.needleColor(PitchRollHeavePriorityElement.pitch),\n strokeColor: 'var(--border-silhouette-color)',\n },\n {\n angle: this.roll,\n fillColor: this.needleColor(PitchRollHeavePriorityElement.roll),\n strokeColor: 'var(--border-silhouette-color)',\n }\n );\n }\n\n return html`\n <obc-watch\n .watchCircleType=${WatchCircleType.double}\n .zoomToFitArc=${false}\n .areas=${areas}\n .barAreas=${barAreas}\n .needles=${needles}\n .vessels=${this.isDualScale || this.showsReadout\n ? []\n : [\n {\n size: VesselImageSize.large,\n vesselImage: this.vesselImageSide,\n transform: `rotate(${this.pitch}deg)`,\n },\n {\n size: VesselImageSize.large,\n vesselImage: this.vesselImageFore,\n transform: `rotate(${this.roll}deg) scale(${this.normalizedScaleForeImage})`,\n },\n ]}\n .tickmarks=${tickmarks}\n .advices=${this.advices(pitchDeg, rollDeg)}\n ></obc-watch>\n `;\n }\n\n private advices(pitchDeg: number, rollDeg: number): AngleAdviceRaw[] {\n const advices: AngleAdviceRaw[] = [];\n const push = (\n center: number,\n halfDeg: number,\n max: number | undefined,\n trigger: boolean,\n cap: number\n ) => {\n if (max === undefined) return;\n const outer = Math.min(halfDeg, cap);\n const inner = Math.min(max, outer);\n const state = trigger ? AdviceState.triggered : AdviceState.regular;\n advices.push({\n minAngle: center - outer,\n maxAngle: center - inner,\n type: AdviceType.caution,\n state,\n hideMinTickmark: true,\n });\n advices.push({\n minAngle: center + inner,\n maxAngle: center + outer,\n type: AdviceType.caution,\n state,\n hideMaxTickmark: true,\n });\n };\n push(90, pitchDeg, this.maxPitchAdvice, this.triggerPitchAdvice, 30);\n push(180, rollDeg, this.maxRollAdvice, this.triggerRollAdvice, 45);\n if (this.isDualScale) {\n push(270, pitchDeg, this.maxPitchAdvice, this.triggerPitchAdvice, 30);\n push(0, rollDeg, this.maxRollAdvice, this.triggerRollAdvice, 45);\n }\n return advices;\n }\n\n static override styles = [\n centerReadoutStyles,\n css`\n * {\n box-sizing: border-box;\n }\n\n .container {\n position: relative;\n width: 100%;\n height: 100%;\n }\n\n .container > * {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n }\n\n .readout {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n `,\n ];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-pitch-roll-heave': ObcPitchRollHeave;\n }\n}\n"],"names":["ObcPitchRollHeaveType","PitchRollHeavePriorityElement"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pitch-roll-heave.js","sources":["../../../src/navigation-instruments/pitch-roll-heave/pitch-roll-heave.ts"],"sourcesContent":["import {LitElement, css, html, nothing, svg, type SVGTemplateResult} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport '../watch/watch.js';\nimport {\n VesselImage,\n VesselImageSize,\n WatchCircleType,\n type WatchArea,\n OUTER_RING_RADIUS,\n innerRingRadiusFor,\n vesselImages,\n} from '../watch/watch.js';\nimport {arcTickmarks, TickmarkType, type Tickmark} from '../watch/tickmark.js';\nimport {AdviceState, AdviceType, type AngleAdviceRaw} from '../watch/advice.js';\nimport {customElement} from '../../decorator.js';\nimport {Priority} from '../types.js';\nimport {\n CenterReadoutArrangement,\n centerReadoutStyles,\n renderCenterReadouts,\n} from '../readout/center-readout.js';\nimport {ReadoutSize} from '../readout/readout.js';\nimport {\n computeZoomToFitArcFrame,\n normalizeArcAngle,\n shiftArcFrameToOuterEdge,\n} from '../../svghelpers/arc-frame.js';\nimport {\n linearTickInterval,\n watchfaceLinear,\n} from '../../building-blocks/instrument-linear/instrument-linear.js';\nimport type {\n LinearAdvice,\n LinearAdviceRaw,\n} from '../../building-blocks/instrument-linear/advice.js';\n\nexport enum ObcPitchRollHeaveType {\n /** Pitch on the right, roll at the bottom, heave in the left band slot. */\n singleScale = 'single-scale',\n /** Pitch and roll mirrored onto both sides, heave centred. */\n dualScale = 'dual-scale',\n}\n\nexport enum PitchRollHeavePriorityElement {\n pitch = 'pitch',\n roll = 'roll',\n heave = 'heave',\n}\n\n/** Half-side of the centre overlay viewBox in SVG units. */\nconst CENTRE_HALF = 200;\n\n/**\n * Minimum diagonal clearance, in central-layer pixels, between the zoomed\n * heave column and the adjacent roll band. Matches the constant\n * `obc-pitch-roll` uses between its own adjacent arcs.\n */\nconst CORNER_GAP_PX = 32;\n\n/** Numerical safety floor when an axis arc has to collapse for clearance. */\nconst MIN_ARC_HALF_DEG = 2;\n\n/** Width of the tick lane inside the heave column, in SVG units. */\nconst HEAVE_SCALE_WIDTH = 24;\n\n/** Band thickness at the natural, un-zoomed radii. */\nconst NOMINAL_BAND =\n OUTER_RING_RADIUS - innerRingRadiusFor(WatchCircleType.double);\n\n/**\n * Clearance kept between the centred (`dual-scale`) heave column's corners and\n * the surrounding band, in central-layer pixels. Sized so the un-zoomed\n * default is untouched — there the corner sits 13.2 units inside the free\n * radius — while the tighter zoomed layout is pulled back off the bands.\n */\nconst HEAVE_CENTRE_GAP_PX = 10;\n\n/**\n * The band slot the heave column fills, in central-layer coordinates.\n *\n * `outerR`/`innerR` bound the slot radially; `capRadius` is the radius of the\n * pitch arc's outer edge about its own origin, which is what the column's\n * height is measured against so the two line up. Un-zoomed the two radii\n * coincide; under zoom the arc is drawn on a shifted sub-watch and they differ.\n */\ninterface HeaveBand {\n outerR: number;\n innerR: number;\n capRadius: number;\n pitchDeg: number;\n}\n\n/**\n * Natural size of the heave column: as thick as the band slot, and tall enough\n * that its top and bottom edges sit level with the pitch arc's end caps.\n */\nfunction heaveColumnSize(band: HeaveBand): {width: number; height: number} {\n return {\n width: band.outerR - band.innerR,\n height: 2 * band.capRadius * Math.sin((band.pitchDeg * Math.PI) / 180),\n };\n}\n\n/**\n * Distance from a point to an axis-aligned rectangle; 0 when the point is\n * inside. Used to keep the zoomed roll band clear of the heave column, which\n * — unlike the arc-to-arc case — is a rectangle, so a corner may clear it on\n * one axis alone.\n */\nfunction distanceToRect(\n px: number,\n py: number,\n x0: number,\n y0: number,\n x1: number,\n y1: number\n): number {\n const dx = Math.max(0, x0 - px, px - x1);\n const dy = Math.max(0, y0 - py, py - y1);\n return Math.hypot(dx, dy);\n}\n\n/**\n * `<obc-pitch-roll-heave>` — Combined pitch, roll and heave indicator.\n *\n * Places a pitch arc, a roll arc and a linear heave column around one watch\n * face. The heave column occupies the same radial slot as the arcs, and its\n * height is derived from the pitch arc so its top and bottom edges sit level\n * with the pitch arc's end caps.\n *\n * Variants (`type`):\n * - `single-scale` (default) — pitch on the right, roll at the bottom, heave in\n * the left slot, vessel silhouettes in the centre.\n * - `dual-scale` — pitch and roll mirrored onto the opposite sides, with the\n * heave column moved to the centre.\n *\n * Set `hasReadout` to replace the centre content with stacked pitch, roll and\n * heave readouts, and `zoomToFitArc` to enlarge narrow arcs so they fill the\n * available space.\n *\n * @element obc-pitch-roll-heave\n * @experimental\n */\n@customElement('obc-pitch-roll-heave')\nexport class ObcPitchRollHeave extends LitElement {\n @property({type: String}) type: ObcPitchRollHeaveType =\n ObcPitchRollHeaveType.singleScale;\n\n @property({type: Number}) pitch = 0;\n @property({type: Number}) roll = 0;\n @property({type: Number}) heave = 0;\n @property({type: Number}) minAvgPitch = 0;\n @property({type: Number}) maxAvgPitch = 0;\n @property({type: Number}) minAvgRoll = 0;\n @property({type: Number}) maxAvgRoll = 0;\n @property({type: Number}) minTrendHeave = 0;\n @property({type: Number}) maxTrendHeave = 0;\n /** Half-extent of the heave scale in metres; the column spans `±heaveRange`. */\n @property({type: Number}) heaveRange = 10;\n\n /**\n * Half-extent of the pitch arc in degrees. Also drives the heave column\n * height, which is `2 · outerRadius · sin(pitchArcAngle)` so the column's\n * edges stay level with the pitch arc's end caps.\n */\n @property({type: Number}) pitchArcAngle = 30;\n /** Half-extent of the roll arc in degrees. */\n @property({type: Number}) rollArcAngle = 45;\n @property({type: Boolean}) zoomToFitArc = false;\n\n /**\n * Replaces the centre content with stacked pitch, roll and heave readouts.\n * Ignored when `type` is `dual-scale`, where the heave column occupies the\n * centre.\n * @availableWhen type==singleScale\n */\n @property({type: Boolean}) hasReadout = false;\n /** @availableWhen hasReadout==true */\n @property({type: String}) pitchLabel = 'Pitch';\n /** @availableWhen hasReadout==true */\n @property({type: String}) rollLabel = 'Roll';\n /** @availableWhen hasReadout==true */\n @property({type: String}) heaveLabel = 'Heave';\n /**\n * Unit shown in the pitch and roll readouts.\n * @availableWhen hasReadout==true\n */\n @property({type: String}) unit = 'DEG';\n /**\n * Unit shown in the heave readout.\n * @availableWhen hasReadout==true\n */\n @property({type: String}) heaveUnit = 'm';\n /** @availableWhen hasReadout==true */\n @property({type: Number}) fractionDigits = 0;\n\n /** @availableWhen type==singleScale && hasReadout==false */\n @property({type: String}) vesselImageFore: VesselImage = VesselImage.psvFore;\n /** @availableWhen type==singleScale && hasReadout==false */\n @property({type: String}) vesselImageSide: VesselImage = VesselImage.psvSide;\n /** @availableWhen type==singleScale && hasReadout==false */\n @property({type: Number}) scaleForeImage = 1;\n\n @property({type: Number}) maxPitchAdvice: number | undefined = undefined;\n @property({type: Number}) maxRollAdvice: number | undefined = undefined;\n /** @availableWhen maxPitchAdvice!=undefined */\n @property({type: Boolean}) triggerPitchAdvice = false;\n /** @availableWhen maxRollAdvice!=undefined */\n @property({type: Boolean}) triggerRollAdvice = false;\n @property({type: Array}) heaveAdvice: LinearAdvice[] = [];\n\n @property({type: String}) priority: Priority = Priority.regular;\n @property({type: Array, attribute: false})\n priorityElements: PitchRollHeavePriorityElement[] = [\n PitchRollHeavePriorityElement.pitch,\n PitchRollHeavePriorityElement.roll,\n PitchRollHeavePriorityElement.heave,\n ];\n\n private priorityFor(element: PitchRollHeavePriorityElement): Priority {\n const selected = Array.isArray(this.priorityElements)\n ? this.priorityElements\n : [];\n return selected.includes(element) ? this.priority : Priority.regular;\n }\n\n private needleColor(element: PitchRollHeavePriorityElement): string {\n return this.priorityFor(element) === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n\n private barColor(element: PitchRollHeavePriorityElement): string {\n return this.priorityFor(element) === Priority.enhanced\n ? 'var(--instrument-enhanced-tertiary-color)'\n : 'var(--instrument-regular-tertiary-color)';\n }\n\n private get normalizedScaleForeImage(): number {\n if (!Number.isFinite(this.scaleForeImage)) {\n return 1;\n }\n return Math.max(0, Math.min(2, this.scaleForeImage));\n }\n\n private get isDualScale(): boolean {\n return this.type === ObcPitchRollHeaveType.dualScale;\n }\n\n /** The centre readouts replace the vessels; never available in dual scale. */\n private get showsReadout(): boolean {\n return this.hasReadout && !this.isDualScale;\n }\n\n /**\n * Pitch half-extent, capped so a roll arc of the minimum size still fits in\n * the remaining quadrant.\n */\n private get requestedPitchArcAngle(): number {\n return Math.min(\n 90 - MIN_ARC_HALF_DEG,\n normalizeArcAngle(this.pitchArcAngle, 30)\n );\n }\n\n /**\n * Roll half-extent, clamped so the pitch and roll arcs cannot meet: the two\n * diagonal gaps each span `90 - pitch - roll` degrees, so the pair has to\n * stay under 90° combined.\n */\n private get requestedRollArcAngle(): number {\n const roll = normalizeArcAngle(this.rollArcAngle, 45);\n const headroom = 90 - this.requestedPitchArcAngle;\n return Math.max(MIN_ARC_HALF_DEG, Math.min(roll, headroom));\n }\n\n override render() {\n const pitchReq = this.requestedPitchArcAngle;\n const rollReq = this.requestedRollArcAngle;\n const overlayViewBox = `-${CENTRE_HALF} -${CENTRE_HALF} ${CENTRE_HALF * 2} ${CENTRE_HALF * 2}`;\n\n const layout = this.zoomToFitArc\n ? this.zoomLayout(pitchReq, rollReq)\n : undefined;\n const band: HeaveBand = layout?.band ?? {\n outerR: OUTER_RING_RADIUS,\n innerR: innerRingRadiusFor(WatchCircleType.double),\n capRadius: OUTER_RING_RADIUS,\n pitchDeg: pitchReq,\n };\n\n return html`\n <div class=\"container\">\n <svg viewBox=${overlayViewBox}>\n ${this.showsReadout ? nothing : this.renderCrosshair()}\n ${this.renderOverlayVessels()}\n ${this.zoomToFitArc || this.isDualScale\n ? nothing\n : this.renderComplement(pitchReq)}\n ${this.renderHeaveColumn(band)}\n </svg>\n ${layout\n ? this.renderZoomedArcs(layout)\n : this.renderFullWatch(pitchReq, rollReq)}\n ${this.showsReadout\n ? html`<div class=\"readout\">\n ${renderCenterReadouts(\n [\n {\n value: this.pitch,\n label: this.pitchLabel,\n unit: this.unit,\n fractionDigits: this.fractionDigits,\n size: ReadoutSize.large,\n priority: this.priorityFor(\n PitchRollHeavePriorityElement.pitch\n ),\n },\n {\n value: this.roll,\n label: this.rollLabel,\n unit: this.unit,\n fractionDigits: this.fractionDigits,\n size: ReadoutSize.large,\n priority: this.priorityFor(\n PitchRollHeavePriorityElement.roll\n ),\n },\n {\n value: this.heave,\n label: this.heaveLabel,\n unit: this.heaveUnit,\n fractionDigits: this.fractionDigits,\n size: ReadoutSize.large,\n priority: this.priorityFor(\n PitchRollHeavePriorityElement.heave\n ),\n },\n ],\n CenterReadoutArrangement.stacked\n )}\n </div>`\n : nothing}\n </div>\n `;\n }\n\n /**\n * Crosshair drawn on the overlay rather than through `obc-watch`'s own\n * `crosshairEnabled`: the design has the arc bands covering the arms, but\n * `obc-watch` renders its crosshair after the bands, i.e. on top of them.\n * Drawing it here puts it under the watch layer, so the bands and the heave\n * column mask it naturally.\n *\n * In `single-scale` nothing frames the segment above the vessel (the other\n * three arms end under the pitch band, roll band and heave column), so the\n * vertical arm stops at the centre instead of continuing upward. In\n * `dual-scale` the top roll band gives it a natural endpoint, so the full\n * arm is kept.\n */\n private renderCrosshair(): SVGTemplateResult {\n const r = OUTER_RING_RADIUS;\n const yTop = this.isDualScale ? -r : 0;\n return svg`\n <line\n x1=${-r} y1=\"0\" x2=${r} y2=\"0\"\n stroke=\"var(--instrument-frame-tertiary-color)\"\n vector-effect=\"non-scaling-stroke\"\n />\n <line\n x1=\"0\" y1=${yTop} x2=\"0\" y2=${r}\n stroke=\"var(--instrument-frame-tertiary-color)\"\n vector-effect=\"non-scaling-stroke\"\n />\n `;\n }\n\n /**\n * Vessel silhouettes on the centre layer. Only needed under zoom — the\n * un-zoomed path hands them to `obc-watch` via `vessels`, while the zoomed\n * sub-watches have no room for them.\n */\n private renderOverlayVessels(): SVGTemplateResult | typeof nothing {\n if (!this.zoomToFitArc || this.isDualScale || this.showsReadout) {\n return nothing;\n }\n const vesselScale = 224 / 160;\n return svg`\n <g style=\"transform: rotate(${this.pitch}deg) scale(${vesselScale}) translate(-80px, -80px);\">\n ${vesselImages[this.vesselImageSide]}\n </g>\n <g style=\"transform: rotate(${this.roll}deg) scale(${vesselScale * this.normalizedScaleForeImage}) translate(-80px, -80px);\">\n ${vesselImages[this.vesselImageFore]}\n </g>\n `;\n }\n\n /**\n * Thin ring bridging the empty span across the top, from where the heave\n * column's upper edge crosses the outer ring round to the pitch arc's start.\n * Because the column height is derived from the pitch arc, both ends land at\n * `±pitchArcAngle` off the vertical, making the ring symmetric. The two\n * diagonal gaps lower down are left open by design.\n */\n private renderComplement(pitchDeg: number): SVGTemplateResult {\n const r = OUTER_RING_RADIUS;\n const rad = (pitchDeg * Math.PI) / 180;\n // Ring runs clockwise from (270 + pitchDeg) through 0 to (90 - pitchDeg).\n const x1 = -r * Math.cos(rad);\n const y1 = -r * Math.sin(rad);\n const x2 = r * Math.cos(rad);\n const y2 = -r * Math.sin(rad);\n return svg`\n <path\n d=\"M ${x1} ${y1} A ${r} ${r} 0 0 1 ${x2} ${y2}\"\n fill=\"none\"\n stroke=\"var(--instrument-frame-tertiary-color)\"\n vector-effect=\"non-scaling-stroke\"\n />\n `;\n }\n\n /**\n * Linear heave scale, built from the same building block `obc-heave` uses.\n *\n * The column fills the band's radial slot, so its width equals the band\n * thickness and its height keeps its top and bottom edges level with the\n * pitch arc's end caps. In `single-scale` it sits in the left slot and is\n * mirrored so the tick lane faces outward; in `dual-scale` it moves to the\n * centre, unmirrored, and shrinks if the zoomed bands leave too little room.\n */\n private renderHeaveColumn(band: HeaveBand): SVGTemplateResult {\n const {width, height: naturalHeight} = heaveColumnSize(band);\n let height = naturalHeight;\n let offsetX = -(band.outerR + band.innerR) / 2;\n\n if (this.isDualScale) {\n offsetX = 0;\n // The centred column has to stay inside whatever the bands leave free.\n // Only the height gives way: the column's thickness reads as a match for\n // the band thickness, and shrinking both would break that.\n const free = band.innerR - HEAVE_CENTRE_GAP_PX;\n const halfWidth = width / 2;\n const maxHalfHeight =\n free > halfWidth ? Math.sqrt(free * free - halfWidth * halfWidth) : 0;\n height = Math.min(height, 2 * maxHalfHeight);\n }\n\n const scaleWidth = HEAVE_SCALE_WIDTH * Math.min(1, width / NOMINAL_BAND);\n\n const gauge = watchfaceLinear(\n {\n height,\n width,\n scaleWidth,\n minValue: -this.heaveRange,\n maxValue: this.heaveRange,\n },\n [{min: this.minTrendHeave, max: this.maxTrendHeave}],\n {value: this.heave},\n {container: 'var(--instrument-frame-primary-color)'},\n {\n hideContainer: false,\n off: false,\n priority: this.priorityFor(PitchRollHeavePriorityElement.heave),\n },\n {\n mainTickmarks: [],\n primaryTickmarkInterval: 0,\n secondaryTickmarkInterval: linearTickInterval(height, this.heaveRange),\n },\n this.heaveAdvices\n );\n\n const mirror = this.isDualScale ? '' : ' scale(-1, 1)';\n return svg`<g transform=\"translate(${offsetX}, 0)${mirror}\">${gauge}</g>`;\n }\n\n private get heaveAdvices(): LinearAdviceRaw[] {\n return this.heaveAdvice.map((advice) => {\n const isActive =\n this.maxTrendHeave >= advice.min && this.minTrendHeave <= advice.max;\n const state = isActive\n ? AdviceState.triggered\n : advice.hinted\n ? AdviceState.hinted\n : AdviceState.regular;\n return {...advice, state} satisfies LinearAdviceRaw;\n });\n }\n\n /**\n * Zoom-fit geometry, computed once per render and shared by the arc layer\n * and the heave column.\n *\n * Frames are built at the REQUESTED half-extents with the same math as\n * `obc-pitch` / `obc-roll`, so each sub-watch matches its standalone\n * equivalent. Two clearance passes then shorten only the *rendered* arcs —\n * the frames stay untouched, so band thickness, position and zoom level are\n * preserved:\n *\n * 1. pitch vs roll at the diagonal, ratio-preserving, exactly as\n * `obc-pitch-roll` does it;\n * 2. roll vs the heave column, `single-scale` only, shortening the roll arc\n * alone. Because the column's height follows the pitch arc, pass 1 already\n * pulls the column in whenever pitch shrinks, so pitch needs no second\n * pass.\n */\n private zoomLayout(pitchReq: number, rollReq: number) {\n const ext = 48;\n const targetSize = (176 + ext) * 2;\n const innerNat = innerRingRadiusFor(WatchCircleType.double);\n const buildFrame = (halfDeg: number) => {\n const areas: WatchArea[] = [\n {\n startAngle: -halfDeg,\n endAngle: halfDeg,\n roundOutsideCut: true,\n roundInsideCut: true,\n },\n ];\n const baseFrame = computeZoomToFitArcFrame({\n areas,\n outerRadius: OUTER_RING_RADIUS,\n innerRadius: innerNat,\n extension: ext,\n targetSize,\n });\n const subArcFrame = shiftArcFrameToOuterEdge(\n baseFrame,\n OUTER_RING_RADIUS + baseFrame.radiusOffset,\n OUTER_RING_RADIUS,\n CENTRE_HALF\n );\n const scale = (CENTRE_HALF * 2) / subArcFrame.width;\n const outerR = (OUTER_RING_RADIUS + baseFrame.radiusOffset) * scale;\n const innerR = (innerNat + baseFrame.radiusOffset) * scale;\n return {subArcFrame, outerR, innerR};\n };\n const pitchFrame = buildFrame(pitchReq);\n const rollFrame = buildFrame(rollReq);\n\n const OR = OUTER_RING_RADIUS;\n const toRad = (deg: number) => (deg * Math.PI) / 180;\n const signedDist = (\n px: number,\n py: number,\n qx: number,\n qy: number\n ): number => {\n const dx = qx - px;\n const dy = qy - py;\n const mag = Math.hypot(dx, dy);\n return dx > 0 && dy > 0 ? mag : -mag;\n };\n // Diagonal gap between two adjacent cardinal bands. All such gaps in this\n // layout are congruent, so one pair stands in for the rest.\n const minGap = (apRad: number, arRad: number): number => {\n const cosP = Math.cos(apRad);\n const sinP = Math.sin(apRad);\n const cosR = Math.cos(arRad);\n const sinR = Math.sin(arRad);\n const p1x = pitchFrame.innerR * sinP;\n const p1y = pitchFrame.outerR - OR - pitchFrame.innerR * cosP;\n const p2x = pitchFrame.outerR * sinP;\n const p2y = pitchFrame.outerR - OR - pitchFrame.outerR * cosP;\n const q1x = OR - rollFrame.outerR + rollFrame.innerR * cosR;\n const q1y = -rollFrame.innerR * sinR;\n const q2x = OR - rollFrame.outerR + rollFrame.outerR * cosR;\n const q2y = -rollFrame.outerR * sinR;\n return Math.min(\n signedDist(p1x, p1y, q1x, q1y),\n signedDist(p2x, p2y, q2x, q2y)\n );\n };\n\n let aP = toRad(pitchReq);\n let aR = toRad(rollReq);\n if (minGap(aP, aR) < CORNER_GAP_PX) {\n let lo = 0;\n let hi = 1;\n for (let i = 0; i < 40; i++) {\n const mid = (lo + hi) / 2;\n if (minGap(aP * mid, aR * mid) >= CORNER_GAP_PX) {\n lo = mid;\n } else {\n hi = mid;\n }\n }\n aP *= lo;\n aR *= lo;\n }\n const pitchClampedDeg = Math.max(MIN_ARC_HALF_DEG, (aP * 180) / Math.PI);\n let rollClampedDeg = Math.max(MIN_ARC_HALF_DEG, (aR * 180) / Math.PI);\n\n const bandFor = (pitchDeg: number): HeaveBand => ({\n outerR: OR,\n innerR: OR - (pitchFrame.outerR - pitchFrame.innerR),\n capRadius: pitchFrame.outerR,\n pitchDeg,\n });\n\n if (!this.isDualScale) {\n // Roll's left end caps versus the heave column rectangle. Shrinking the\n // roll arc moves both caps toward the bottom cardinal, away from the\n // column, so the gap grows monotonically as the scalar shrinks.\n const band = bandFor(pitchClampedDeg);\n const {width, height} = heaveColumnSize(band);\n const x1 = -band.innerR;\n const x0 = x1 - width;\n const y1 = height / 2;\n const heaveGap = (arRad: number): number => {\n const cosR = Math.cos(arRad);\n const sinR = Math.sin(arRad);\n const outerX = -rollFrame.outerR * sinR;\n const outerY = OR - rollFrame.outerR + rollFrame.outerR * cosR;\n const innerX = -rollFrame.innerR * sinR;\n const innerY = OR - rollFrame.outerR + rollFrame.innerR * cosR;\n return Math.min(\n distanceToRect(outerX, outerY, x0, -y1, x1, y1),\n distanceToRect(innerX, innerY, x0, -y1, x1, y1)\n );\n };\n if (heaveGap(toRad(rollClampedDeg)) < CORNER_GAP_PX) {\n let lo = 0;\n let hi = rollClampedDeg;\n for (let i = 0; i < 40; i++) {\n const mid = (lo + hi) / 2;\n if (heaveGap(toRad(mid)) >= CORNER_GAP_PX) {\n lo = mid;\n } else {\n hi = mid;\n }\n }\n rollClampedDeg = Math.max(MIN_ARC_HALF_DEG, lo);\n }\n }\n\n return {\n pitchFrame,\n rollFrame,\n pitchClampedDeg,\n rollClampedDeg,\n band: bandFor(pitchClampedDeg),\n };\n }\n\n /**\n * Zoomed-arc layer: CSS-rotated `<obc-watch>` instances, each holding a\n * single arc rendered at the watch's natural top and rotated onto its\n * cardinal. `single-scale` places pitch right and roll bottom; `dual-scale`\n * mirrors both. The heave column lives on the centre overlay.\n */\n private renderZoomedArcs(layout: ReturnType<typeof this.zoomLayout>) {\n const {pitchFrame, rollFrame, pitchClampedDeg, rollClampedDeg} = layout;\n\n const subAreas = (halfDeg: number): WatchArea[] => [\n {\n startAngle: -halfDeg,\n endAngle: halfDeg,\n roundOutsideCut: true,\n roundInsideCut: true,\n },\n ];\n\n // Clip each sub-watch to the sector its (possibly shortened) arc covers so\n // the indicator cannot leak past the visible band.\n const sectorClip = (\n halfDeg: number,\n frame: typeof rollFrame.subArcFrame\n ): string => {\n const oxPct = (-frame.x / frame.width) * 100;\n const oyPct = (-frame.y / frame.height) * 100;\n const dxPct = oyPct * Math.tan((halfDeg * Math.PI) / 180);\n const lx = Math.max(0, oxPct - dxPct);\n const rx = Math.min(100, oxPct + dxPct);\n return `polygon(${oxPct}% ${oyPct}%, ${lx}% 0%, ${rx}% 0%)`;\n };\n\n const axis = (\n element: PitchRollHeavePriorityElement,\n frame: typeof rollFrame,\n halfDeg: number,\n value: number,\n avgMin: number,\n avgMax: number,\n max: number | undefined,\n trigger: boolean,\n cap: number\n ) => ({\n arcFrame: frame.subArcFrame,\n areas: subAreas(halfDeg),\n barAreas: [\n {\n startAngle: avgMin,\n endAngle: avgMax,\n fillColor: this.barColor(element),\n },\n ],\n needles: [\n {\n angle: value,\n fillColor: this.needleColor(element),\n strokeColor: 'var(--border-silhouette-color)',\n },\n ],\n advices: this.subAdvices(halfDeg, max, trigger, cap),\n tickmarks: [\n {angle: 0, type: TickmarkType.main},\n ...arcTickmarks(0, halfDeg),\n ],\n clipPath: sectorClip(halfDeg, frame.subArcFrame),\n });\n\n const pitchAxis = axis(\n PitchRollHeavePriorityElement.pitch,\n pitchFrame,\n pitchClampedDeg,\n this.pitch,\n this.minAvgPitch,\n this.maxAvgPitch,\n this.maxPitchAdvice,\n this.triggerPitchAdvice,\n 30\n );\n const rollAxis = axis(\n PitchRollHeavePriorityElement.roll,\n rollFrame,\n rollClampedDeg,\n this.roll,\n this.minAvgRoll,\n this.maxAvgRoll,\n this.maxRollAdvice,\n this.triggerRollAdvice,\n 45\n );\n\n const subWatch = (rotation: number, a: typeof pitchAxis) => html`\n <obc-watch\n class=\"sub-watch\"\n style=\"transform: rotate(${rotation}deg); clip-path: ${a.clipPath};\"\n .watchCircleType=${WatchCircleType.double}\n .zoomToFitArc=${true}\n .arcFrame=${a.arcFrame}\n .areas=${a.areas}\n .barAreas=${a.barAreas}\n .needles=${a.needles}\n .vessels=${[]}\n .tickmarks=${a.tickmarks}\n .advices=${a.advices}\n ></obc-watch>\n `;\n\n return html`\n ${subWatch(90, pitchAxis)} ${subWatch(180, rollAxis)}\n ${this.isDualScale\n ? html`${subWatch(270, pitchAxis)} ${subWatch(0, rollAxis)}`\n : nothing}\n `;\n }\n\n /** Caution bands for one sub-watch axis, at sub-watch-local angles. */\n private subAdvices(\n halfDeg: number,\n max: number | undefined,\n trigger: boolean,\n cap: number\n ): AngleAdviceRaw[] {\n if (max === undefined) return [];\n const outer = Math.min(halfDeg, cap);\n const inner = Math.min(max, outer);\n const state = trigger ? AdviceState.triggered : AdviceState.regular;\n return [\n {\n minAngle: -outer,\n maxAngle: -inner,\n type: AdviceType.caution,\n state,\n hideMinTickmark: true,\n },\n {\n minAngle: inner,\n maxAngle: outer,\n type: AdviceType.caution,\n state,\n hideMaxTickmark: true,\n },\n ];\n }\n\n /** Areas, tickmarks, bars and needles for the un-zoomed single watch. */\n private renderFullWatch(pitchDeg: number, rollDeg: number) {\n const arc = (center: number, half: number): WatchArea => ({\n startAngle: center - half,\n endAngle: center + half,\n roundOutsideCut: true,\n roundInsideCut: true,\n });\n\n const areas: WatchArea[] = [arc(90, pitchDeg), arc(180, rollDeg)];\n const tickmarks: Tickmark[] = [\n {angle: 90, type: TickmarkType.main},\n {angle: 180, type: TickmarkType.main},\n ...arcTickmarks(90, pitchDeg),\n ...arcTickmarks(180, rollDeg),\n ];\n const barAreas = [\n {\n startAngle: 90 + this.minAvgPitch,\n endAngle: 90 + this.maxAvgPitch,\n fillColor: this.barColor(PitchRollHeavePriorityElement.pitch),\n },\n {\n startAngle: 180 + this.minAvgRoll,\n endAngle: 180 + this.maxAvgRoll,\n fillColor: this.barColor(PitchRollHeavePriorityElement.roll),\n },\n ];\n const needles = [\n {\n angle: 90 + this.pitch,\n fillColor: this.needleColor(PitchRollHeavePriorityElement.pitch),\n strokeColor: 'var(--border-silhouette-color)',\n },\n {\n angle: 180 + this.roll,\n fillColor: this.needleColor(PitchRollHeavePriorityElement.roll),\n strokeColor: 'var(--border-silhouette-color)',\n },\n ];\n\n if (this.isDualScale) {\n areas.push(arc(270, pitchDeg), arc(0, rollDeg));\n tickmarks.push(\n {angle: 270, type: TickmarkType.main},\n {angle: 0, type: TickmarkType.main},\n ...arcTickmarks(270, pitchDeg),\n ...arcTickmarks(0, rollDeg)\n );\n barAreas.push(\n {\n startAngle: 270 + this.minAvgPitch,\n endAngle: 270 + this.maxAvgPitch,\n fillColor: this.barColor(PitchRollHeavePriorityElement.pitch),\n },\n {\n startAngle: this.minAvgRoll,\n endAngle: this.maxAvgRoll,\n fillColor: this.barColor(PitchRollHeavePriorityElement.roll),\n }\n );\n needles.push(\n {\n angle: 270 + this.pitch,\n fillColor: this.needleColor(PitchRollHeavePriorityElement.pitch),\n strokeColor: 'var(--border-silhouette-color)',\n },\n {\n angle: this.roll,\n fillColor: this.needleColor(PitchRollHeavePriorityElement.roll),\n strokeColor: 'var(--border-silhouette-color)',\n }\n );\n }\n\n return html`\n <obc-watch\n .watchCircleType=${WatchCircleType.double}\n .zoomToFitArc=${false}\n .areas=${areas}\n .barAreas=${barAreas}\n .needles=${needles}\n .vessels=${this.isDualScale || this.showsReadout\n ? []\n : [\n {\n size: VesselImageSize.large,\n vesselImage: this.vesselImageSide,\n transform: `rotate(${this.pitch}deg)`,\n },\n {\n size: VesselImageSize.large,\n vesselImage: this.vesselImageFore,\n transform: `rotate(${this.roll}deg) scale(${this.normalizedScaleForeImage})`,\n },\n ]}\n .tickmarks=${tickmarks}\n .advices=${this.advices(pitchDeg, rollDeg)}\n ></obc-watch>\n `;\n }\n\n private advices(pitchDeg: number, rollDeg: number): AngleAdviceRaw[] {\n const advices: AngleAdviceRaw[] = [];\n const push = (\n center: number,\n halfDeg: number,\n max: number | undefined,\n trigger: boolean,\n cap: number\n ) => {\n if (max === undefined) return;\n const outer = Math.min(halfDeg, cap);\n const inner = Math.min(max, outer);\n const state = trigger ? AdviceState.triggered : AdviceState.regular;\n advices.push({\n minAngle: center - outer,\n maxAngle: center - inner,\n type: AdviceType.caution,\n state,\n hideMinTickmark: true,\n });\n advices.push({\n minAngle: center + inner,\n maxAngle: center + outer,\n type: AdviceType.caution,\n state,\n hideMaxTickmark: true,\n });\n };\n push(90, pitchDeg, this.maxPitchAdvice, this.triggerPitchAdvice, 30);\n push(180, rollDeg, this.maxRollAdvice, this.triggerRollAdvice, 45);\n if (this.isDualScale) {\n push(270, pitchDeg, this.maxPitchAdvice, this.triggerPitchAdvice, 30);\n push(0, rollDeg, this.maxRollAdvice, this.triggerRollAdvice, 45);\n }\n return advices;\n }\n\n static override styles = [\n centerReadoutStyles,\n css`\n * {\n box-sizing: border-box;\n }\n\n .container {\n position: relative;\n width: 100%;\n height: 100%;\n }\n\n .container > * {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n }\n\n .readout {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n `,\n ];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-pitch-roll-heave': ObcPitchRollHeave;\n }\n}\n"],"names":["ObcPitchRollHeaveType","PitchRollHeavePriorityElement"],"mappings":"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"}
|
|
@@ -23,7 +23,8 @@ export { RotType, RotPosition };
|
|
|
23
23
|
* - **Track bar** (`hasTrackBar`): A bar in the ring band growing from the
|
|
24
24
|
* twelve o'clock position to the measured rate of turn, with a needle
|
|
25
25
|
* marker at its end and sector tickmarks (pairs with
|
|
26
|
-
* `watchCircleType="double"` for the banded face
|
|
26
|
+
* `watchCircleType="double"` for the banded face, or `"triple"` when the
|
|
27
|
+
* ROT dots sit on the inner circle).
|
|
27
28
|
* - **Center readout** (`hasReadout`): A centered readout showing the
|
|
28
29
|
* measured rate of turn (label `ROT`, unit `DEG/min` by default).
|
|
29
30
|
* - **Color priority**: Uses `priority` to select regular or enhanced color
|
|
@@ -74,7 +75,9 @@ export declare class ObcRateOfTurn extends LitElement {
|
|
|
74
75
|
* When `true`, shows a bar in the ring band from the twelve o'clock
|
|
75
76
|
* position to the measured rate of turn, with a needle marker at its end
|
|
76
77
|
* and sector tickmarks. Pairs with `watchCircleType="double"` for the
|
|
77
|
-
* banded face
|
|
78
|
+
* banded face — or `"triple"` when `rotPosition` is `innerCircle`, so the
|
|
79
|
+
* dots get their inner track too. Driven by `rateOfTurnDegreesPerMinute`
|
|
80
|
+
* only.
|
|
78
81
|
*/
|
|
79
82
|
hasTrackBar: boolean;
|
|
80
83
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-of-turn.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/rate-of-turn/rate-of-turn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAgC,MAAM,KAAK,CAAC;AAE9D,OAAO,mBAAmB,CAAC;AAC3B,OAAO,EAAC,eAAe,EAAE,OAAO,EAAE,WAAW,EAAC,MAAM,mBAAmB,CAAC;AAUxE,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AAErC,OAAO,EAAC,OAAO,EAAE,WAAW,EAAC,CAAC;AAE9B
|
|
1
|
+
{"version":3,"file":"rate-of-turn.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/rate-of-turn/rate-of-turn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAgC,MAAM,KAAK,CAAC;AAE9D,OAAO,mBAAmB,CAAC;AAC3B,OAAO,EAAC,eAAe,EAAE,OAAO,EAAE,WAAW,EAAC,MAAM,mBAAmB,CAAC;AAUxE,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AAErC,OAAO,EAAC,OAAO,EAAE,WAAW,EAAC,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,qBACa,aAAc,SAAQ,UAAU;IAC3C;;;OAGG;IACuB,0BAA0B,EAAE,MAAM,GAAG,SAAS,CAAC;IAEzE;;;OAGG;IACuB,qBAAqB,EAAE,MAAM,CAAM;IAE7D;;;;OAIG;IACuB,kBAAkB,EAAE,MAAM,CAAK;IAE/B,OAAO,EAAE,OAAO,CAAgB;IAChC,WAAW,EAAE,WAAW,CAAqB;IAC7C,QAAQ,EAAE,QAAQ,CAAoB;IACtC,aAAa,EAAE,MAAM,CAAK;IAC1B,WAAW,EAAE,MAAM,CAAM;IACzB,eAAe,EAAE,eAAe,CACjC;IACE,gBAAgB,EAAE,OAAO,CAAS;IACnC,iBAAiB,EAAE,MAAM,CAAyB;IAC5E;;;;;;;OAOG;IACwB,WAAW,EAAE,OAAO,CAAS;IACxD;;;;;OAKG;IACuB,WAAW,EAAE,MAAM,CAAM;IACnD;;;OAGG;IACuB,YAAY,EAAE,MAAM,CAAM;IACpD;;;OAGG;IACwB,UAAU,EAAE,OAAO,CAAS;IACvD;;;OAGG;IACuB,KAAK,SAAS;IACxC;;;OAGG;IACuB,IAAI,SAAa;IAC3C;;;OAGG;IACuB,cAAc,SAAK;IAE7C,OAAO,KAAK,aAAa,GAKxB;IAED,OAAO,KAAK,aAAa,GAaxB;IAED,OAAO,KAAK,gBAAgB,GAc3B;IAED,OAAO,KAAK,cAAc,GAOzB;IAED,OAAgB,MAAM,4BA6BpB;IAEO,MAAM;CAoDhB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,kBAAkB,EAAE,aAAa,CAAC;KACnC;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-of-turn.js","sources":["../../../src/navigation-instruments/rate-of-turn/rate-of-turn.ts"],"sourcesContent":["import {LitElement, css, html, nothing, unsafeCSS} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport '../watch/watch.js';\nimport {WatchCircleType, RotType, RotPosition} from '../watch/watch.js';\nimport {Tickmark, TickmarkType} from '../watch/tickmark.js';\nimport {\n centerReadoutStyles,\n renderCenterReadouts,\n} from '../readout/center-readout.js';\nimport {ReadoutSize} from '../readout/readout.js';\nimport instrumentReadoutStyle from '../readout/instrument-readout.css?inline';\nimport {ROT_ZERO_DEADBAND_DEG} from './rot-renderer.js';\nimport {customElement} from '../../decorator.js';\nimport {Priority} from '../types.js';\n\nexport {RotType, RotPosition};\n\n/**\n * `<obc-rate-of-turn>` — Standalone rate-of-turn indicator rendered on a circular watch face.\n *\n * Wraps `<obc-watch>` to display a spinning-dot or arc-bar ROT visualization\n * without any additional instrument overlays. Useful for isolating the ROT\n * indicator in layouts where heading/compass elements are handled separately.\n *\n * ## Features\n *\n * - **Dot mode** (`rotType=\"dots\"`): Five evenly-spaced dots spin at the\n * resolved rotations-per-minute (derived from\n * `rateOfTurnDegreesPerMinute × rotDotAnimationFactor / 360`).\n * - **Bar mode** (`rotType=\"bar\"`): A banana-shaped arc from `barStartAngle`\n * to `barEndAngle` with clipped spinning dots inside.\n * - **Track position**: Place the indicator on the outer scale ring\n * (`rotPosition=\"scale\"`) or the inner circle\n * (`rotPosition=\"innerCircle\"`).\n * - **Track bar** (`hasTrackBar`): A bar in the ring band growing from the\n * twelve o'clock position to the measured rate of turn, with a needle\n * marker at its end and sector tickmarks (pairs with\n * `watchCircleType=\"double\"` for the banded face).\n * - **Center readout** (`hasReadout`): A centered readout showing the\n * measured rate of turn (label `ROT`, unit `DEG/min` by default).\n * - **Color priority**: Uses `priority` to select regular or enhanced color\n * palette; `rotPortStarboard` colors the track bar and needle by turn\n * direction.\n *\n * ## Usage Guidelines\n *\n * - Set `rateOfTurnDegreesPerMinute` to the current sensor value in degrees\n * per minute (the maritime/AIS convention). Sign controls direction\n * (positive = starboard / clockwise).\n * - Tune `rotDotAnimationFactor` to amplify the dot animation independently\n * of the physical value (default `18` ≈ 1 rpm at 20°/min).\n * - In bar mode, `barStartAngle` and `barEndAngle` define the static arc\n * span (0° = 12 o'clock, clockwise).\n * - Change `watchCircleType` to match the surrounding instrument ring style\n * (e.g. `triple` for compass contexts).\n *\n * @element obc-rate-of-turn\n * @stable\n */\n@customElement('obc-rate-of-turn')\nexport class ObcRateOfTurn extends LitElement {\n /**\n * Measured rate of turn in degrees per minute (positive = starboard).\n * When `undefined`, the legacy `rotationsPerMinute` value is used.\n */\n @property({type: Number}) rateOfTurnDegreesPerMinute: number | undefined;\n\n /**\n * Visual amplification applied to the spinning dot animation. Default `18`\n * keeps the legacy visual feel (≈1 rpm at 20°/min).\n */\n @property({type: Number}) rotDotAnimationFactor: number = 18;\n\n /**\n * @deprecated Use `rateOfTurnDegreesPerMinute` (and optionally\n * `rotDotAnimationFactor`) instead. Takes effect only when\n * `rateOfTurnDegreesPerMinute` is `undefined`.\n */\n @property({type: Number}) rotationsPerMinute: number = 1;\n\n @property({type: String}) rotType: RotType = RotType.dots;\n @property({type: String}) rotPosition: RotPosition = RotPosition.scale;\n @property({type: String}) priority: Priority = Priority.regular;\n @property({type: Number}) barStartAngle: number = 0;\n @property({type: Number}) barEndAngle: number = 30;\n @property({type: String}) watchCircleType: WatchCircleType =\n WatchCircleType.single;\n @property({type: Boolean}) rotPortStarboard: boolean = false;\n @property({type: Number}) rotAtZeroDeadband: number = ROT_ZERO_DEADBAND_DEG;\n /**\n * When `true`, shows a bar in the ring band from the twelve o'clock\n * position to the measured rate of turn, with a needle marker at its end\n * and sector tickmarks. Pairs with `watchCircleType=\"double\"` for the\n * banded face. Driven by `rateOfTurnDegreesPerMinute` only.\n */\n @property({type: Boolean}) hasTrackBar: boolean = false;\n /**\n * Bar-extent reference value in **degrees per minute**: the track bar\n * reaches ±`rotArcExtent` when the measured ROT equals ±`rotMaxValue`.\n * Default `60` aligns with ES-TRIN 2025/1 Art. 3.02.\n * @availableWhen hasTrackBar==true\n */\n @property({type: Number}) rotMaxValue: number = 60;\n /**\n * Arc extent of the track bar in degrees per direction. Default `60`.\n * @availableWhen hasTrackBar==true\n */\n @property({type: Number}) rotArcExtent: number = 60;\n /**\n * When `true`, shows a centered `<obc-readout>` with the measured rate of\n * turn. Shows a dash while `rateOfTurnDegreesPerMinute` is unset.\n */\n @property({type: Boolean}) hasReadout: boolean = false;\n /**\n * Readout label. Default `ROT`.\n * @availableWhen hasReadout==true\n */\n @property({type: String}) label = 'ROT';\n /**\n * Readout unit. Default `DEG/min`.\n * @availableWhen hasReadout==true\n */\n @property({type: String}) unit = 'DEG/min';\n /**\n * Number of fraction digits shown in the readout. Default `0`.\n * @availableWhen hasReadout==true\n */\n @property({type: Number}) fractionDigits = 0;\n\n private get trackBarAngle(): number {\n const max = this.rotMaxValue || 1;\n const rot = this.rateOfTurnDegreesPerMinute ?? 0;\n const ratio = Math.max(-1, Math.min(1, rot / max));\n return ratio * this.rotArcExtent;\n }\n\n private get trackBarColor(): string {\n if (this.rotPortStarboard) {\n const rot = this.rateOfTurnDegreesPerMinute ?? 0;\n if (rot > 0) {\n return 'var(--instrument-starboard-secondary-color)';\n }\n if (rot < 0) {\n return 'var(--instrument-port-secondary-color)';\n }\n }\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-tertiary-color)'\n : 'var(--instrument-regular-tertiary-color)';\n }\n\n private get trackNeedleColor(): string {\n if (this.rotPortStarboard) {\n const rot = this.rateOfTurnDegreesPerMinute ?? 0;\n if (rot > 0) {\n return 'var(--instrument-starboard-primary-color)';\n }\n if (rot < 0) {\n return 'var(--instrument-port-primary-color)';\n }\n return 'var(--instrument-regular-secondary-color)';\n }\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n\n private get trackTickmarks(): Tickmark[] {\n const ticks: Tickmark[] = [{angle: 0, type: TickmarkType.main}];\n for (let angle = 30; angle <= this.rotArcExtent; angle += 30) {\n ticks.push({angle, type: TickmarkType.primary});\n ticks.push({angle: -angle, type: TickmarkType.primary});\n }\n return ticks;\n }\n\n static override styles = [\n unsafeCSS(instrumentReadoutStyle),\n centerReadoutStyles,\n css`\n * {\n box-sizing: border-box;\n }\n\n .container {\n position: relative;\n width: 100%;\n height: 100%;\n }\n\n .container > * {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n }\n\n .center-readout-overlay {\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n }\n `,\n ];\n\n override render() {\n return html`<div class=\"container\">\n <obc-watch\n .watchCircleType=${this.watchCircleType}\n .priority=${this.priority}\n .tickmarks=${this.hasTrackBar ? this.trackTickmarks : []}\n .barAreas=${this.hasTrackBar\n ? [\n {\n startAngle: 0,\n endAngle: this.trackBarAngle,\n fillColor: this.trackBarColor,\n },\n ]\n : []}\n .needles=${this.hasTrackBar\n ? [\n {\n angle: this.trackBarAngle,\n fillColor: this.trackNeedleColor,\n strokeColor: 'var(--border-silhouette-color)',\n },\n ]\n : []}\n .rotType=${this.rotType}\n .rotPosition=${this.rotPosition}\n .rotStartAngle=${this.barStartAngle}\n .rotEndAngle=${this.barEndAngle}\n .rateOfTurnDegreesPerMinute=${this.rateOfTurnDegreesPerMinute}\n .rotDotAnimationFactor=${this.rotDotAnimationFactor}\n .rotationsPerMinute=${this.rotationsPerMinute}\n .rotPortStarboard=${this.rotPortStarboard}\n .rotAtZeroDeadband=${this.rotAtZeroDeadband}\n ></obc-watch>\n ${this.hasReadout\n ? html`<div class=\"center-readout-overlay\">\n ${renderCenterReadouts([\n {\n value: this.rateOfTurnDegreesPerMinute ?? null,\n label: this.label,\n unit: this.unit,\n fractionDigits: this.fractionDigits,\n size: ReadoutSize.large,\n priority: this.priority,\n centerValue: true,\n centerMeta: true,\n },\n ])}\n </div>`\n : nothing}\n </div>`;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-rate-of-turn': ObcRateOfTurn;\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AA4DO,IAAM,gBAAN,cAA4B,WAAW;AAAA,EAAvC,cAAA;AAAA,UAAA,GAAA,SAAA;AAWqB,SAAA,wBAAgC;AAOhC,SAAA,qBAA6B;AAE7B,SAAA,UAAmB,QAAQ;AAC3B,SAAA,cAA2B,YAAY;AACvC,SAAA,WAAqB,SAAS;AAC9B,SAAA,gBAAwB;AACxB,SAAA,cAAsB;AACtB,SAAA,kBACxB,gBAAgB;AACS,SAAA,mBAA4B;AAC7B,SAAA,oBAA4B;AAO3B,SAAA,cAAuB;AAOxB,SAAA,cAAsB;AAKtB,SAAA,eAAuB;AAKtB,SAAA,aAAsB;AAKvB,SAAA,QAAQ;AAKR,SAAA,OAAO;AAKP,SAAA,iBAAiB;AAAA,EAAA;AAAA,EAE3C,IAAY,gBAAwB;AAClC,UAAM,MAAM,KAAK,eAAe;AAChC,UAAM,MAAM,KAAK,8BAA8B;AAC/C,UAAM,QAAQ,KAAK,IAAI,IAAI,KAAK,IAAI,GAAG,MAAM,GAAG,CAAC;AACjD,WAAO,QAAQ,KAAK;AAAA,EACtB;AAAA,EAEA,IAAY,gBAAwB;AAClC,QAAI,KAAK,kBAAkB;AACzB,YAAM,MAAM,KAAK,8BAA8B;AAC/C,UAAI,MAAM,GAAG;AACX,eAAO;AAAA,MACT;AACA,UAAI,MAAM,GAAG;AACX,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO,KAAK,aAAa,SAAS,WAC9B,8CACA;AAAA,EACN;AAAA,EAEA,IAAY,mBAA2B;AACrC,QAAI,KAAK,kBAAkB;AACzB,YAAM,MAAM,KAAK,8BAA8B;AAC/C,UAAI,MAAM,GAAG;AACX,eAAO;AAAA,MACT;AACA,UAAI,MAAM,GAAG;AACX,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AACA,WAAO,KAAK,aAAa,SAAS,WAC9B,+CACA;AAAA,EACN;AAAA,EAEA,IAAY,iBAA6B;AACvC,UAAM,QAAoB,CAAC,EAAC,OAAO,GAAG,MAAM,aAAa,MAAK;AAC9D,aAAS,QAAQ,IAAI,SAAS,KAAK,cAAc,SAAS,IAAI;AAC5D,YAAM,KAAK,EAAC,OAAO,MAAM,aAAa,SAAQ;AAC9C,YAAM,KAAK,EAAC,OAAO,CAAC,OAAO,MAAM,aAAa,SAAQ;AAAA,IACxD;AACA,WAAO;AAAA,EACT;AAAA,EAiCS,SAAS;AAChB,WAAO;AAAA;AAAA,2BAEgB,KAAK,eAAe;AAAA,oBAC3B,KAAK,QAAQ;AAAA,qBACZ,KAAK,cAAc,KAAK,iBAAiB,CAAA,CAAE;AAAA,oBAC5C,KAAK,cACb;AAAA,MACE;AAAA,QACE,YAAY;AAAA,QACZ,UAAU,KAAK;AAAA,QACf,WAAW,KAAK;AAAA,MAAA;AAAA,IAClB,IAEF,CAAA,CAAE;AAAA,mBACK,KAAK,cACZ;AAAA,MACE;AAAA,QACE,OAAO,KAAK;AAAA,QACZ,WAAW,KAAK;AAAA,QAChB,aAAa;AAAA,MAAA;AAAA,IACf,IAEF,CAAA,CAAE;AAAA,mBACK,KAAK,OAAO;AAAA,uBACR,KAAK,WAAW;AAAA,yBACd,KAAK,aAAa;AAAA,uBACpB,KAAK,WAAW;AAAA,sCACD,KAAK,0BAA0B;AAAA,iCACpC,KAAK,qBAAqB;AAAA,8BAC7B,KAAK,kBAAkB;AAAA,4BACzB,KAAK,gBAAgB;AAAA,6BACpB,KAAK,iBAAiB;AAAA;AAAA,QAE3C,KAAK,aACH;AAAA,cACI,qBAAqB;AAAA,MACrB;AAAA,QACE,OAAO,KAAK,8BAA8B;AAAA,QAC1C,OAAO,KAAK;AAAA,QACZ,MAAM,KAAK;AAAA,QACX,gBAAgB,KAAK;AAAA,QACrB,MAAM,YAAY;AAAA,QAClB,UAAU,KAAK;AAAA,QACf,aAAa;AAAA,QACb,YAAY;AAAA,MAAA;AAAA,IACd,CACD,CAAC;AAAA,oBAEJ,OAAO;AAAA;AAAA,EAEf;AACF;AAvMa,cAoHK,SAAS;AAAA,EACvB,UAAU,sBAAsB;AAAA,EAChC;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA0BF;AA5I0B,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GALb,cAKe,WAAA,8BAAA,CAAA;AAMA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAXb,cAWe,WAAA,yBAAA,CAAA;AAOA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAlBb,cAkBe,WAAA,sBAAA,CAAA;AAEA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GApBb,cAoBe,WAAA,WAAA,CAAA;AACA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GArBb,cAqBe,WAAA,eAAA,CAAA;AACA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAtBb,cAsBe,WAAA,YAAA,CAAA;AACA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAvBb,cAuBe,WAAA,iBAAA,CAAA;AACA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAxBb,cAwBe,WAAA,eAAA,CAAA;AACA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAzBb,cAyBe,WAAA,mBAAA,CAAA;AAEC,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GA3Bd,cA2BgB,WAAA,oBAAA,CAAA;AACD,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GA5Bb,cA4Be,WAAA,qBAAA,CAAA;AAOC,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GAnCd,cAmCgB,WAAA,eAAA,CAAA;AAOD,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GA1Cb,cA0Ce,WAAA,eAAA,CAAA;AAKA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GA/Cb,cA+Ce,WAAA,gBAAA,CAAA;AAKC,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GApDd,cAoDgB,WAAA,cAAA,CAAA;AAKD,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAzDb,cAyDe,WAAA,SAAA,CAAA;AAKA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GA9Db,cA8De,WAAA,QAAA,CAAA;AAKA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAnEb,cAmEe,WAAA,kBAAA,CAAA;AAnEf,gBAAN,gBAAA;AAAA,EADN,cAAc,kBAAkB;AAAA,GACpB,aAAA;"}
|
|
1
|
+
{"version":3,"file":"rate-of-turn.js","sources":["../../../src/navigation-instruments/rate-of-turn/rate-of-turn.ts"],"sourcesContent":["import {LitElement, css, html, nothing, unsafeCSS} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport '../watch/watch.js';\nimport {WatchCircleType, RotType, RotPosition} from '../watch/watch.js';\nimport {Tickmark, TickmarkType} from '../watch/tickmark.js';\nimport {\n centerReadoutStyles,\n renderCenterReadouts,\n} from '../readout/center-readout.js';\nimport {ReadoutSize} from '../readout/readout.js';\nimport instrumentReadoutStyle from '../readout/instrument-readout.css?inline';\nimport {ROT_ZERO_DEADBAND_DEG} from './rot-renderer.js';\nimport {customElement} from '../../decorator.js';\nimport {Priority} from '../types.js';\n\nexport {RotType, RotPosition};\n\n/**\n * `<obc-rate-of-turn>` — Standalone rate-of-turn indicator rendered on a circular watch face.\n *\n * Wraps `<obc-watch>` to display a spinning-dot or arc-bar ROT visualization\n * without any additional instrument overlays. Useful for isolating the ROT\n * indicator in layouts where heading/compass elements are handled separately.\n *\n * ## Features\n *\n * - **Dot mode** (`rotType=\"dots\"`): Five evenly-spaced dots spin at the\n * resolved rotations-per-minute (derived from\n * `rateOfTurnDegreesPerMinute × rotDotAnimationFactor / 360`).\n * - **Bar mode** (`rotType=\"bar\"`): A banana-shaped arc from `barStartAngle`\n * to `barEndAngle` with clipped spinning dots inside.\n * - **Track position**: Place the indicator on the outer scale ring\n * (`rotPosition=\"scale\"`) or the inner circle\n * (`rotPosition=\"innerCircle\"`).\n * - **Track bar** (`hasTrackBar`): A bar in the ring band growing from the\n * twelve o'clock position to the measured rate of turn, with a needle\n * marker at its end and sector tickmarks (pairs with\n * `watchCircleType=\"double\"` for the banded face, or `\"triple\"` when the\n * ROT dots sit on the inner circle).\n * - **Center readout** (`hasReadout`): A centered readout showing the\n * measured rate of turn (label `ROT`, unit `DEG/min` by default).\n * - **Color priority**: Uses `priority` to select regular or enhanced color\n * palette; `rotPortStarboard` colors the track bar and needle by turn\n * direction.\n *\n * ## Usage Guidelines\n *\n * - Set `rateOfTurnDegreesPerMinute` to the current sensor value in degrees\n * per minute (the maritime/AIS convention). Sign controls direction\n * (positive = starboard / clockwise).\n * - Tune `rotDotAnimationFactor` to amplify the dot animation independently\n * of the physical value (default `18` ≈ 1 rpm at 20°/min).\n * - In bar mode, `barStartAngle` and `barEndAngle` define the static arc\n * span (0° = 12 o'clock, clockwise).\n * - Change `watchCircleType` to match the surrounding instrument ring style\n * (e.g. `triple` for compass contexts).\n *\n * @element obc-rate-of-turn\n * @stable\n */\n@customElement('obc-rate-of-turn')\nexport class ObcRateOfTurn extends LitElement {\n /**\n * Measured rate of turn in degrees per minute (positive = starboard).\n * When `undefined`, the legacy `rotationsPerMinute` value is used.\n */\n @property({type: Number}) rateOfTurnDegreesPerMinute: number | undefined;\n\n /**\n * Visual amplification applied to the spinning dot animation. Default `18`\n * keeps the legacy visual feel (≈1 rpm at 20°/min).\n */\n @property({type: Number}) rotDotAnimationFactor: number = 18;\n\n /**\n * @deprecated Use `rateOfTurnDegreesPerMinute` (and optionally\n * `rotDotAnimationFactor`) instead. Takes effect only when\n * `rateOfTurnDegreesPerMinute` is `undefined`.\n */\n @property({type: Number}) rotationsPerMinute: number = 1;\n\n @property({type: String}) rotType: RotType = RotType.dots;\n @property({type: String}) rotPosition: RotPosition = RotPosition.scale;\n @property({type: String}) priority: Priority = Priority.regular;\n @property({type: Number}) barStartAngle: number = 0;\n @property({type: Number}) barEndAngle: number = 30;\n @property({type: String}) watchCircleType: WatchCircleType =\n WatchCircleType.single;\n @property({type: Boolean}) rotPortStarboard: boolean = false;\n @property({type: Number}) rotAtZeroDeadband: number = ROT_ZERO_DEADBAND_DEG;\n /**\n * When `true`, shows a bar in the ring band from the twelve o'clock\n * position to the measured rate of turn, with a needle marker at its end\n * and sector tickmarks. Pairs with `watchCircleType=\"double\"` for the\n * banded face — or `\"triple\"` when `rotPosition` is `innerCircle`, so the\n * dots get their inner track too. Driven by `rateOfTurnDegreesPerMinute`\n * only.\n */\n @property({type: Boolean}) hasTrackBar: boolean = false;\n /**\n * Bar-extent reference value in **degrees per minute**: the track bar\n * reaches ±`rotArcExtent` when the measured ROT equals ±`rotMaxValue`.\n * Default `60` aligns with ES-TRIN 2025/1 Art. 3.02.\n * @availableWhen hasTrackBar==true\n */\n @property({type: Number}) rotMaxValue: number = 60;\n /**\n * Arc extent of the track bar in degrees per direction. Default `60`.\n * @availableWhen hasTrackBar==true\n */\n @property({type: Number}) rotArcExtent: number = 60;\n /**\n * When `true`, shows a centered `<obc-readout>` with the measured rate of\n * turn. Shows a dash while `rateOfTurnDegreesPerMinute` is unset.\n */\n @property({type: Boolean}) hasReadout: boolean = false;\n /**\n * Readout label. Default `ROT`.\n * @availableWhen hasReadout==true\n */\n @property({type: String}) label = 'ROT';\n /**\n * Readout unit. Default `DEG/min`.\n * @availableWhen hasReadout==true\n */\n @property({type: String}) unit = 'DEG/min';\n /**\n * Number of fraction digits shown in the readout. Default `0`.\n * @availableWhen hasReadout==true\n */\n @property({type: Number}) fractionDigits = 0;\n\n private get trackBarAngle(): number {\n const max = this.rotMaxValue || 1;\n const rot = this.rateOfTurnDegreesPerMinute ?? 0;\n const ratio = Math.max(-1, Math.min(1, rot / max));\n return ratio * this.rotArcExtent;\n }\n\n private get trackBarColor(): string {\n if (this.rotPortStarboard) {\n const rot = this.rateOfTurnDegreesPerMinute ?? 0;\n if (rot > 0) {\n return 'var(--instrument-starboard-secondary-color)';\n }\n if (rot < 0) {\n return 'var(--instrument-port-secondary-color)';\n }\n }\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-tertiary-color)'\n : 'var(--instrument-regular-tertiary-color)';\n }\n\n private get trackNeedleColor(): string {\n if (this.rotPortStarboard) {\n const rot = this.rateOfTurnDegreesPerMinute ?? 0;\n if (rot > 0) {\n return 'var(--instrument-starboard-primary-color)';\n }\n if (rot < 0) {\n return 'var(--instrument-port-primary-color)';\n }\n return 'var(--instrument-regular-secondary-color)';\n }\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n\n private get trackTickmarks(): Tickmark[] {\n const ticks: Tickmark[] = [{angle: 0, type: TickmarkType.main}];\n for (let angle = 30; angle <= this.rotArcExtent; angle += 30) {\n ticks.push({angle, type: TickmarkType.primary});\n ticks.push({angle: -angle, type: TickmarkType.primary});\n }\n return ticks;\n }\n\n static override styles = [\n unsafeCSS(instrumentReadoutStyle),\n centerReadoutStyles,\n css`\n * {\n box-sizing: border-box;\n }\n\n .container {\n position: relative;\n width: 100%;\n height: 100%;\n }\n\n .container > * {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n }\n\n .center-readout-overlay {\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n }\n `,\n ];\n\n override render() {\n return html`<div class=\"container\">\n <obc-watch\n .watchCircleType=${this.watchCircleType}\n .priority=${this.priority}\n .tickmarks=${this.hasTrackBar ? this.trackTickmarks : []}\n .barAreas=${this.hasTrackBar\n ? [\n {\n startAngle: 0,\n endAngle: this.trackBarAngle,\n fillColor: this.trackBarColor,\n },\n ]\n : []}\n .needles=${this.hasTrackBar\n ? [\n {\n angle: this.trackBarAngle,\n fillColor: this.trackNeedleColor,\n strokeColor: 'var(--border-silhouette-color)',\n },\n ]\n : []}\n .rotType=${this.rotType}\n .rotPosition=${this.rotPosition}\n .rotStartAngle=${this.barStartAngle}\n .rotEndAngle=${this.barEndAngle}\n .rateOfTurnDegreesPerMinute=${this.rateOfTurnDegreesPerMinute}\n .rotDotAnimationFactor=${this.rotDotAnimationFactor}\n .rotationsPerMinute=${this.rotationsPerMinute}\n .rotPortStarboard=${this.rotPortStarboard}\n .rotAtZeroDeadband=${this.rotAtZeroDeadband}\n ></obc-watch>\n ${this.hasReadout\n ? html`<div class=\"center-readout-overlay\">\n ${renderCenterReadouts([\n {\n value: this.rateOfTurnDegreesPerMinute ?? null,\n label: this.label,\n unit: this.unit,\n fractionDigits: this.fractionDigits,\n size: ReadoutSize.large,\n priority: this.priority,\n centerValue: true,\n centerMeta: true,\n },\n ])}\n </div>`\n : nothing}\n </div>`;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-rate-of-turn': ObcRateOfTurn;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,37 @@ export type ReadoutNumericFormatOptions = {
|
|
|
3
3
|
minValueLength: number;
|
|
4
4
|
fractionDigits: number;
|
|
5
5
|
};
|
|
6
|
+
/**
|
|
7
|
+
* How a readout's `value` is interpreted.
|
|
8
|
+
* - `number`: formatted via `fractionDigits` / `maxDigits`.
|
|
9
|
+
* - `text`: rendered verbatim, with the numeric format options ignored.
|
|
10
|
+
*/
|
|
11
|
+
export declare enum ReadoutValueType {
|
|
12
|
+
number = "number",
|
|
13
|
+
text = "text"
|
|
14
|
+
}
|
|
15
|
+
/** Whether `value` is one of the supported {@link ReadoutValueType} values. */
|
|
16
|
+
export declare function isReadoutValueType(value: unknown): value is ReadoutValueType;
|
|
17
|
+
/**
|
|
18
|
+
* Throws when `valueType` is not a supported value, or when `value` is text but
|
|
19
|
+
* `valueType` is `number`.
|
|
20
|
+
*
|
|
21
|
+
* `valueType` is validated first because an attribute carries an unchecked
|
|
22
|
+
* string: a typo such as `valuetype="strng"` matches neither mode, so every
|
|
23
|
+
* mode check falls through and the readout silently renders the unavailable
|
|
24
|
+
* dash — the opposite of the loud failure this contract exists to give.
|
|
25
|
+
* `undefined`/`null` are allowed and mean "use the default".
|
|
26
|
+
*
|
|
27
|
+
* Attributes are always strings, so a numeric-looking string (`value="10.12"`)
|
|
28
|
+
* is accepted and parsed. Blank strings resolve to the unavailable dash rather
|
|
29
|
+
* than throwing — `value="${maybeUndefined}"` is a common template shape, and
|
|
30
|
+
* `Number('')` is `0`, a silently wrong reading.
|
|
31
|
+
*/
|
|
32
|
+
export declare function assertReadoutValueType(tagName: string, value: number | string | null | undefined, valueType: ReadoutValueType): void;
|
|
33
|
+
/** The value as a number, or `undefined` when it is text / unavailable. */
|
|
34
|
+
export declare function resolveReadoutNumericValue(value: number | string | null | undefined, valueType: ReadoutValueType): number | undefined;
|
|
35
|
+
/** The value as display text, or `undefined` when not in text mode / blank. */
|
|
36
|
+
export declare function resolveReadoutTextValue(value: number | string | null | undefined, valueType: ReadoutValueType): string | undefined;
|
|
6
37
|
export declare function formatNumericValue(value: number | undefined, options: ReadoutNumericFormatOptions): string;
|
|
7
38
|
export declare function readoutFormattedInteger(valueText: string): number;
|
|
8
39
|
export declare function getHintZeros(value: number | undefined, { showZeroPadding, minValueLength, fractionDigits }: ReadoutNumericFormatOptions): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readout-formatters.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/readout/readout-formatters.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,2BAA2B,GAAG;IACxC,eAAe,EAAE,OAAO,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;
|
|
1
|
+
{"version":3,"file":"readout-formatters.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/readout/readout-formatters.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,2BAA2B,GAAG;IACxC,eAAe,EAAE,OAAO,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF;;;;GAIG;AACH,oBAAY,gBAAgB;IAC1B,MAAM,WAAW;IACjB,IAAI,SAAS;CACd;AAID,+EAA+E;AAC/E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAE5E;AAMD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,EACzC,SAAS,EAAE,gBAAgB,GAC1B,IAAI,CAyBN;AAED,2EAA2E;AAC3E,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,EACzC,SAAS,EAAE,gBAAgB,GAC1B,MAAM,GAAG,SAAS,CAgBpB;AAED,+EAA+E;AAC/E,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,EACzC,SAAS,EAAE,gBAAgB,GAC1B,MAAM,GAAG,SAAS,CAUpB;AAoBD,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,OAAO,EAAE,2BAA2B,GACnC,MAAM,CAMR;AAED,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CASjE;AAED,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,EAAC,eAAe,EAAE,cAAc,EAAE,cAAc,EAAC,EAAE,2BAA2B,GAC7E,MAAM,CAeR"}
|
|
@@ -1,3 +1,52 @@
|
|
|
1
|
+
var ReadoutValueType = /* @__PURE__ */ ((ReadoutValueType2) => {
|
|
2
|
+
ReadoutValueType2["number"] = "number";
|
|
3
|
+
ReadoutValueType2["text"] = "text";
|
|
4
|
+
return ReadoutValueType2;
|
|
5
|
+
})(ReadoutValueType || {});
|
|
6
|
+
const READOUT_VALUE_TYPES = Object.values(ReadoutValueType);
|
|
7
|
+
function isReadoutValueType(value) {
|
|
8
|
+
return typeof value === "string" && READOUT_VALUE_TYPES.includes(value);
|
|
9
|
+
}
|
|
10
|
+
function isBlank(value) {
|
|
11
|
+
return value.trim() === "";
|
|
12
|
+
}
|
|
13
|
+
function assertReadoutValueType(tagName, value, valueType) {
|
|
14
|
+
const resolved = valueType ?? "number";
|
|
15
|
+
if (!isReadoutValueType(resolved)) {
|
|
16
|
+
throw new TypeError(
|
|
17
|
+
`<${tagName}>: valueType must be ${READOUT_VALUE_TYPES.map((t) => `"${t}"`).join(" or ")} (got ${JSON.stringify(valueType)}).`
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
if (resolved !== "number" || typeof value !== "string" || isBlank(value)) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
if (Number.isFinite(Number(value))) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
throw new TypeError(
|
|
27
|
+
`<${tagName}>: value must be a number when valueType is "number" (got ${JSON.stringify(value)}). Set valueType="text" to render text.`
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
function resolveReadoutNumericValue(value, valueType) {
|
|
31
|
+
if (valueType === "text" || value === null || value === void 0) {
|
|
32
|
+
return void 0;
|
|
33
|
+
}
|
|
34
|
+
if (typeof value === "number") {
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
if (isBlank(value)) {
|
|
38
|
+
return void 0;
|
|
39
|
+
}
|
|
40
|
+
const parsed = Number(value);
|
|
41
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
42
|
+
}
|
|
43
|
+
function resolveReadoutTextValue(value, valueType) {
|
|
44
|
+
if (valueType !== "text" || value === null || value === void 0) {
|
|
45
|
+
return void 0;
|
|
46
|
+
}
|
|
47
|
+
const text = typeof value === "number" ? String(value) : value;
|
|
48
|
+
return isBlank(text) ? void 0 : text;
|
|
49
|
+
}
|
|
1
50
|
function dashedGenerator({
|
|
2
51
|
showZeroPadding,
|
|
3
52
|
minValueLength,
|
|
@@ -40,8 +89,13 @@ function getHintZeros(value, { showZeroPadding, minValueLength, fractionDigits }
|
|
|
40
89
|
return "";
|
|
41
90
|
}
|
|
42
91
|
export {
|
|
92
|
+
ReadoutValueType,
|
|
93
|
+
assertReadoutValueType,
|
|
43
94
|
formatNumericValue,
|
|
44
95
|
getHintZeros,
|
|
45
|
-
|
|
96
|
+
isReadoutValueType,
|
|
97
|
+
readoutFormattedInteger,
|
|
98
|
+
resolveReadoutNumericValue,
|
|
99
|
+
resolveReadoutTextValue
|
|
46
100
|
};
|
|
47
101
|
//# sourceMappingURL=readout-formatters.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readout-formatters.js","sources":["../../../src/navigation-instruments/readout/readout-formatters.ts"],"sourcesContent":["export type ReadoutNumericFormatOptions = {\n showZeroPadding: boolean;\n minValueLength: number;\n fractionDigits: number;\n};\n\nfunction dashedGenerator({\n showZeroPadding,\n minValueLength,\n fractionDigits,\n}: ReadoutNumericFormatOptions): string {\n const visibleDigits = showZeroPadding ? Math.max(minValueLength, 1) : 1;\n\n if (fractionDigits < 1) {\n return '-'.repeat(visibleDigits);\n }\n\n const integerDigits = visibleDigits - fractionDigits;\n\n return (\n '-'.repeat(Math.max(integerDigits, 1)) + '.' + '-'.repeat(fractionDigits)\n );\n}\n\nexport function formatNumericValue(\n value: number | undefined,\n options: ReadoutNumericFormatOptions\n): string {\n if (value === undefined) {\n return dashedGenerator(options);\n }\n\n return value.toFixed(options.fractionDigits);\n}\n\nexport function readoutFormattedInteger(valueText: string): number {\n const t = valueText.trim();\n if (!t) {\n return 0;\n }\n\n const rest = t.startsWith('-') ? t.slice(1) : t;\n const dot = rest.indexOf('.');\n return dot === -1 ? rest.length : dot;\n}\n\nexport function getHintZeros(\n value: number | undefined,\n {showZeroPadding, minValueLength, fractionDigits}: ReadoutNumericFormatOptions\n): string {\n const formattedValue = formatNumericValue(value, {\n showZeroPadding,\n minValueLength,\n fractionDigits,\n });\n const dotLength = fractionDigits > 0 ? 1 : 0;\n const integerLength = formattedValue.length - dotLength;\n const hintedDigits = Math.max(minValueLength - integerLength, 0);\n\n if (hintedDigits > 0) {\n return '0'.repeat(hintedDigits);\n }\n\n return '';\n}\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"readout-formatters.js","sources":["../../../src/navigation-instruments/readout/readout-formatters.ts"],"sourcesContent":["export type ReadoutNumericFormatOptions = {\n showZeroPadding: boolean;\n minValueLength: number;\n fractionDigits: number;\n};\n\n/**\n * How a readout's `value` is interpreted.\n * - `number`: formatted via `fractionDigits` / `maxDigits`.\n * - `text`: rendered verbatim, with the numeric format options ignored.\n */\nexport enum ReadoutValueType {\n number = 'number',\n text = 'text',\n}\n\nconst READOUT_VALUE_TYPES: readonly string[] = Object.values(ReadoutValueType);\n\n/** Whether `value` is one of the supported {@link ReadoutValueType} values. */\nexport function isReadoutValueType(value: unknown): value is ReadoutValueType {\n return typeof value === 'string' && READOUT_VALUE_TYPES.includes(value);\n}\n\nfunction isBlank(value: string): boolean {\n return value.trim() === '';\n}\n\n/**\n * Throws when `valueType` is not a supported value, or when `value` is text but\n * `valueType` is `number`.\n *\n * `valueType` is validated first because an attribute carries an unchecked\n * string: a typo such as `valuetype=\"strng\"` matches neither mode, so every\n * mode check falls through and the readout silently renders the unavailable\n * dash — the opposite of the loud failure this contract exists to give.\n * `undefined`/`null` are allowed and mean \"use the default\".\n *\n * Attributes are always strings, so a numeric-looking string (`value=\"10.12\"`)\n * is accepted and parsed. Blank strings resolve to the unavailable dash rather\n * than throwing — `value=\"${maybeUndefined}\"` is a common template shape, and\n * `Number('')` is `0`, a silently wrong reading.\n */\nexport function assertReadoutValueType(\n tagName: string,\n value: number | string | null | undefined,\n valueType: ReadoutValueType\n): void {\n // `undefined`/`null` mean \"use the default\", matching how the components and\n // the resolvers treat an unset `valueType`.\n const resolved = valueType ?? ReadoutValueType.number;\n if (!isReadoutValueType(resolved)) {\n throw new TypeError(\n `<${tagName}>: valueType must be ` +\n `${READOUT_VALUE_TYPES.map((t) => `\"${t}\"`).join(' or ')} ` +\n `(got ${JSON.stringify(valueType)}).`\n );\n }\n if (\n resolved !== ReadoutValueType.number ||\n typeof value !== 'string' ||\n isBlank(value)\n ) {\n return;\n }\n if (Number.isFinite(Number(value))) {\n return;\n }\n throw new TypeError(\n `<${tagName}>: value must be a number when valueType is \"number\" ` +\n `(got ${JSON.stringify(value)}). Set valueType=\"text\" to render text.`\n );\n}\n\n/** The value as a number, or `undefined` when it is text / unavailable. */\nexport function resolveReadoutNumericValue(\n value: number | string | null | undefined,\n valueType: ReadoutValueType\n): number | undefined {\n if (\n valueType === ReadoutValueType.text ||\n value === null ||\n value === undefined\n ) {\n return undefined;\n }\n if (typeof value === 'number') {\n return value;\n }\n if (isBlank(value)) {\n return undefined;\n }\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : undefined;\n}\n\n/** The value as display text, or `undefined` when not in text mode / blank. */\nexport function resolveReadoutTextValue(\n value: number | string | null | undefined,\n valueType: ReadoutValueType\n): string | undefined {\n if (\n valueType !== ReadoutValueType.text ||\n value === null ||\n value === undefined\n ) {\n return undefined;\n }\n const text = typeof value === 'number' ? String(value) : value;\n return isBlank(text) ? undefined : text;\n}\n\nfunction dashedGenerator({\n showZeroPadding,\n minValueLength,\n fractionDigits,\n}: ReadoutNumericFormatOptions): string {\n const visibleDigits = showZeroPadding ? Math.max(minValueLength, 1) : 1;\n\n if (fractionDigits < 1) {\n return '-'.repeat(visibleDigits);\n }\n\n const integerDigits = visibleDigits - fractionDigits;\n\n return (\n '-'.repeat(Math.max(integerDigits, 1)) + '.' + '-'.repeat(fractionDigits)\n );\n}\n\nexport function formatNumericValue(\n value: number | undefined,\n options: ReadoutNumericFormatOptions\n): string {\n if (value === undefined) {\n return dashedGenerator(options);\n }\n\n return value.toFixed(options.fractionDigits);\n}\n\nexport function readoutFormattedInteger(valueText: string): number {\n const t = valueText.trim();\n if (!t) {\n return 0;\n }\n\n const rest = t.startsWith('-') ? t.slice(1) : t;\n const dot = rest.indexOf('.');\n return dot === -1 ? rest.length : dot;\n}\n\nexport function getHintZeros(\n value: number | undefined,\n {showZeroPadding, minValueLength, fractionDigits}: ReadoutNumericFormatOptions\n): string {\n const formattedValue = formatNumericValue(value, {\n showZeroPadding,\n minValueLength,\n fractionDigits,\n });\n const dotLength = fractionDigits > 0 ? 1 : 0;\n const integerLength = formattedValue.length - dotLength;\n const hintedDigits = Math.max(minValueLength - integerLength, 0);\n\n if (hintedDigits > 0) {\n return '0'.repeat(hintedDigits);\n }\n\n return '';\n}\n"],"names":["ReadoutValueType"],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ import { LitElement } from 'lit';
|
|
|
2
2
|
import { ReadoutBlockSize, ReadoutBlockDataQuality } from '../../building-blocks/readout-block/readout-block.js';
|
|
3
3
|
import { ReadoutListItemSetpointInteraction, ReadoutValueOptions, ReadoutSetpointOptions, ReadoutAdviceOptions, ReadoutReserverOptions, ReadoutSrcOptions } from '../readout-list-item/readout-list-item.js';
|
|
4
4
|
import { Priority } from '../types.js';
|
|
5
|
+
import { ReadoutValueType } from './readout-formatters.js';
|
|
5
6
|
import { AlertFrameConfig } from '../../components/alert-frame/alert-frame.js';
|
|
6
7
|
import '../../components/textbox/textbox.js';
|
|
7
8
|
import '../../building-blocks/readout-block/readout-block.js';
|
|
@@ -10,6 +11,7 @@ import '../../components/context-menu-input/context-menu-input.js';
|
|
|
10
11
|
import '../../icons/icon-chevron-right-google.js';
|
|
11
12
|
import '../../icons/icon-drop-down-google.js';
|
|
12
13
|
export { ObcTextboxFontWeight } from '../../components/textbox/textbox.js';
|
|
14
|
+
export { ReadoutValueType } from './readout-formatters.js';
|
|
13
15
|
export type { ReadoutBlockState, ReadoutValueOptions, ReadoutSetpointOptions, ReadoutAdviceOptions, ReadoutReserverOptions, ReadoutSrcOptions, } from '../readout-list-item/readout-list-item.js';
|
|
14
16
|
/**
|
|
15
17
|
* Density/size scale of the readout (an alias of `ReadoutBlockSize`).
|
|
@@ -137,6 +139,8 @@ export interface ReadoutSourceOptions extends ReadoutSrcOptions {
|
|
|
137
139
|
* `flyout` interactivity via `srcOptions.interaction`.
|
|
138
140
|
* - **Formatting:** shared `fractionDigits`, width reservation via
|
|
139
141
|
* `maxDigits` and per-segment `hintedZeros`; a `null` value renders a dash.
|
|
142
|
+
* - **Text values:** `valueType="text"` renders `value` verbatim (e.g.
|
|
143
|
+
* `"Auto"`) instead of formatting it as a number.
|
|
140
144
|
*
|
|
141
145
|
* ### Usage Guidelines
|
|
142
146
|
* Use for stand-alone instrument readouts and readouts embedded in
|
|
@@ -174,7 +178,17 @@ export declare class ObcReadout extends LitElement {
|
|
|
174
178
|
* value block at full size, so the layout does not shift when data arrives.
|
|
175
179
|
*/
|
|
176
180
|
hasValue: boolean;
|
|
177
|
-
|
|
181
|
+
/**
|
|
182
|
+
* The value; `null` renders a dash. A number by default, or text when
|
|
183
|
+
* {@link valueType} is `text`.
|
|
184
|
+
*/
|
|
185
|
+
value: number | string | null;
|
|
186
|
+
/**
|
|
187
|
+
* How {@link value} is interpreted. `number` (default) formats it via
|
|
188
|
+
* `fractionDigits`; `text` renders it verbatim and ignores the numeric
|
|
189
|
+
* format options. Passing text while this is `number` throws.
|
|
190
|
+
*/
|
|
191
|
+
valueType: ReadoutValueType;
|
|
178
192
|
/** Render the value as `offText` (e.g. equipment powered down). Affects the value only. */
|
|
179
193
|
off: boolean;
|
|
180
194
|
/** Text shown in place of the value when `off` is true. @availableWhen off==true */
|
|
@@ -195,7 +209,17 @@ export declare class ObcReadout extends LitElement {
|
|
|
195
209
|
hasDegree: boolean;
|
|
196
210
|
/** @availableWhen hasDegree==false */
|
|
197
211
|
hasDegreeSpacer: boolean;
|
|
212
|
+
/**
|
|
213
|
+
* Also formats the numeric setpoint / advice blocks, which stay numeric
|
|
214
|
+
* even when the value is text.
|
|
215
|
+
* @availableWhen valueType==number || hasSetpoint==true || hasAdvice==true
|
|
216
|
+
*/
|
|
198
217
|
fractionDigits: number;
|
|
218
|
+
/**
|
|
219
|
+
* Also formats the numeric setpoint / advice blocks, which stay numeric
|
|
220
|
+
* even when the value is text.
|
|
221
|
+
* @availableWhen valueType==number || hasSetpoint==true || hasAdvice==true
|
|
222
|
+
*/
|
|
199
223
|
maxDigits: number;
|
|
200
224
|
dataQuality?: ReadoutDataQuality;
|
|
201
225
|
alert: boolean | AlertFrameConfig;
|
|
@@ -361,6 +385,7 @@ export declare class ObcReadout extends LitElement {
|
|
|
361
385
|
* divider.
|
|
362
386
|
*/
|
|
363
387
|
private renderHorizontalLayout;
|
|
388
|
+
protected willUpdate(changed: Map<string, unknown>): void;
|
|
364
389
|
updated(changed: Map<string, unknown>): void;
|
|
365
390
|
private clearDeferredSetpointHide;
|
|
366
391
|
disconnectedCallback(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readout.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/readout/readout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAgD,MAAM,KAAK,CAAC;AAK9E,OAAO,qCAAqC,CAAC;AAK7C,OAAO,sDAAsD,CAAC;AAC9D,OAAO,EAEL,gBAAgB,EAChB,uBAAuB,EAExB,MAAM,sDAAsD,CAAC;AAC9D,OAAO,EACL,kCAAkC,EAElC,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACvB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"readout.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/readout/readout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAgD,MAAM,KAAK,CAAC;AAK9E,OAAO,qCAAqC,CAAC;AAK7C,OAAO,sDAAsD,CAAC;AAC9D,OAAO,EAEL,gBAAgB,EAChB,uBAAuB,EAExB,MAAM,sDAAsD,CAAC;AAC9D,OAAO,EACL,kCAAkC,EAElC,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACvB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AACrC,OAAO,EAGL,gBAAgB,EAEjB,MAAM,yBAAyB,CAAC;AAUjC,OAAO,EACL,KAAK,gBAAgB,EAKtB,MAAM,6CAA6C,CAAC;AAErD,OAAO,mCAAmC,CAAC;AAC3C,OAAO,2DAA2D,CAAC;AAMnE,OAAO,0CAA0C,CAAC;AAClD,OAAO,sCAAsC,CAAC;AAM9C,OAAO,EAAC,oBAAoB,EAAC,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAC,gBAAgB,EAAC,MAAM,yBAAyB,CAAC;AACzD,YAAY,EACV,iBAAiB,EACjB,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,2CAA2C,CAAC;AAEnD;;;;;GAKG;AACH,eAAO,MAAM,WAAW,yBAAmB,CAAC;AAC5C,MAAM,MAAM,WAAW,GAAG,gBAAgB,CAAC;AAE3C;;;;;GAKG;AACH,eAAO,MAAM,eAAe,iBAAW,CAAC;AACxC,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;AAEvC;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,gCAA0B,CAAC;AAC1D,MAAM,MAAM,kBAAkB,GAAG,uBAAuB,CAAC;AAEzD;;;;;;;;GAQG;AACH,eAAO,MAAM,0BAA0B,2CAAqC,CAAC;AAC7E,MAAM,MAAM,0BAA0B,GAAG,kCAAkC,CAAC;AAE5E;;;;;;;;GAQG;AACH,oBAAY,gBAAgB;IAC1B,QAAQ,aAAa;IACrB,UAAU,eAAe;CAC1B;AAED;;;;;;GAMG;AACH,oBAAY,eAAe;IACzB,MAAM,WAAW;IACjB,OAAO,YAAY;CACpB;AAED;;;;;;GAMG;AACH,oBAAY,gBAAgB;IAC1B,QAAQ,aAAa;IACrB,IAAI,SAAS;IACb,MAAM,WAAW;CAClB;AAED;;;;;;;;;GASG;AACH,oBAAY,wBAAwB;IAClC,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,MAAM,WAAW;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAqB,SAAQ,iBAAiB;IAC7D,wDAAwD;IACxD,WAAW,CAAC,EAAE,wBAAwB,CAAC;CACxC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AACH,qBACa,UAAW,SAAQ,UAAU;IAEd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IAEvC;;;;;OAKG;IAC0C,QAAQ,UAAQ;IAC7D;;;OAGG;IACuB,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAQ;IAC/D;;;;OAIG;IACuB,SAAS,EAAE,gBAAgB,CAC3B;IAC1B,2FAA2F;IAChE,GAAG,UAAS;IACvC,oFAAoF;IAC1D,OAAO,SAAS;IAEf,WAAW,UAAS;IAC/C,uCAAuC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAEjB,SAAS,UAAS;IAC7C,qCAAqC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAGhB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,SAAS,CAAC,EAAE,gBAAgB,CAAC;IACvD,yCAAyC;IACf,QAAQ,CAAC,EAAE,eAAe,CAAC;IACrD,8DAA8D;IACpC,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC5B,SAAS,UAAS;IAC7C,sCAAsC;IACX,eAAe,UAAS;IACnD;;;;OAIG;IACuB,cAAc,SAAK;IAC7C;;;;OAIG;IACuB,SAAS,SAAK;IACd,WAAW,CAAC,EAAE,kBAAkB,CAAC;IAKjC,KAAK,EAAE,OAAO,GAAG,gBAAgB,CAAS;IAGpE,oCAAoC;IACV,YAAY,CAAC,EAAE,mBAAmB,CAAC;IAC7D,uCAAuC;IACb,eAAe,CAAC,EAAE,sBAAsB,CAAC;IACnE,qCAAqC;IACX,aAAa,CAAC,EAAE,oBAAoB,CAAC;IAC/D,8BAA8B;IACJ,WAAW,CAAC,EAAE,sBAAsB,CAAC;IAC/D,6BAA6B;IACH,UAAU,CAAC,EAAE,oBAAoB,CAAC;IAE5D;;;;OAIG;IACuC,gBAAgB,UAAS;IAEnE,yEAAyE;IAChE,OAAO,CAAC,yBAAyB,CACb;IAC7B,OAAO,CAAC,yBAAyB,CAAC,CAAS;IAC3C,OAAO,CAAC,uBAAuB,CAAS;IAE/B,OAAO,CAAC,0BAA0B,CAAS;IAC3C,OAAO,CAAC,mBAAmB,CAA2B;IAG/D,OAAO,CAAC,gBAAgB,CAAC,CAAkB;IAE3C,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAQlC;IAEF,OAAO,KAAK,YAAY,GAEvB;IAED,OAAO,KAAK,gBAAgB,GAE3B;IAED,OAAO,KAAK,iBAAiB,GAE5B;IAED,OAAO,KAAK,gBAAgB,GAE3B;IAED,OAAO,KAAK,iBAAiB,GAE5B;IAED,OAAO,KAAK,YAAY,GAEvB;IAED,OAAO,KAAK,sBAAsB,GAEjC;IAED,OAAO,KAAK,iBAAiB,GAE5B;IAED,OAAO,KAAK,MAAM,GAEjB;IAED,OAAO,KAAK,yBAAyB,GAEpC;IAED,OAAO,KAAK,YAAY,GAWvB;IAED,OAAO,KAAK,2BAA2B,GAKtC;IAED,OAAO,KAAK,UAAU,GAIrB;IAED,OAAO,KAAK,OAAO,GAIlB;IAED,OAAO,KAAK,gBAAgB,GAE3B;IAED;;;;;OAKG;IACH,OAAO,KAAK,kBAAkB,GAE7B;IAED;;;;;OAKG;IACH,OAAO,KAAK,oBAAoB,GAQ/B;IAED;;;;;OAKG;IACH,OAAO,KAAK,WAAW,GAEtB;IAED,kEAAkE;IAClE,OAAO,KAAK,WAAW,GAEtB;IAED,oFAAoF;IACpF,OAAO,KAAK,aAAa,GAExB;IAED,OAAO,KAAK,SAAS,GAQpB;IAED,OAAO,KAAK,YAAY,GAEvB;IAED,gGAAgG;IAChG,OAAO,KAAK,WAAW,GAEtB;IAED,4EAA4E;IAC5E,OAAO,KAAK,cAAc,GAEzB;IAED,OAAO,CAAC,oBAAoB;IAI5B,8EAA8E;IAC9E,OAAO,CAAC,kBAAkB;IAM1B;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IAU3B,OAAO,CAAC,WAAW;IAwDnB;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAiBzB;;;;;;;OAOG;IACH,OAAO,CAAC,kBAAkB;IAgB1B,OAAO,CAAC,aAAa;IA4BrB,OAAO,KAAK,iBAAiB,GAO5B;IAED,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,mBAAmB;IAmB3B;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;IA0B1B;;;;;;;OAOG;IACH,OAAO,CAAC,uBAAuB;IA+B/B,oFAAoF;IACpF,OAAO,CAAC,cAAc;IA8BtB,OAAO,CAAC,mBAAmB;IAgE3B,+EAA+E;IAC/E,OAAO,CAAC,YAAY;IAsBpB,OAAO,CAAC,8BAA8B;IAiBtC,OAAO,CAAC,4BAA4B;IAQpC,OAAO,CAAC,uBAAuB;IAgB/B,OAAO,CAAC,6BAA6B;IAWrC,OAAO,CAAC,uBAAuB,CAc7B;IAEF,OAAO,CAAC,2BAA2B;IAiBnC;;;;;;OAMG;IACH,OAAO,KAAK,oBAAoB,GAQ/B;IAED,OAAO,CAAC,yBAAyB;IAqBjC,OAAO,CAAC,sBAAsB;IAY9B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,0BAA0B;IAuClC;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAyB5B;;;;OAIG;IACH,OAAO,CAAC,sBAAsB;cAuBX,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAYzD,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAoDrD,OAAO,CAAC,yBAAyB;IAQxB,oBAAoB,IAAI,IAAI;IAa5B,MAAM;IAkCf,OAAgB,MAAM,0BAA6B;CACpD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,aAAa,EAAE,UAAU,CAAC;KAC3B;CACF"}
|