@oicl/openbridge-webcomponents 2.0.0-next.161 → 2.0.0-next.163

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.
Files changed (33) hide show
  1. package/bundle/openbridge-webcomponents.bundle.js +439 -327
  2. package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
  3. package/custom-elements.json +96 -29
  4. package/dist/components/keyboard-numeric/keyboard-numeric.css.js +2 -3
  5. package/dist/components/keyboard-numeric/keyboard-numeric.css.js.map +1 -1
  6. package/dist/navigation-instruments/compass-sector/compass-sector.css.js +20 -11
  7. package/dist/navigation-instruments/compass-sector/compass-sector.css.js.map +1 -1
  8. package/dist/navigation-instruments/compass-sector/compass-sector.d.ts +18 -17
  9. package/dist/navigation-instruments/compass-sector/compass-sector.d.ts.map +1 -1
  10. package/dist/navigation-instruments/compass-sector/compass-sector.js +85 -52
  11. package/dist/navigation-instruments/compass-sector/compass-sector.js.map +1 -1
  12. package/dist/navigation-instruments/gauge-radial/gauge-radial.css.js +2 -6
  13. package/dist/navigation-instruments/gauge-radial/gauge-radial.css.js.map +1 -1
  14. package/dist/navigation-instruments/rudder/rudder.css.js +40 -0
  15. package/dist/navigation-instruments/rudder/rudder.css.js.map +1 -0
  16. package/dist/navigation-instruments/rudder/rudder.d.ts +9 -0
  17. package/dist/navigation-instruments/rudder/rudder.d.ts.map +1 -1
  18. package/dist/navigation-instruments/rudder/rudder.js +40 -23
  19. package/dist/navigation-instruments/rudder/rudder.js.map +1 -1
  20. package/dist/navigation-instruments/watch/watch.css.js +6 -0
  21. package/dist/navigation-instruments/watch/watch.css.js.map +1 -1
  22. package/dist/navigation-instruments/watch/watch.d.ts.map +1 -1
  23. package/dist/navigation-instruments/watch/watch.js +11 -1
  24. package/dist/navigation-instruments/watch/watch.js.map +1 -1
  25. package/dist/svghelpers/arc-frame.d.ts +8 -0
  26. package/dist/svghelpers/arc-frame.d.ts.map +1 -1
  27. package/dist/svghelpers/arc-frame.js +16 -6
  28. package/dist/svghelpers/arc-frame.js.map +1 -1
  29. package/dist/svghelpers/radial-frame.d.ts +14 -1
  30. package/dist/svghelpers/radial-frame.d.ts.map +1 -1
  31. package/dist/svghelpers/radial-frame.js +3 -1
  32. package/dist/svghelpers/radial-frame.js.map +1 -1
  33. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"compass-sector.js","sources":["../../../src/navigation-instruments/compass-sector/compass-sector.ts"],"sourcesContent":["import {LitElement, PropertyValues, html, svg, unsafeCSS, nothing} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport componentStyle from './compass-sector.css?inline';\nimport '../watch/watch.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 {Tickmark, TickmarkType, TickmarkStyle} from '../watch/tickmark.js';\nimport {arrow, ArrowStyle} from '../compass/arrow.js';\nimport {AdviceState, AngleAdvice, AngleAdviceRaw} from '../watch/advice.js';\nimport {\n WatchCircleType,\n WatchArea,\n OUTER_RING_RADIUS,\n innerRingRadiusFor,\n RotType,\n RotPosition,\n} from '../watch/watch.js';\nimport {SetpointBundle} from '../../svghelpers/setpoint-bundle.js';\nimport {\n computeZoomToFitArcFrame,\n type ZoomToFitArcFrame,\n} from '../../svghelpers/arc-frame.js';\nimport {ROT_ZERO_DEADBAND_DEG} from '../rate-of-turn/rot-renderer.js';\nimport {customElement} from '../../decorator.js';\nimport {normalizeAngle} from '../../svghelpers/math.js';\nimport {InstrumentState, Priority} from '../types.js';\nexport {RotType, RotPosition};\n\nexport enum CompassSectorPriorityElement {\n hdg = 'hdg',\n cog = 'cog',\n rot = 'rot',\n}\n\n// Fixed frame padding for the zoomed and un-zoomed paths alike. The bespoke\n// FOV-compression geometry stays instead of svghelpers/radial-frame.ts: the\n// viewBox is cached per FOV, which a container-size-dependent label reserve\n// would invalidate, and 72 units covers the 3-char degree labels.\n// TODO(#1021): adopt computeRadialFrame if degree labels ever clip.\nconst PADDING = 72;\nconst WATCH_TYPE = WatchCircleType.triple;\nconst INNER_RADIUS = innerRingRadiusFor(WATCH_TYPE);\n/** Half of the fixed 120° arc on the watch face. */\nconst ARC_HALF_EXTENT = 60;\nconst SCALE_INNER_RADIUS = innerRingRadiusFor(WatchCircleType.single);\n\ninterface TickDensity {\n mainInterval: number;\n primaryInterval: number;\n secondaryInterval: number | undefined;\n}\n\nfunction tickDensityForFOV(fov: number): TickDensity {\n if (fov <= 30) {\n return {mainInterval: 10, primaryInterval: 5, secondaryInterval: 1};\n } else if (fov <= 60) {\n return {mainInterval: 10, primaryInterval: 5, secondaryInterval: undefined};\n } else if (fov <= 120) {\n return {mainInterval: 30, primaryInterval: 10, secondaryInterval: 5};\n } else {\n return {mainInterval: 90, primaryInterval: 30, secondaryInterval: 10};\n }\n}\n\n/**\n * `<obc-compass-sector>` — Curved compass strip that auto‑scales to keep HDG and COG visible.\n *\n * Renders a fixed 120° arc of a triple‑ring compass face. The visible\n * compass range (field of view) adjusts automatically so that both the\n * heading (HDG) and course‑over‑ground (COG) arrows are always in view.\n * This is the radial equivalent of `<obc-compass-flat>`: the arc shape\n * never changes — only the scale (compass‑degrees per arc‑degree) changes.\n *\n * ## Features\n *\n * - **Fixed 120° arc**: The watch face is always a 120° sector (±60° from\n * center), identical in shape to `<obc-rot-sector>`.\n * - **FOV auto‑scaling**: The field of view widens when the HDG–COG\n * angular difference grows, compressing more compass degrees into the\n * fixed arc. Tickmark density adjusts automatically.\n * - **HDG / COG arrows**: Solid (HDG) arrow is always at the arc center.\n * Hollow (COG) arrow is positioned proportionally within the arc.\n * - **North arrow**: A gray triangle in the outer scale band indicates\n * north when it falls within the visible FOV.\n * - **Heading setpoint**: Optional setpoint marker with auto at‑setpoint\n * detection and confirm animation, positioned at the mapped arc angle.\n * - **Advice zones**: Pass `headingAdvices` to render caution/alert arcs,\n * mapped into the scaled arc.\n * - **Rate of turn**: Animated ROT indicator (dots or bar) spanning from\n * HDG to the mapped COG position, clipped to the arc.\n * - **Zoom to fit**: When `zoomToFitArc` is `true`, the fixed 120° arc is\n * enlarged to fill the available space.\n *\n * ## Usage Guidelines\n *\n * - Set `heading` and `courseOverGround` to sensor values in degrees.\n * - Adjust `minFOV` to control the minimum zoom level (default 30°).\n * - Enable `zoomToFitArc` to enlarge the arc to fill the viewport.\n * - For a full‑circle compass, use `<obc-compass>` instead.\n *\n * @availableWhen newHeadingSetpoint headingSetpoint!=null\n * @availableWhen atHeadingSetpoint headingSetpoint!=null && autoAtHeadingSetpoint==false\n * @availableWhen headingSetpointAtZeroDeadband headingSetpoint!=null\n * @availableWhen headingSetpointOverride headingSetpoint!=null\n * @availableWhen autoAtHeadingSetpoint headingSetpoint!=null\n * @availableWhen autoAtHeadingSetpointDeadband headingSetpoint!=null && autoAtHeadingSetpoint==true\n * @availableWhen animateSetpoint headingSetpoint!=null\n * @availableWhen touching headingSetpoint!=null\n * @availableWhen rotPosition rotType!=undefined\n * @property rateOfTurnDegreesPerMinute - Measured rate of turn in degrees per minute (positive = starboard).\n * Drives both the bar extent and (after multiplication by\n * `rotDotAnimationFactor`) the spinning dot animation. When `undefined`,\n * falls back to the deprecated `rotationsPerMinute`.\n * @availableWhen rateOfTurnDegreesPerMinute rotType!=undefined\n * @property rotDotAnimationFactor - Visual amplification applied only to the spinning dot animation\n * (not to the bar extent). Default `18` keeps the legacy visual feel\n * (≈1 rpm at 20°/min).\n * @availableWhen rotDotAnimationFactor rotType!=undefined\n * @availableWhen rotPortStarboard rotType!=undefined\n * @availableWhen rotAtZeroDeadband rotType==bar\n * @availableWhen priorityElements priority==enhanced\n * @property hasReadout - When `true`, shows a centered `<obc-readout>` under the arc displaying the\n * heading (label `HDG`, unit `DEG`). The value color follows the HDG entry in\n * `priorityElements`, matching the HDG arrow.\n * @property label - Readout label. Default `HDG`.\n * @availableWhen label hasReadout==true\n * @property unit - Readout unit. Default `DEG`.\n * @availableWhen unit hasReadout==true\n * @property fractionDigits - Number of fraction digits shown in the readout. Default `0`.\n * @availableWhen fractionDigits hasReadout==true\n * @property rotMaxValue - Bar-extent reference value in degrees per minute: the bar fills the full\n * ±`ARC_HALF_EXTENT` arc when the measured rate of turn reaches\n * ±`rotMaxValue`. The default `60` aligns with ES-TRIN 2025/1 Art. 3.02.\n * @availableWhen rotMaxValue rotType==bar\n * @stable\n */\n@customElement('obc-compass-sector')\nexport class ObcCompassSector extends LitElement {\n @property({type: Number}) heading = 0;\n @property({type: Number}) courseOverGround = 0;\n\n @property({type: Number}) headingSetpoint: number | null = null;\n @property({type: Number}) newHeadingSetpoint: number | undefined;\n @property({type: Boolean}) atHeadingSetpoint: boolean = false;\n @property({type: Number}) headingSetpointAtZeroDeadband: number = 0.5;\n @property({type: Boolean}) headingSetpointOverride: boolean = false;\n @property({type: Boolean, attribute: false}) autoAtHeadingSetpoint = true;\n @property({type: Number}) autoAtHeadingSetpointDeadband: number = 2;\n @property({type: Boolean}) animateSetpoint: boolean = false;\n @property({type: Boolean}) touching: boolean = false;\n @property({type: Array, attribute: false}) headingAdvices: AngleAdvice[] = [];\n\n @property({type: Number}) minFOV: number = 30;\n\n @property({type: String}) rotType: RotType | undefined;\n @property({type: String}) rotPosition: RotPosition = RotPosition.innerCircle;\n @property({type: Number}) rateOfTurnDegreesPerMinute: number | undefined;\n @property({type: Number}) rotDotAnimationFactor: number = 18;\n /**\n * @deprecated Use `rateOfTurnDegreesPerMinute` (and optionally\n * `rotDotAnimationFactor`) instead. Takes effect only when\n * `rateOfTurnDegreesPerMinute` is `undefined`.\n * @availableWhen rotType!=undefined && rateOfTurnDegreesPerMinute==undefined\n */\n @property({type: Number}) rotationsPerMinute: number = 1;\n @property({type: Number}) rotMaxValue: number = 60;\n @property({type: Boolean}) rotPortStarboard: boolean = false;\n @property({type: Number}) rotAtZeroDeadband: number = ROT_ZERO_DEADBAND_DEG;\n\n @property({type: String}) state: InstrumentState = InstrumentState.active;\n @property({type: String}) priority: Priority = Priority.regular;\n @property({type: Array, attribute: false})\n priorityElements: CompassSectorPriorityElement[] = [\n CompassSectorPriorityElement.hdg,\n ];\n @property({type: Boolean}) tickmarksInside: boolean = false;\n @property({type: Boolean}) zoomToFitArc: boolean = false;\n @property({type: Boolean}) hasReadout: boolean = false;\n @property({type: String}) label = 'HDG';\n @property({type: String}) unit = 'DEG';\n @property({type: Number}) fractionDigits = 0;\n\n private _headingSp = new SetpointBundle({\n angularWraparound: true,\n onAnimationEnd: () => this.requestUpdate(),\n });\n\n // Cached computed values — updated in willUpdate()\n private _halfFOV = 30;\n private _arcHalfExtent = ARC_HALF_EXTENT;\n private _scale = 1;\n private _radiusOffset = 0;\n private _cachedViewBox = '';\n private _cachedArcFrame: ZoomToFitArcFrame | undefined;\n private _cachedAreas: WatchArea[] = [];\n private _cachedTickmarks: Tickmark[] = [];\n private _cachedAdvices: AngleAdviceRaw[] = [];\n\n override willUpdate(changed: PropertyValues): void {\n super.willUpdate(changed);\n this._headingSp.sync({\n setpoint: this.headingSetpoint ?? undefined,\n newSetpoint: this.newHeadingSetpoint,\n atSetpoint: this.atHeadingSetpoint,\n touching: this.touching,\n autoAtSetpoint: this.autoAtHeadingSetpoint,\n autoAtSetpointDeadband: this.autoAtHeadingSetpointDeadband,\n setpointAtZeroDeadband: this.headingSetpointAtZeroDeadband,\n setpointOverride: this.headingSetpointOverride,\n animateSetpoint: this.animateSetpoint,\n });\n\n const arcInputsChanged =\n changed.has('heading') ||\n changed.has('courseOverGround') ||\n changed.has('minFOV') ||\n changed.has('zoomToFitArc');\n\n if (arcInputsChanged) {\n let diff = this.courseOverGround - this.heading;\n if (diff > 180) diff -= 360;\n else if (diff < -180) diff += 360;\n const minFov = Math.max(1, this.minFOV);\n const MARGIN = 15;\n\n if (this.zoomToFitArc) {\n const needed = Math.max(minFov, Math.abs(diff) + MARGIN);\n if (needed <= ARC_HALF_EXTENT) {\n this._halfFOV = needed;\n this._arcHalfExtent = needed;\n this._scale = 1;\n } else {\n this._halfFOV = needed;\n this._arcHalfExtent = ARC_HALF_EXTENT;\n this._scale = ARC_HALF_EXTENT / needed;\n }\n } else {\n this._halfFOV = Math.max(minFov, Math.abs(diff));\n this._arcHalfExtent = ARC_HALF_EXTENT;\n this._scale = ARC_HALF_EXTENT / this._halfFOV;\n }\n\n this._cachedAreas = [\n {\n startAngle: this.heading - this._arcHalfExtent,\n endAngle: this.heading + this._arcHalfExtent,\n roundInsideCut: true,\n roundOutsideCut: true,\n },\n ];\n\n this._computeViewBox();\n this._cachedTickmarks = this._buildTickmarks();\n }\n\n if (arcInputsChanged || changed.has('headingAdvices')) {\n this._cachedAdvices = this._buildAdvices();\n }\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this._headingSp.dispose();\n }\n\n // ---------------------------------------------------------------------------\n // Angle mapping — maps compass degrees to arc positions\n // ---------------------------------------------------------------------------\n\n private _mapAngle(compassDeg: number): number {\n let diff = compassDeg - this.heading;\n if (diff > 180) diff -= 360;\n else if (diff < -180) diff += 360;\n return this.heading + diff * this._scale;\n }\n\n // ---------------------------------------------------------------------------\n // Areas — fixed 120° arc centered on heading (built in willUpdate)\n // ---------------------------------------------------------------------------\n\n // ---------------------------------------------------------------------------\n // Tickmarks — compass-degree labels at mapped arc positions\n // ---------------------------------------------------------------------------\n\n private _buildTickmarks(): Tickmark[] {\n const fov = this._halfFOV * 2;\n const {mainInterval, primaryInterval, secondaryInterval} =\n tickDensityForFOV(fov);\n const halfFov = this._halfFOV;\n const compassStart = this.heading - halfFov;\n const compassEnd = this.heading + halfFov;\n\n const tickmarks: Tickmark[] = [];\n const added = new Set<number>();\n\n const addTick = (\n arcAngle: number,\n type: TickmarkType,\n text?: string\n ): void => {\n const key = Math.round(arcAngle * 1000);\n if (added.has(key)) return;\n added.add(key);\n tickmarks.push({angle: arcAngle, type, text});\n };\n\n const step = secondaryInterval ?? primaryInterval;\n const firstTick = Math.ceil(compassStart / step) * step;\n\n for (\n let compassDeg = firstTick;\n compassDeg <= compassEnd;\n compassDeg += step\n ) {\n const norm = normalizeAngle(compassDeg);\n const arcAngle = this._mapAngle(compassDeg);\n const isMain = norm % mainInterval === 0;\n const isPrimary = norm % primaryInterval === 0;\n\n if (isMain) {\n addTick(arcAngle, TickmarkType.main, Math.round(norm).toString());\n } else if (isPrimary) {\n addTick(arcAngle, TickmarkType.primary);\n } else {\n addTick(arcAngle, TickmarkType.secondary);\n }\n }\n\n return tickmarks;\n }\n\n // ---------------------------------------------------------------------------\n // ViewBox\n // ---------------------------------------------------------------------------\n\n private _computeViewBox(): void {\n if (this.zoomToFitArc) {\n const targetSize = (176 + PADDING) * 2;\n const frame = computeZoomToFitArcFrame({\n areas: this._cachedAreas,\n outerRadius: OUTER_RING_RADIUS,\n innerRadius: INNER_RADIUS,\n extension: PADDING,\n targetSize,\n });\n this._radiusOffset = frame.radiusOffset;\n this._cachedViewBox = frame.viewBox;\n this._cachedArcFrame = frame;\n } else {\n this._radiusOffset = 0;\n const width = (176 + PADDING) * 2;\n this._cachedViewBox = `-${width / 2} -${width / 2} ${width} ${width}`;\n this._cachedArcFrame = undefined;\n }\n }\n\n // ---------------------------------------------------------------------------\n // North arrow — rendered in overlay at mapped 0° position\n // ---------------------------------------------------------------------------\n\n private _renderNorthArrow(rOff: number) {\n let northOffset = -this.heading;\n if (northOffset > 180) northOffset -= 360;\n else if (northOffset < -180) northOffset += 360;\n if (Math.abs(northOffset) > this._halfFOV) return nothing;\n\n const northArcAngle = this._mapAngle(0);\n const radius = OUTER_RING_RADIUS + rOff;\n return svg`\n <g transform=\"rotate(${northArcAngle}) translate(0, ${-radius})\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M-17.8457 24.984 0 0 17.8458 24.984C11.9868 24.3338 6.0324 24 0 24-6.0323 24-11.9867 24.3338-17.8457 24.984Z\"\n fill=\"var(--instrument-frame-tertiary-color)\"/>\n </g>\n `;\n }\n\n // ---------------------------------------------------------------------------\n // Priority & advice helpers\n // ---------------------------------------------------------------------------\n\n private _angleInRange(value: number, min: number, max: number): boolean {\n const v = normalizeAngle(value);\n const start = normalizeAngle(min);\n const end = normalizeAngle(max);\n return start <= end ? v >= start && v <= end : v >= start || v <= end;\n }\n\n private _buildAdvices(): AngleAdviceRaw[] {\n return this.headingAdvices.map(({minAngle, maxAngle, hinted, type}) => {\n const state = this._angleInRange(this.heading, minAngle, maxAngle)\n ? AdviceState.triggered\n : hinted\n ? AdviceState.hinted\n : AdviceState.regular;\n return {\n minAngle: this._mapAngle(minAngle),\n maxAngle: this._mapAngle(maxAngle),\n type,\n state,\n };\n });\n }\n\n private get _effectiveRotDegPerMin(): number {\n return this.rateOfTurnDegreesPerMinute ?? this.rotationsPerMinute;\n }\n\n private get _rotEndAngle(): number {\n const maxVal = this.rotMaxValue || 1;\n const barCompassDeg =\n (this._effectiveRotDegPerMin / maxVal) * ARC_HALF_EXTENT;\n return this._mapAngle(this.heading + barCompassDeg);\n }\n\n private priorityFor(element: CompassSectorPriorityElement): Priority {\n const selected = Array.isArray(this.priorityElements)\n ? this.priorityElements\n : [];\n return selected.includes(element) ? this.priority : Priority.regular;\n }\n\n /**\n * Vertical placement of the readout as a percentage of the host height.\n *\n * With `zoomToFitArc` the arc is reframed by `computeZoomToFitArcFrame`, whose\n * `radiusOffset`/`viewBox` depend on the arc's *absolute* orientation (which\n * cardinal axes its bounding box crosses), not just its bend. The arc itself\n * is always rotated back to the top, so it stays put on screen — but a\n * frame-derived offset would swing wildly as `heading` rotates the bbox around\n * the circle. So in zoom we use a fixed offset, which keeps the readout steady\n * under the (stationary) arc regardless of heading.\n *\n * Without zoom the viewBox is the fixed, origin-symmetric 120° framing, so the\n * geometry is orientation-independent: place the readout halfway down the inner\n * radius from the watch center toward the arc's inner edge.\n */\n private get _readoutTopPercent(): number {\n if (this.zoomToFitArc) {\n return 70;\n }\n const [, vy, , vh] = this._cachedViewBox.split(' ').map(Number);\n if (!vh || Number.isNaN(vy)) {\n return 50;\n }\n const anchorY = -INNER_RADIUS * 0.5;\n return Math.round(((anchorY - vy) / vh) * 1000) / 10;\n }\n\n // ---------------------------------------------------------------------------\n // Render\n // ---------------------------------------------------------------------------\n\n override render() {\n const rotation = -this.heading;\n const viewBox = this._cachedViewBox;\n const rOff = this._radiusOffset;\n\n const mappedCOG = this._mapAngle(this.courseOverGround);\n const mappedSetpoint =\n this.headingSetpoint != null\n ? this._mapAngle(this.headingSetpoint)\n : undefined;\n const mappedNewSetpoint =\n this.newHeadingSetpoint != null\n ? this._mapAngle(this.newHeadingSetpoint)\n : undefined;\n\n return html`\n <div class=\"container\">\n <obc-watch\n .touching=${this.touching}\n .padding=${PADDING}\n .advices=${this._cachedAdvices}\n .tickmarks=${this._cachedTickmarks}\n .tickmarkStyle=${TickmarkStyle.regular}\n .tickmarksInside=${this.tickmarksInside}\n .state=${this.state}\n .watchCircleType=${WATCH_TYPE}\n .northArrow=${false}\n .areas=${this._cachedAreas}\n .arcFrame=${this._cachedArcFrame}\n .zoomToFitArc=${this.zoomToFitArc}\n .tickFadeAngle=${this._arcHalfExtent * 0.2}\n .rotation=${rotation}\n .angleSetpoint=${mappedSetpoint}\n .newAngleSetpoint=${mappedNewSetpoint}\n .atAngleSetpoint=${this._headingSp.computeAtSetpoint(this.heading)}\n .angleSetpointAtZeroDeadband=${this.headingSetpointAtZeroDeadband}\n .setpointOverride=${this.headingSetpointOverride}\n .priority=${this.priority}\n .animateSetpoint=${this.animateSetpoint}\n .rotType=${this.rotType}\n .rotPosition=${this.rotPosition}\n .rotStartAngle=${this.heading}\n .rotEndAngle=${this._rotEndAngle}\n .rotPriority=${this.priorityFor(CompassSectorPriorityElement.rot)}\n .rotPortStarboard=${this.rotPortStarboard}\n .rotAtZeroDeadband=${this.rotAtZeroDeadband}\n .rateOfTurnDegreesPerMinute=${this.rateOfTurnDegreesPerMinute}\n .rotDotAnimationFactor=${this.rotDotAnimationFactor}\n .rotationsPerMinute=${this.rotationsPerMinute}\n >\n </obc-watch>\n <svg viewBox=\"${viewBox}\" transform=\"rotate(${rotation})\">\n <g transform=\"rotate(${this.heading})\">\n <line\n x1=\"0\"\n y1=\"${-(SCALE_INNER_RADIUS + rOff)}\"\n x2=\"0\"\n y2=\"${-(INNER_RADIUS + rOff)}\"\n stroke=\"var(--instrument-frame-tertiary-color)\"\n stroke-width=\"1\"\n vector-effect=\"non-scaling-stroke\"\n />\n </g>\n ${this._renderNorthArrow(rOff)}\n ${arrow(\n ArrowStyle.HDG,\n this.heading,\n this.priorityFor(CompassSectorPriorityElement.hdg),\n rOff\n )}\n ${arrow(\n ArrowStyle.COG,\n mappedCOG,\n this.priorityFor(CompassSectorPriorityElement.cog),\n rOff\n )}\n </svg>\n ${\n this.hasReadout\n ? html`<div\n class=\"readout\"\n style=\"top: ${this._readoutTopPercent}%\"\n >\n ${renderCenterReadouts([\n {\n value: this.heading,\n label: this.label,\n unit: this.unit,\n fractionDigits: this.fractionDigits,\n size: ReadoutSize.large,\n priority: this.priorityFor(\n CompassSectorPriorityElement.hdg\n ),\n centerValue: true,\n centerMeta: true,\n },\n ])}\n </div>`\n : nothing\n }\n </div>\n `;\n }\n\n static override styles = [\n unsafeCSS(instrumentReadoutStyle),\n centerReadoutStyles,\n unsafeCSS(componentStyle),\n ];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-compass-sector': ObcCompassSector;\n }\n}\n"],"names":["CompassSectorPriorityElement"],"mappings":"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"}
1
+ {"version":3,"file":"compass-sector.js","sources":["../../../src/navigation-instruments/compass-sector/compass-sector.ts"],"sourcesContent":["import {LitElement, PropertyValues, html, svg, unsafeCSS, nothing} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport {ResizeController} from '@lit-labs/observers/resize-controller.js';\nimport componentStyle from './compass-sector.css?inline';\nimport '../watch/watch.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 {Tickmark, TickmarkType, TickmarkStyle} from '../watch/tickmark.js';\nimport {arrow, ArrowStyle} from '../compass/arrow.js';\nimport {AdviceState, AngleAdvice, AngleAdviceRaw} from '../watch/advice.js';\nimport {\n WatchCircleType,\n WatchArea,\n OUTER_RING_RADIUS,\n innerRingRadiusFor,\n RotType,\n RotPosition,\n} from '../watch/watch.js';\nimport {SetpointBundle} from '../../svghelpers/setpoint-bundle.js';\nimport {\n computeRadialFrame,\n estimateLabelWidthPx,\n measureContainerPx,\n observeInnerBox,\n type RadialFrame,\n} from '../../svghelpers/radial-frame.js';\nimport {ROT_ZERO_DEADBAND_DEG} from '../rate-of-turn/rot-renderer.js';\nimport {customElement} from '../../decorator.js';\nimport {degToRad, normalizeAngle} from '../../svghelpers/math.js';\nimport {InstrumentState, Priority} from '../types.js';\nexport {RotType, RotPosition};\n\nexport enum CompassSectorPriorityElement {\n hdg = 'hdg',\n cog = 'cog',\n rot = 'rot',\n}\n\n/** The sector instruments' shared box: 40 units around the outer ring. */\nconst BASE_PADDING = 48;\n/**\n * Bottom crops, % of the 448 box, one per feature that hangs below the band.\n * Each leaves its lowest paint the same 40-unit margin the ring gets above —\n * `100 · (184 − y) / 448` — and `_clipBottom()` takes the deepest in play.\n * The band's own floor is the filleted inner corner at ±60°, y ≈ −47.\n */\nconst SECTOR_CLIP_BOTTOM = 51.5;\n/** ROT dots and bar ride the inner-circle track, ~5 units below the band. */\nconst SECTOR_CLIP_BOTTOM_ROT = 50.4;\n/** Inside labels sit under the inner ring, far below the band's floor. */\nconst SECTOR_CLIP_BOTTOM_INSIDE_LABELS = 47.3;\n/** The readout is px-sized, so it needs the room obc-gauge-radial's 180° sector reserves. */\nconst SECTOR_CLIP_BOTTOM_READOUT = 44;\n/**\n * Clearance the zoom flattens the arc out to. Zero puts the arc ends on the\n * side edges, which is the point of zooming; the un-zoomed 120° arc stops\n * well short of them because the box keeps the whole circle's width.\n */\nconst SECTOR_SIDE_MARGIN = 0;\nconst WATCH_TYPE = WatchCircleType.triple;\nconst INNER_RADIUS = innerRingRadiusFor(WATCH_TYPE);\n/** Half of the fixed 120° arc on the watch face. */\nconst ARC_HALF_EXTENT = 60;\nconst SCALE_INNER_RADIUS = innerRingRadiusFor(WatchCircleType.single);\n\ninterface TickDensity {\n mainInterval: number;\n primaryInterval: number;\n secondaryInterval: number | undefined;\n}\n\nfunction tickDensityForFOV(fov: number): TickDensity {\n if (fov <= 30) {\n return {mainInterval: 10, primaryInterval: 5, secondaryInterval: 1};\n } else if (fov <= 60) {\n return {mainInterval: 10, primaryInterval: 5, secondaryInterval: undefined};\n } else if (fov <= 120) {\n return {mainInterval: 30, primaryInterval: 10, secondaryInterval: 5};\n } else {\n return {mainInterval: 90, primaryInterval: 30, secondaryInterval: 10};\n }\n}\n\n/**\n * `<obc-compass-sector>` — Curved compass strip that auto‑scales to keep HDG and COG visible.\n *\n * Renders a fixed 120° arc of a triple‑ring compass face. The visible\n * compass range (field of view) adjusts automatically so that both the\n * heading (HDG) and course‑over‑ground (COG) arrows are always in view.\n * This is the radial equivalent of `<obc-compass-flat>`: the arc shape\n * never changes — only the scale (compass‑degrees per arc‑degree) changes.\n *\n * ## Features\n *\n * - **Fixed 120° arc**: The watch face is always a 120° sector (±60° from\n * center), identical in shape to `<obc-rot-sector>`.\n * - **FOV auto‑scaling**: The field of view widens when the HDG–COG\n * angular difference grows, compressing more compass degrees into the\n * fixed arc. Tickmark density adjusts automatically.\n * - **HDG / COG arrows**: Solid (HDG) arrow is always at the arc center.\n * Hollow (COG) arrow is positioned proportionally within the arc.\n * - **North arrow**: A gray triangle in the outer scale band indicates\n * north when it falls within the visible FOV.\n * - **Heading setpoint**: Optional setpoint marker with auto at‑setpoint\n * detection and confirm animation, positioned at the mapped arc angle.\n * - **Advice zones**: Pass `headingAdvices` to render caution/alert arcs,\n * mapped into the scaled arc.\n * - **Rate of turn**: Animated ROT indicator (dots or bar) spanning from\n * HDG to the mapped COG position, clipped to the arc.\n * - **Zoom to fit**: When `zoomToFitArc` is `true`, the fixed 120° arc is\n * enlarged to fill the available space.\n *\n * ## Usage Guidelines\n *\n * - Set `heading` and `courseOverGround` to sensor values in degrees.\n * - Adjust `minFOV` to control the minimum zoom level (default 30°).\n * - Enable `zoomToFitArc` to enlarge the arc to fill the viewport.\n * - For a full‑circle compass, use `<obc-compass>` instead.\n *\n * @availableWhen newHeadingSetpoint headingSetpoint!=null\n * @availableWhen atHeadingSetpoint headingSetpoint!=null && autoAtHeadingSetpoint==false\n * @availableWhen headingSetpointAtZeroDeadband headingSetpoint!=null\n * @availableWhen headingSetpointOverride headingSetpoint!=null\n * @availableWhen autoAtHeadingSetpoint headingSetpoint!=null\n * @availableWhen autoAtHeadingSetpointDeadband headingSetpoint!=null && autoAtHeadingSetpoint==true\n * @availableWhen animateSetpoint headingSetpoint!=null\n * @availableWhen touching headingSetpoint!=null\n * @availableWhen rotPosition rotType!=undefined\n * @property rateOfTurnDegreesPerMinute - Measured rate of turn in degrees per minute (positive = starboard).\n * Drives both the bar extent and (after multiplication by\n * `rotDotAnimationFactor`) the spinning dot animation. When `undefined`,\n * falls back to the deprecated `rotationsPerMinute`.\n * @availableWhen rateOfTurnDegreesPerMinute rotType!=undefined\n * @property rotDotAnimationFactor - Visual amplification applied only to the spinning dot animation\n * (not to the bar extent). Default `18` keeps the legacy visual feel\n * (≈1 rpm at 20°/min).\n * @availableWhen rotDotAnimationFactor rotType!=undefined\n * @availableWhen rotPortStarboard rotType!=undefined\n * @availableWhen rotAtZeroDeadband rotType==bar\n * @availableWhen priorityElements priority==enhanced\n * @property hasReadout - When `true`, shows a centered `<obc-readout>` under the arc displaying the\n * heading (label `HDG`, unit `DEG`). The value color follows the HDG entry in\n * `priorityElements`, matching the HDG arrow.\n * @property label - Readout label. Default `HDG`.\n * @availableWhen label hasReadout==true\n * @property unit - Readout unit. Default `DEG`.\n * @availableWhen unit hasReadout==true\n * @property fractionDigits - Number of fraction digits shown in the readout. Default `0`.\n * @availableWhen fractionDigits hasReadout==true\n * @property rotMaxValue - Bar-extent reference value in degrees per minute: the bar fills the full\n * ±`ARC_HALF_EXTENT` arc when the measured rate of turn reaches\n * ±`rotMaxValue`. The default `60` aligns with ES-TRIN 2025/1 Art. 3.02.\n * @availableWhen rotMaxValue rotType==bar\n * @stable\n */\n@customElement('obc-compass-sector')\nexport class ObcCompassSector extends LitElement {\n @property({type: Number}) heading = 0;\n @property({type: Number}) courseOverGround = 0;\n\n @property({type: Number}) headingSetpoint: number | null = null;\n @property({type: Number}) newHeadingSetpoint: number | undefined;\n @property({type: Boolean}) atHeadingSetpoint: boolean = false;\n @property({type: Number}) headingSetpointAtZeroDeadband: number = 0.5;\n @property({type: Boolean}) headingSetpointOverride: boolean = false;\n @property({type: Boolean, attribute: false}) autoAtHeadingSetpoint = true;\n @property({type: Number}) autoAtHeadingSetpointDeadband: number = 2;\n @property({type: Boolean}) animateSetpoint: boolean = false;\n @property({type: Boolean}) touching: boolean = false;\n @property({type: Array, attribute: false}) headingAdvices: AngleAdvice[] = [];\n\n @property({type: Number}) minFOV: number = 30;\n\n @property({type: String}) rotType: RotType | undefined;\n @property({type: String}) rotPosition: RotPosition = RotPosition.innerCircle;\n @property({type: Number}) rateOfTurnDegreesPerMinute: number | undefined;\n @property({type: Number}) rotDotAnimationFactor: number = 18;\n /**\n * @deprecated Use `rateOfTurnDegreesPerMinute` (and optionally\n * `rotDotAnimationFactor`) instead. Takes effect only when\n * `rateOfTurnDegreesPerMinute` is `undefined`.\n * @availableWhen rotType!=undefined && rateOfTurnDegreesPerMinute==undefined\n */\n @property({type: Number}) rotationsPerMinute: number = 1;\n @property({type: Number}) rotMaxValue: number = 60;\n @property({type: Boolean}) rotPortStarboard: boolean = false;\n @property({type: Number}) rotAtZeroDeadband: number = ROT_ZERO_DEADBAND_DEG;\n\n @property({type: String}) state: InstrumentState = InstrumentState.active;\n @property({type: String}) priority: Priority = Priority.regular;\n @property({type: Array, attribute: false})\n priorityElements: CompassSectorPriorityElement[] = [\n CompassSectorPriorityElement.hdg,\n ];\n @property({type: Boolean}) tickmarksInside: boolean = false;\n @property({type: Boolean}) zoomToFitArc: boolean = false;\n @property({type: Boolean}) hasReadout: boolean = false;\n @property({type: String}) label = 'HDG';\n @property({type: String}) unit = 'DEG';\n @property({type: Number}) fractionDigits = 0;\n\n private _headingSp = new SetpointBundle({\n angularWraparound: true,\n onAnimationEnd: () => this.requestUpdate(),\n });\n\n // Cached computed values — updated in willUpdate()\n private _halfFOV = 30;\n private _arcHalfExtent = ARC_HALF_EXTENT;\n private _scale = 1;\n private _cachedAreas: WatchArea[] = [];\n private _cachedTickmarks: Tickmark[] = [];\n private _cachedAdvices: AngleAdviceRaw[] = [];\n\n // The frame follows the host box, which no property change announces.\n private _resizeController = new ResizeController(this, {});\n\n private _aspectWidth = 448;\n private _aspectHeight = 217.28;\n\n override firstUpdated(changed: PropertyValues): void {\n super.firstUpdated(changed);\n observeInnerBox(this._resizeController, this.renderRoot);\n }\n\n override willUpdate(changed: PropertyValues): void {\n super.willUpdate(changed);\n this._headingSp.sync({\n setpoint: this.headingSetpoint ?? undefined,\n newSetpoint: this.newHeadingSetpoint,\n atSetpoint: this.atHeadingSetpoint,\n touching: this.touching,\n autoAtSetpoint: this.autoAtHeadingSetpoint,\n autoAtSetpointDeadband: this.autoAtHeadingSetpointDeadband,\n setpointAtZeroDeadband: this.headingSetpointAtZeroDeadband,\n setpointOverride: this.headingSetpointOverride,\n animateSetpoint: this.animateSetpoint,\n });\n\n const arcInputsChanged =\n changed.has('heading') ||\n changed.has('courseOverGround') ||\n changed.has('minFOV') ||\n changed.has('zoomToFitArc');\n\n if (arcInputsChanged) {\n let diff = this.courseOverGround - this.heading;\n if (diff > 180) diff -= 360;\n else if (diff < -180) diff += 360;\n const minFov = Math.max(1, this.minFOV);\n const MARGIN = 15;\n\n if (this.zoomToFitArc) {\n const needed = Math.max(minFov, Math.abs(diff) + MARGIN);\n if (needed <= ARC_HALF_EXTENT) {\n this._halfFOV = needed;\n this._arcHalfExtent = needed;\n this._scale = 1;\n } else {\n this._halfFOV = needed;\n this._arcHalfExtent = ARC_HALF_EXTENT;\n this._scale = ARC_HALF_EXTENT / needed;\n }\n } else {\n this._halfFOV = Math.max(minFov, Math.abs(diff));\n this._arcHalfExtent = ARC_HALF_EXTENT;\n this._scale = ARC_HALF_EXTENT / this._halfFOV;\n }\n\n this._cachedAreas = [\n {\n startAngle: this.heading - this._arcHalfExtent,\n endAngle: this.heading + this._arcHalfExtent,\n roundInsideCut: true,\n roundOutsideCut: true,\n },\n ];\n\n this._cachedTickmarks = this._buildTickmarks();\n }\n\n if (arcInputsChanged || changed.has('headingAdvices')) {\n this._cachedAdvices = this._buildAdvices();\n }\n }\n\n override updated(changed: PropertyValues): void {\n super.updated(changed);\n // The host IS the canvas, so its box follows the frame the render used.\n this.style.setProperty(\n '--obc-compass-sector-aspect',\n `${this._aspectWidth} / ${this._aspectHeight}`\n );\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this._headingSp.dispose();\n }\n\n // ---------------------------------------------------------------------------\n // Angle mapping — maps compass degrees to arc positions\n // ---------------------------------------------------------------------------\n\n private _mapAngle(compassDeg: number): number {\n let diff = compassDeg - this.heading;\n if (diff > 180) diff -= 360;\n else if (diff < -180) diff += 360;\n return this.heading + diff * this._scale;\n }\n\n // ---------------------------------------------------------------------------\n // Areas — fixed 120° arc centered on heading (built in willUpdate)\n // ---------------------------------------------------------------------------\n\n // ---------------------------------------------------------------------------\n // Tickmarks — compass-degree labels at mapped arc positions\n // ---------------------------------------------------------------------------\n\n private _buildTickmarks(): Tickmark[] {\n const fov = this._halfFOV * 2;\n const {mainInterval, primaryInterval, secondaryInterval} =\n tickDensityForFOV(fov);\n const halfFov = this._halfFOV;\n const compassStart = this.heading - halfFov;\n const compassEnd = this.heading + halfFov;\n\n const tickmarks: Tickmark[] = [];\n const added = new Set<number>();\n\n const addTick = (\n arcAngle: number,\n type: TickmarkType,\n text?: string\n ): void => {\n const key = Math.round(arcAngle * 1000);\n if (added.has(key)) return;\n added.add(key);\n tickmarks.push({angle: arcAngle, type, text});\n };\n\n const step = secondaryInterval ?? primaryInterval;\n const firstTick = Math.ceil(compassStart / step) * step;\n\n for (\n let compassDeg = firstTick;\n compassDeg <= compassEnd;\n compassDeg += step\n ) {\n const norm = normalizeAngle(compassDeg);\n const arcAngle = this._mapAngle(compassDeg);\n const isMain = norm % mainInterval === 0;\n const isPrimary = norm % primaryInterval === 0;\n\n if (isMain) {\n addTick(arcAngle, TickmarkType.main, Math.round(norm).toString());\n } else if (isPrimary) {\n addTick(arcAngle, TickmarkType.primary);\n } else {\n addTick(arcAngle, TickmarkType.secondary);\n }\n }\n\n return tickmarks;\n }\n\n // ---------------------------------------------------------------------------\n // ViewBox\n // ---------------------------------------------------------------------------\n\n /** Deepest crop the active features need, so none of them is shaved. */\n private _clipBottom(): number {\n const clips = [SECTOR_CLIP_BOTTOM];\n if (\n this.rotType !== undefined &&\n this.rotPosition === RotPosition.innerCircle\n ) {\n clips.push(SECTOR_CLIP_BOTTOM_ROT);\n }\n if (this.tickmarksInside) {\n clips.push(SECTOR_CLIP_BOTTOM_INSIDE_LABELS);\n }\n if (this.hasReadout) {\n clips.push(SECTOR_CLIP_BOTTOM_READOUT);\n }\n return Math.min(...clips);\n }\n\n /**\n * One frame per render, feeding both layers: the shared sector box cropped\n * to the arc. Zoom enlarges the arc rather than the window, so the window\n * only slides outward by the radius offset and the canvas holds still.\n */\n private _buildFrame(): RadialFrame {\n const frame = computeRadialFrame({\n basePadding: BASE_PADDING,\n labelWidthPx: this.tickmarksInside\n ? 0\n : estimateLabelWidthPx(this._cachedTickmarks.map((t) => t.text)),\n clips: {top: 0, bottom: this._clipBottom(), left: 0, right: 0},\n containerPx: measureContainerPx(this),\n });\n\n if (!this.zoomToFitArc) {\n return frame;\n }\n\n // Flatten the arc until its ends reach the same margin the 120° arc keeps,\n // measured off the window rather than the live heading — a frame fitted\n // where the arc currently points swings its box around the circle and the\n // arc drifts with it (#1152).\n const halfWidth = frame.width / 2 - SECTOR_SIDE_MARGIN;\n const sin = Math.sin(degToRad(this._arcHalfExtent));\n const radiusOffset = Math.max(0, halfWidth / sin - OUTER_RING_RADIUS);\n const y = frame.y - radiusOffset;\n return {\n ...frame,\n y,\n radiusOffset,\n viewBox: `${frame.x} ${y} ${frame.width} ${frame.height}`,\n };\n }\n\n // ---------------------------------------------------------------------------\n // North arrow — rendered in overlay at mapped 0° position\n // ---------------------------------------------------------------------------\n\n private _renderNorthArrow(rOff: number) {\n let northOffset = -this.heading;\n if (northOffset > 180) northOffset -= 360;\n else if (northOffset < -180) northOffset += 360;\n if (Math.abs(northOffset) > this._halfFOV) return nothing;\n\n const northArcAngle = this._mapAngle(0);\n const radius = OUTER_RING_RADIUS + rOff;\n return svg`\n <g transform=\"rotate(${northArcAngle}) translate(0, ${-radius})\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M-17.8457 24.984 0 0 17.8458 24.984C11.9868 24.3338 6.0324 24 0 24-6.0323 24-11.9867 24.3338-17.8457 24.984Z\"\n fill=\"var(--instrument-frame-tertiary-color)\"/>\n </g>\n `;\n }\n\n // ---------------------------------------------------------------------------\n // Priority & advice helpers\n // ---------------------------------------------------------------------------\n\n private _angleInRange(value: number, min: number, max: number): boolean {\n const v = normalizeAngle(value);\n const start = normalizeAngle(min);\n const end = normalizeAngle(max);\n return start <= end ? v >= start && v <= end : v >= start || v <= end;\n }\n\n private _buildAdvices(): AngleAdviceRaw[] {\n return this.headingAdvices.map(({minAngle, maxAngle, hinted, type}) => {\n const state = this._angleInRange(this.heading, minAngle, maxAngle)\n ? AdviceState.triggered\n : hinted\n ? AdviceState.hinted\n : AdviceState.regular;\n return {\n minAngle: this._mapAngle(minAngle),\n maxAngle: this._mapAngle(maxAngle),\n type,\n state,\n };\n });\n }\n\n private get _effectiveRotDegPerMin(): number {\n return this.rateOfTurnDegreesPerMinute ?? this.rotationsPerMinute;\n }\n\n private get _rotEndAngle(): number {\n const maxVal = this.rotMaxValue || 1;\n const barCompassDeg =\n (this._effectiveRotDegPerMin / maxVal) * ARC_HALF_EXTENT;\n return this._mapAngle(this.heading + barCompassDeg);\n }\n\n private priorityFor(element: CompassSectorPriorityElement): Priority {\n const selected = Array.isArray(this.priorityElements)\n ? this.priorityElements\n : [];\n return selected.includes(element) ? this.priority : Priority.regular;\n }\n\n /**\n * Vertical placement of the readout as a percentage of the frame height.\n *\n * The anchor sits halfway down the inner radius, below the arc's inner edge.\n * Zoom pushes that edge out by the radius offset, so the anchor follows it\n * and the gap under the arc reads the same in both modes.\n */\n private _readoutTopPercent(frame: RadialFrame): number {\n if (!frame.height) {\n return 50;\n }\n const anchorY = -INNER_RADIUS * 0.5 - frame.radiusOffset;\n return Math.round(((anchorY - frame.y) / frame.height) * 1000) / 10;\n }\n\n // ---------------------------------------------------------------------------\n // Render\n // ---------------------------------------------------------------------------\n\n override render() {\n const rotation = -this.heading;\n const frame = this._buildFrame();\n const viewBox = frame.viewBox;\n const rOff = frame.radiusOffset;\n // The overlay rotates its element box like obc-watch does, so it needs the\n // same pivot: the cropped frame's centre is not the compass centre.\n const pivotX = (-frame.x / frame.width) * 100;\n const pivotY = (-frame.y / frame.height) * 100;\n this._aspectWidth = frame.width;\n this._aspectHeight = frame.height;\n const tickmarks = frame.labelsHidden\n ? this._cachedTickmarks.map((t) => ({...t, text: undefined}))\n : this._cachedTickmarks;\n\n const mappedCOG = this._mapAngle(this.courseOverGround);\n const mappedSetpoint =\n this.headingSetpoint != null\n ? this._mapAngle(this.headingSetpoint)\n : undefined;\n const mappedNewSetpoint =\n this.newHeadingSetpoint != null\n ? this._mapAngle(this.newHeadingSetpoint)\n : undefined;\n\n return html`\n <div class=\"container\">\n <obc-watch\n .touching=${this.touching}\n .advices=${this._cachedAdvices}\n .tickmarks=${tickmarks}\n .tickmarkStyle=${TickmarkStyle.regular}\n .tickmarksInside=${this.tickmarksInside}\n .state=${this.state}\n .watchCircleType=${WATCH_TYPE}\n .northArrow=${false}\n .areas=${this._cachedAreas}\n .arcFrame=${frame}\n .tickFadeAngle=${this._arcHalfExtent * 0.2}\n .rotation=${rotation}\n .angleSetpoint=${mappedSetpoint}\n .newAngleSetpoint=${mappedNewSetpoint}\n .atAngleSetpoint=${this._headingSp.computeAtSetpoint(this.heading)}\n .angleSetpointAtZeroDeadband=${this.headingSetpointAtZeroDeadband}\n .setpointOverride=${this.headingSetpointOverride}\n .priority=${this.priority}\n .animateSetpoint=${this.animateSetpoint}\n .rotType=${this.rotType}\n .rotPosition=${this.rotPosition}\n .rotStartAngle=${this.heading}\n .rotEndAngle=${this._rotEndAngle}\n .rotPriority=${this.priorityFor(CompassSectorPriorityElement.rot)}\n .rotPortStarboard=${this.rotPortStarboard}\n .rotAtZeroDeadband=${this.rotAtZeroDeadband}\n .rateOfTurnDegreesPerMinute=${this.rateOfTurnDegreesPerMinute}\n .rotDotAnimationFactor=${this.rotDotAnimationFactor}\n .rotationsPerMinute=${this.rotationsPerMinute}\n >\n </obc-watch>\n <svg\n viewBox=\"${viewBox}\"\n transform=\"rotate(${rotation})\"\n style=\"transform-origin: ${pivotX}% ${pivotY}%\"\n >\n <g transform=\"rotate(${this.heading})\">\n <line\n x1=\"0\"\n y1=\"${-(SCALE_INNER_RADIUS + rOff)}\"\n x2=\"0\"\n y2=\"${-(INNER_RADIUS + rOff)}\"\n stroke=\"var(--instrument-frame-tertiary-color)\"\n stroke-width=\"1\"\n vector-effect=\"non-scaling-stroke\"\n />\n </g>\n ${this._renderNorthArrow(rOff)}\n ${arrow(\n ArrowStyle.HDG,\n this.heading,\n this.priorityFor(CompassSectorPriorityElement.hdg),\n rOff\n )}\n ${arrow(\n ArrowStyle.COG,\n mappedCOG,\n this.priorityFor(CompassSectorPriorityElement.cog),\n rOff\n )}\n </svg>\n ${\n this.hasReadout\n ? html`<div\n class=\"readout\"\n style=\"top: ${this._readoutTopPercent(frame)}%\"\n >\n ${renderCenterReadouts([\n {\n value: this.heading,\n label: this.label,\n unit: this.unit,\n fractionDigits: this.fractionDigits,\n size: ReadoutSize.large,\n priority: this.priorityFor(\n CompassSectorPriorityElement.hdg\n ),\n centerValue: true,\n centerMeta: true,\n },\n ])}\n </div>`\n : nothing\n }\n </div>\n `;\n }\n\n static override styles = [\n unsafeCSS(instrumentReadoutStyle),\n centerReadoutStyles,\n unsafeCSS(componentStyle),\n ];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-compass-sector': ObcCompassSector;\n }\n}\n"],"names":["CompassSectorPriorityElement"],"mappings":"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"}
@@ -27,12 +27,8 @@ const componentStyle = css`* {
27
27
 
28
28
  position: relative;
29
29
 
30
- /* The dial is the largest box of its sector's aspect ratio that fits inside
31
- *both* the available width and height of the (full-size) host. \`width: auto\`
32
- stretches the block to the host width, then \`aspect-ratio\` + \`max-height\`
33
- transfer the constraint back, shrinking it to fit a short host too — see
34
- issue #992. The host always fills its container, so the gauge can be
35
- positioned within the leftover space via the alignment classes below. */
30
+ /* The host always fills its container, so the gauge can be positioned within
31
+ the leftover space via the alignment classes below. */
36
32
  width: auto;
37
33
  height: auto;
38
34
  max-width: 100%;
@@ -1 +1 @@
1
- {"version":3,"file":"gauge-radial.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"gauge-radial.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,40 @@
1
+ import { css } from "lit";
2
+ const componentStyle = css`* {
3
+ -webkit-tap-highlight-color: transparent;
4
+ }
5
+
6
+ * {
7
+ box-sizing: border-box;
8
+ }
9
+
10
+ .container {
11
+ position: relative;
12
+ width: 100%;
13
+ height: 100%;
14
+ }
15
+
16
+ .container > * {
17
+ position: absolute;
18
+ top: 0;
19
+ left: 0;
20
+ width: 100%;
21
+ height: 100%;
22
+ }
23
+
24
+ :host {
25
+ display: block;
26
+ /* The element is the cropped canvas, not a square holding one, so the
27
+ aspect comes from the frame each render — the top crop and zoom both move
28
+ it. 448 / 269 is the un-zoomed box (448 wide × 448·(1 − 40%) tall); keep
29
+ in sync with the \`clips\` top in rudder.ts. */
30
+ width: auto;
31
+ height: auto;
32
+ max-width: 100%;
33
+ max-height: 100%;
34
+ aspect-ratio: var(--obc-rudder-aspect, 448 / 269);
35
+ }
36
+ `;
37
+ export {
38
+ componentStyle as default
39
+ };
40
+ //# sourceMappingURL=rudder.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rudder.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -96,6 +96,15 @@ export declare class ObcRudder extends ObcRudder_base {
96
96
  private _resizeController;
97
97
  firstUpdated(changed: PropertyValues): void;
98
98
  updated(changed: PropertyValues): void;
99
+ /**
100
+ * Radial reach of the needle path about the watch centre, and its half
101
+ * width — the zoomed arc's own box stops short of the inner end.
102
+ */
103
+ private static readonly NEEDLE_INNER_RADIUS;
104
+ private static readonly NEEDLE_OUTER_RADIUS;
105
+ private static readonly NEEDLE_HALF_WIDTH;
106
+ /** Box the zoomed frame must keep visible, in SVG units. */
107
+ private _needleIncludeBox;
99
108
  private get _needleTransform();
100
109
  getAngle(value: number): number;
101
110
  get barColor(): "var(--instrument-regular-secondary-color)" | "var(--instrument-enhanced-secondary-color)" | "var(--instrument-frame-tertiary-color)" | "var(--instrument-regular-tertiary-color)" | "var(--instrument-enhanced-tertiary-color)";
@@ -1 +1 @@
1
- {"version":3,"file":"rudder.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/rudder/rudder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,cAAc,EAAa,OAAO,EAAM,MAAM,KAAK,CAAC;AAGxE,OAAO,mBAAmB,CAAC;AAC3B,OAAO,EAAW,aAAa,EAAe,MAAM,sBAAsB,CAAC;AAE3E,OAAO,EAAC,eAAe,EAAE,QAAQ,EAAC,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAc,WAAW,EAAiB,MAAM,oBAAoB,CAAC;AAW5E,oBAAY,gBAAgB;IAC1B,GAAG,QAAQ;IACX,MAAM,WAAW;CAClB;;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AACH,qBACa,SAAU,SAAQ,cAAyB;IAC5B,KAAK,SAAK;IACV,OAAO,EAAE,gBAAgB,CAAwB;IACjD,QAAQ,SAAM;IACb,UAAU,EAAE,OAAO,CAAS;IAC5B,eAAe,EAAE,OAAO,CAAS;IAClC,KAAK,EAAE,eAAe,CAA0B;IAChD,QAAQ,EAAE,QAAQ,CAAoB;IACtC,aAAa,EAAE,aAAa,CAC9B;IACmB,OAAO,EAAE,WAAW,EAAE,CAAM;IAC5C,YAAY,EAAE,OAAO,CAAS;IAEzD,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IAEjC,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,MAAM,CAA0B;IAExC,oEAAoE;IACpE,OAAO,CAAC,eAAe,CAAS;IAEhC,OAAO,CAAC,iBAAiB,CAAkC;IAElD,YAAY,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAK3C,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAS/C,OAAO,KAAK,gBAAgB,GAM3B;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM;IAItB,IAAI,QAAQ,qOAsBX;IAED,YAAY;IA0BH,MAAM;IAmIf,OAAgB,MAAM,0BAkBpB;CACH;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,YAAY,EAAE,SAAS,CAAC;KACzB;CACF"}
1
+ {"version":3,"file":"rudder.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/rudder/rudder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,cAAc,EAAQ,OAAO,EAAiB,MAAM,KAAK,CAAC;AAI9E,OAAO,mBAAmB,CAAC;AAC3B,OAAO,EAAW,aAAa,EAAe,MAAM,sBAAsB,CAAC;AAE3E,OAAO,EAAC,eAAe,EAAE,QAAQ,EAAC,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAc,WAAW,EAAiB,MAAM,oBAAoB,CAAC;AAa5E,oBAAY,gBAAgB;IAC1B,GAAG,QAAQ;IACX,MAAM,WAAW;CAClB;;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AACH,qBACa,SAAU,SAAQ,cAAyB;IAC5B,KAAK,SAAK;IACV,OAAO,EAAE,gBAAgB,CAAwB;IACjD,QAAQ,SAAM;IACb,UAAU,EAAE,OAAO,CAAS;IAC5B,eAAe,EAAE,OAAO,CAAS;IAClC,KAAK,EAAE,eAAe,CAA0B;IAChD,QAAQ,EAAE,QAAQ,CAAoB;IACtC,aAAa,EAAE,aAAa,CAC9B;IACmB,OAAO,EAAE,WAAW,EAAE,CAAM;IAC5C,YAAY,EAAE,OAAO,CAAS;IAEzD,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IAEjC,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,MAAM,CAA0B;IAExC,oEAAoE;IACpE,OAAO,CAAC,eAAe,CAAS;IAEhC,OAAO,CAAC,iBAAiB,CAAkC;IAElD,YAAY,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAK3C,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAiB/C;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IACpD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAU;IACrD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAQ;IAEjD,4DAA4D;IAC5D,OAAO,CAAC,iBAAiB;IAiBzB,OAAO,KAAK,gBAAgB,GAM3B;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM;IAItB,IAAI,QAAQ,qOAsBX;IAED,YAAY;IA0BH,MAAM;IA8If,OAAgB,MAAM,0BAA6B;CACpD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,YAAY,EAAE,SAAS,CAAC;KACzB;CACF"}
@@ -1,5 +1,6 @@
1
- import { LitElement, nothing, svg, html, css } from "lit";
1
+ import { LitElement, nothing, svg, html, unsafeCSS } from "lit";
2
2
  import { property } from "lit/decorators.js";
3
+ import componentStyle from "./rudder.css.js";
3
4
  import { ResizeController } from "@lit-labs/observers/resize-controller.js";
4
5
  import { innerRingRadiusFor, WatchCircleType } from "../watch/watch.js";
5
6
  import { TickmarkStyle, TickmarkType } from "../watch/tickmark.js";
@@ -7,7 +8,9 @@ import { InstrumentState, Priority } from "../types.js";
7
8
  import { SetpointMixin } from "../../svghelpers/setpoint-mixin.js";
8
9
  import { AdviceState } from "../watch/advice.js";
9
10
  import { customElement } from "../../decorator.js";
10
- import { observeInnerBox, applyPinnedHostSize, computeRadialFrame, measureContainerPx, estimateLabelWidthPx } from "../../svghelpers/radial-frame.js";
11
+ import { degToRad } from "../../svghelpers/math.js";
12
+ import { ArcFrameFit } from "../../svghelpers/arc-frame.js";
13
+ import { observeInnerBox, applyPinnedHostSize, measureContainerPx, estimateLabelWidthPx, computeRadialFrame } from "../../svghelpers/radial-frame.js";
11
14
  var __defProp = Object.defineProperty;
12
15
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
13
16
  var __decorateClass = (decorators, target, key, kind) => {
@@ -46,12 +49,36 @@ let ObcRudder = class extends SetpointMixin(LitElement) {
46
49
  }
47
50
  updated(changed) {
48
51
  super.updated(changed);
52
+ const frame = this._frame;
53
+ if (frame) {
54
+ this.style.setProperty(
55
+ "--obc-rudder-aspect",
56
+ `${frame.width} / ${frame.height}`
57
+ );
58
+ }
49
59
  this._hostSizePinned = applyPinnedHostSize(
50
60
  this,
51
61
  this._frame,
52
62
  this._hostSizePinned
53
63
  );
54
64
  }
65
+ /** Box the zoomed frame must keep visible, in SVG units. */
66
+ _needleIncludeBox(radiusOffset) {
67
+ if (this.variant !== "needle") {
68
+ return void 0;
69
+ }
70
+ const rad = degToRad(this.getAngle(this.angle));
71
+ const u = { x: Math.sin(rad), y: -Math.cos(rad) };
72
+ const inner = ObcRudder.NEEDLE_INNER_RADIUS + radiusOffset;
73
+ const outer = ObcRudder.NEEDLE_OUTER_RADIUS + radiusOffset;
74
+ const w = ObcRudder.NEEDLE_HALF_WIDTH;
75
+ return {
76
+ xMin: Math.min(inner * u.x, outer * u.x) - w,
77
+ xMax: Math.max(inner * u.x, outer * u.x) + w,
78
+ yMin: Math.min(inner * u.y, outer * u.y) - w,
79
+ yMax: Math.max(inner * u.y, outer * u.y) + w
80
+ };
81
+ }
55
82
  get _needleTransform() {
56
83
  const rOff = this._radiusOffset;
57
84
  if (rOff > 0) {
@@ -165,16 +192,21 @@ let ObcRudder = class extends SetpointMixin(LitElement) {
165
192
  state
166
193
  };
167
194
  });
168
- const frame = computeRadialFrame({
195
+ const frameOptions = {
169
196
  basePadding: 48,
170
197
  labelWidthPx: this.tickmarksInside ? 0 : estimateLabelWidthPx(tickmarks.map((t) => t.text)),
171
198
  clips: this.zoomToFitArc ? void 0 : { top: 40, bottom: 0, left: 0, right: 0 },
172
199
  containerPx: measureContainerPx(this),
173
200
  faceDiameter: this.faceDiameter,
174
201
  zoomToFitArc: this.zoomToFitArc,
202
+ // The zoomed arc is flat; a square box would be mostly empty height.
203
+ zoomFit: ArcFrameFit.bbox,
175
204
  areas,
176
205
  innerRadius: innerRingRadiusFor(WatchCircleType.double)
177
- });
206
+ };
207
+ const probe = computeRadialFrame(frameOptions);
208
+ const zoomIncludeBox = this.zoomToFitArc ? this._needleIncludeBox(probe.radiusOffset) : void 0;
209
+ const frame = zoomIncludeBox ? computeRadialFrame({ ...frameOptions, zoomIncludeBox }) : probe;
178
210
  this._radiusOffset = frame.radiusOffset;
179
211
  this._frame = frame;
180
212
  const shownTickmarks = frame.labelsHidden ? tickmarks.map((t) => ({ ...t, text: void 0 })) : tickmarks;
@@ -205,25 +237,10 @@ let ObcRudder = class extends SetpointMixin(LitElement) {
205
237
  `;
206
238
  }
207
239
  };
208
- ObcRudder.styles = css`
209
- * {
210
- box-sizing: border-box;
211
- }
212
-
213
- .container {
214
- position: relative;
215
- width: 100%;
216
- height: 100%;
217
- }
218
-
219
- .container > * {
220
- position: absolute;
221
- top: 0;
222
- left: 0;
223
- width: 100%;
224
- height: 100%;
225
- }
226
- `;
240
+ ObcRudder.NEEDLE_INNER_RADIUS = -16.5;
241
+ ObcRudder.NEEDLE_OUTER_RADIUS = 160.65;
242
+ ObcRudder.NEEDLE_HALF_WIDTH = 16.5;
243
+ ObcRudder.styles = unsafeCSS(componentStyle);
227
244
  __decorateClass([
228
245
  property({ type: Number })
229
246
  ], ObcRudder.prototype, "angle", 2);
@@ -1 +1 @@
1
- {"version":3,"file":"rudder.js","sources":["../../../src/navigation-instruments/rudder/rudder.ts"],"sourcesContent":["import {LitElement, PropertyValues, css, html, nothing, svg} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport {ResizeController} from '@lit-labs/observers/resize-controller.js';\nimport '../watch/watch.js';\nimport {Tickmark, TickmarkStyle, TickmarkType} from '../watch/tickmark.js';\nimport {WatchCircleType, innerRingRadiusFor} from '../watch/watch.js';\nimport {InstrumentState, Priority} from '../types.js';\nimport {SetpointMixin} from '../../svghelpers/setpoint-mixin.js';\nimport {AdviceState, AngleAdvice, AngleAdviceRaw} from '../watch/advice.js';\nimport {customElement} from '../../decorator.js';\nimport {\n applyPinnedHostSize,\n computeRadialFrame,\n estimateLabelWidthPx,\n measureContainerPx,\n observeInnerBox,\n type RadialFrame,\n} from '../../svghelpers/radial-frame.js';\n\nexport enum ObcRudderVariant {\n Bar = 'bar',\n Needle = 'needle',\n}\n\n/**\n * `<obc-rudder>` — Half-circle rudder angle indicator.\n *\n * `ObcRudder` renders a semicircular gauge (40% top-clipped) that displays\n * the current rudder angle with a configurable bar or needle variant. The\n * gauge maps rudder angles to the lower arc of an `<obc-watch>` and overlays\n * a domain-specific needle when the `needle` variant is selected. It inherits\n * a full setpoint property bundle from {@link SetpointMixin}, including\n * auto at-setpoint detection, dual-marker adjustment preview, and deadband\n * tuning.\n *\n * ## Features\n *\n * - **Two display variants**: `bar` (filled arc from zero, default) and\n * `needle` (rotating pointer with silhouette stroke) via the `variant`\n * property.\n * - **Symmetric range**: The gauge spans ±`maxAngle` around the 180° center\n * (zero position at bottom).\n * - **State-aware colors**: Bar and needle colors adapt to the current\n * `InstrumentState` (active, loading, off) and `Priority` (enhanced, regular).\n * - **Setpoint via mixin**: `setpoint`, `newSetpoint`, `touching`,\n * `autoAtSetpointDeadband`, `setpointOverride`, and all other setpoint\n * properties are provided by `SetpointMixin` and forwarded to `<obc-watch>`.\n * - **Advice zones**: Pass an array of `AngleAdvice` objects to render\n * caution/alert arcs; triggered state is derived from whether the setpoint\n * falls inside the advice range.\n *\n * ## Usage Guidelines\n *\n * - Set `maxAngle` to define the symmetric ± range (default: 90°).\n * - Use `priority` to switch between regular and enhanced color palettes\n * (default: `Priority.regular`).\n * - Use `state` to control the instrument color palette.\n * - Enable `showLabels` to show numeric angle labels at tickmarks.\n * - Enable `tickmarksInside` to render tickmarks inside the ring.\n * - Choose `variant` to switch between bar and needle display.\n *\n * ## Best Practices\n *\n * - Prefer `SetpointMixin` properties (`setpoint`, `touching`, etc.) over\n * any legacy aliases — the mixin is the single source of truth.\n * - The top 40% is always clipped; overlay SVGs use the matching clipped\n * viewBox (`-224 -44.8 448 268.8`) for layer alignment.\n *\n * ## Example\n *\n * ```html\n * <obc-rudder\n * angle=\"12\"\n * maxAngle=\"45\"\n * variant=\"needle\"\n * state=\"in-command\"\n * showLabels\n * setpoint=\"15\"\n * ></obc-rudder>\n * ```\n *\n * @element obc-rudder\n *\n * @property tickmarksInside - Whether to render tickmarks inside the ring.\n * @property faceDiameter - Outer-ring diameter in CSS pixels. When set, the instrument renders at a\n * fixed intrinsic size derived from the ring, arc shape and label reserve —\n * so instruments sharing the same value have identical ring circumference\n * regardless of label width or arc extent (like obc-donut-chart's\n * fixedHeight). When unset (default), the instrument fills its container.\n * @stable\n */\n@customElement('obc-rudder')\nexport class ObcRudder extends SetpointMixin(LitElement) {\n @property({type: Number}) angle = 0;\n @property({type: String}) variant: ObcRudderVariant = ObcRudderVariant.Bar;\n @property({type: Number}) maxAngle = 90;\n @property({type: Boolean}) showLabels: boolean = false;\n @property({type: Boolean}) tickmarksInside: boolean = false;\n @property({type: String}) state: InstrumentState = InstrumentState.active;\n @property({type: String}) priority: Priority = Priority.regular;\n @property({type: String}) tickmarkStyle: TickmarkStyle =\n TickmarkStyle.regular;\n @property({type: Array, attribute: false}) advices: AngleAdvice[] = [];\n @property({type: Boolean}) zoomToFitArc: boolean = false;\n @property({type: Number, attribute: 'face-diameter'})\n faceDiameter: number | undefined;\n\n private _radiusOffset = 0;\n private _frame: RadialFrame | undefined;\n\n /** Whether the host size styles were set by applyPinnedHostSize. */\n private _hostSizePinned = false;\n\n private _resizeController = new ResizeController(this, {});\n\n override firstUpdated(changed: PropertyValues): void {\n super.firstUpdated(changed);\n observeInnerBox(this._resizeController, this.renderRoot);\n }\n\n override updated(changed: PropertyValues): void {\n super.updated(changed);\n this._hostSizePinned = applyPinnedHostSize(\n this,\n this._frame,\n this._hostSizePinned\n );\n }\n\n private get _needleTransform(): string {\n const rOff = this._radiusOffset;\n if (rOff > 0) {\n return `translate(-256, -256) rotate(${-this.angle} 256 256) translate(0, ${rOff})`;\n }\n return `translate(-256, -256) rotate(${-this.angle} 256 256)`;\n }\n\n getAngle(value: number) {\n return 180 - value;\n }\n\n get barColor() {\n if (this.variant === ObcRudderVariant.Needle) {\n if (\n this.state === InstrumentState.loading ||\n this.state === InstrumentState.off\n ) {\n return 'var(--instrument-frame-tertiary-color)';\n }\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-tertiary-color)'\n : 'var(--instrument-regular-tertiary-color)';\n } else {\n if (\n this.state === InstrumentState.loading ||\n this.state === InstrumentState.off\n ) {\n return 'var(--instrument-frame-tertiary-color)';\n }\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n }\n\n renderNeedle() {\n if (this.variant === ObcRudderVariant.Bar) {\n return nothing;\n }\n let color: string;\n if (\n this.state === InstrumentState.loading ||\n this.state === InstrumentState.off\n ) {\n color = 'var(--instrument-frame-tertiary-color)';\n } else {\n color =\n this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n return svg`\n <path\n transform=\"${this._needleTransform}\"\n d=\"M260.462 411.447C259.81 416.73 251.933 416.645 251.514 411.191L239.826 259.24C239.618 258.192 239.508 257.109 239.508 256C239.508 255.764 239.514 255.528 239.524 255.294L239.503 255.039L239.462 254.5H239.576C240.334 246.09 247.401 239.5 256.008 239.5C264.615 239.5 271.681 246.09 272.439 254.5H272.542L272.5 255.039L272.488 255.196C272.501 255.462 272.508 255.731 272.508 256C272.508 257.144 272.391 258.261 272.169 259.339L260.487 411.191L260.462 411.447Z\"\n fill=\"${color}\"\n stroke=\"var(--border-silhouette-color)\"\n />\n `;\n }\n\n override render() {\n const maxAngle = Math.max(2, this.maxAngle);\n const areas = [\n {\n startAngle: 180 - maxAngle,\n endAngle: 180 + maxAngle,\n roundInsideCut: true,\n roundOutsideCut: true,\n },\n ];\n\n const barAreas = [\n {\n startAngle: this.getAngle(0),\n endAngle: this.getAngle(this.angle),\n fillColor: this.barColor,\n },\n ];\n\n const setpointAngle =\n this.setpoint !== undefined ? 180 - this.setpoint : undefined;\n\n const tickmarks: Tickmark[] = [\n {\n angle: 180,\n type: TickmarkType.primary,\n text: this.showLabels ? '0' : undefined,\n },\n {\n angle: 180,\n type: TickmarkType.zeroLineThick,\n color: this.barColor,\n },\n {\n angle: 180 - maxAngle,\n type: TickmarkType.secondary,\n text: this.showLabels ? maxAngle.toFixed(0) : undefined,\n },\n {\n angle: 180 + maxAngle,\n type: TickmarkType.secondary,\n text: this.showLabels ? (-maxAngle).toFixed(0) : undefined,\n },\n ];\n\n let helpAngle: null | number = null;\n if (maxAngle > 70) {\n helpAngle = 45;\n } else if (maxAngle > 50) {\n helpAngle = 30;\n } else if (maxAngle > 40) {\n helpAngle = 22.5;\n }\n\n if (helpAngle !== null) {\n tickmarks.push({angle: 180 - helpAngle, type: TickmarkType.primary});\n tickmarks.push({angle: 180 + helpAngle, type: TickmarkType.primary});\n }\n\n const advices = this.advices.map<AngleAdviceRaw>((adv): AngleAdviceRaw => {\n const startAngle = 180 - adv.maxAngle;\n const endAngle = 180 - adv.minAngle;\n const isInRange =\n this.setpoint !== undefined &&\n this.setpoint >= adv.minAngle &&\n this.setpoint <= adv.maxAngle;\n let state;\n if (isInRange) {\n state = AdviceState.triggered;\n } else if (adv.hinted) {\n state = AdviceState.hinted;\n } else {\n state = AdviceState.regular;\n }\n return {\n minAngle: startAngle,\n maxAngle: endAngle,\n type: adv.type,\n state: state,\n };\n });\n\n const frame = computeRadialFrame({\n basePadding: 48,\n labelWidthPx: this.tickmarksInside\n ? 0\n : estimateLabelWidthPx(tickmarks.map((t) => t.text)),\n clips: this.zoomToFitArc\n ? undefined\n : {top: 40, bottom: 0, left: 0, right: 0},\n containerPx: measureContainerPx(this),\n faceDiameter: this.faceDiameter,\n zoomToFitArc: this.zoomToFitArc,\n areas,\n innerRadius: innerRingRadiusFor(WatchCircleType.double),\n });\n this._radiusOffset = frame.radiusOffset;\n this._frame = frame;\n const shownTickmarks = frame.labelsHidden\n ? tickmarks.map((t) => ({...t, text: undefined}))\n : tickmarks;\n const overlayViewBox = frame.viewBox;\n\n return html`\n <div class=\"container\">\n <obc-watch\n .touching=${this.touching}\n .arcFrame=${frame}\n .areas=${areas}\n .angleSetpoint=${setpointAngle}\n .newAngleSetpoint=${\n this.newSetpoint !== undefined ? 180 - this.newSetpoint : undefined\n }\n .atAngleSetpoint=${this.computeAtSetpoint(this.angle)}\n .angleSetpointAtZeroDeadband=${this.setpointAtZeroDeadband}\n .setpointOverride=${this.setpointOverride}\n .animateSetpoint=${this.animateSetpoint}\n .tickmarks=${shownTickmarks}\n .tickmarksInside=${this.tickmarksInside}\n .tickmarkStyle=${this.tickmarkStyle}\n .watchCircleType=${WatchCircleType.double}\n .barAreas=${barAreas}\n .state=${this.state}\n .priority=${this.priority}\n .advices=${advices}\n ></obc-watch>\n <svg viewBox=\"${overlayViewBox}\">${this.renderNeedle()}</svg>\n </div>\n `;\n }\n\n static override styles = 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}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-rudder': ObcRudder;\n }\n}\n"],"names":["ObcRudderVariant"],"mappings":"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"}
1
+ {"version":3,"file":"rudder.js","sources":["../../../src/navigation-instruments/rudder/rudder.ts"],"sourcesContent":["import {LitElement, PropertyValues, html, nothing, svg, unsafeCSS} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport componentStyle from './rudder.css?inline';\nimport {ResizeController} from '@lit-labs/observers/resize-controller.js';\nimport '../watch/watch.js';\nimport {Tickmark, TickmarkStyle, TickmarkType} from '../watch/tickmark.js';\nimport {WatchCircleType, innerRingRadiusFor} from '../watch/watch.js';\nimport {InstrumentState, Priority} from '../types.js';\nimport {SetpointMixin} from '../../svghelpers/setpoint-mixin.js';\nimport {AdviceState, AngleAdvice, AngleAdviceRaw} from '../watch/advice.js';\nimport {customElement} from '../../decorator.js';\nimport {degToRad} from '../../svghelpers/math.js';\nimport {ArcFrameFit} from '../../svghelpers/arc-frame.js';\nimport {\n applyPinnedHostSize,\n computeRadialFrame,\n estimateLabelWidthPx,\n measureContainerPx,\n observeInnerBox,\n type RadialFrame,\n} from '../../svghelpers/radial-frame.js';\n\nexport enum ObcRudderVariant {\n Bar = 'bar',\n Needle = 'needle',\n}\n\n/**\n * `<obc-rudder>` — Half-circle rudder angle indicator.\n *\n * `ObcRudder` renders a semicircular gauge (40% top-clipped) that displays\n * the current rudder angle with a configurable bar or needle variant. The\n * gauge maps rudder angles to the lower arc of an `<obc-watch>` and overlays\n * a domain-specific needle when the `needle` variant is selected. It inherits\n * a full setpoint property bundle from {@link SetpointMixin}, including\n * auto at-setpoint detection, dual-marker adjustment preview, and deadband\n * tuning.\n *\n * ## Features\n *\n * - **Two display variants**: `bar` (filled arc from zero, default) and\n * `needle` (rotating pointer with silhouette stroke) via the `variant`\n * property.\n * - **Symmetric range**: The gauge spans ±`maxAngle` around the 180° center\n * (zero position at bottom).\n * - **State-aware colors**: Bar and needle colors adapt to the current\n * `InstrumentState` (active, loading, off) and `Priority` (enhanced, regular).\n * - **Setpoint via mixin**: `setpoint`, `newSetpoint`, `touching`,\n * `autoAtSetpointDeadband`, `setpointOverride`, and all other setpoint\n * properties are provided by `SetpointMixin` and forwarded to `<obc-watch>`.\n * - **Advice zones**: Pass an array of `AngleAdvice` objects to render\n * caution/alert arcs; triggered state is derived from whether the setpoint\n * falls inside the advice range.\n *\n * ## Usage Guidelines\n *\n * - Set `maxAngle` to define the symmetric ± range (default: 90°).\n * - Use `priority` to switch between regular and enhanced color palettes\n * (default: `Priority.regular`).\n * - Use `state` to control the instrument color palette.\n * - Enable `showLabels` to show numeric angle labels at tickmarks.\n * - Enable `tickmarksInside` to render tickmarks inside the ring.\n * - Choose `variant` to switch between bar and needle display.\n *\n * ## Best Practices\n *\n * - Prefer `SetpointMixin` properties (`setpoint`, `touching`, etc.) over\n * any legacy aliases — the mixin is the single source of truth.\n * - The top 40% is always clipped; overlay SVGs use the matching clipped\n * viewBox (`-224 -44.8 448 268.8`) for layer alignment.\n *\n * ## Example\n *\n * ```html\n * <obc-rudder\n * angle=\"12\"\n * maxAngle=\"45\"\n * variant=\"needle\"\n * state=\"in-command\"\n * showLabels\n * setpoint=\"15\"\n * ></obc-rudder>\n * ```\n *\n * @element obc-rudder\n *\n * @property tickmarksInside - Whether to render tickmarks inside the ring.\n * @property faceDiameter - Outer-ring diameter in CSS pixels. When set, the instrument renders at a\n * fixed intrinsic size derived from the ring, arc shape and label reserve —\n * so instruments sharing the same value have identical ring circumference\n * regardless of label width or arc extent (like obc-donut-chart's\n * fixedHeight). When unset (default), the instrument fills its container.\n * @stable\n */\n@customElement('obc-rudder')\nexport class ObcRudder extends SetpointMixin(LitElement) {\n @property({type: Number}) angle = 0;\n @property({type: String}) variant: ObcRudderVariant = ObcRudderVariant.Bar;\n @property({type: Number}) maxAngle = 90;\n @property({type: Boolean}) showLabels: boolean = false;\n @property({type: Boolean}) tickmarksInside: boolean = false;\n @property({type: String}) state: InstrumentState = InstrumentState.active;\n @property({type: String}) priority: Priority = Priority.regular;\n @property({type: String}) tickmarkStyle: TickmarkStyle =\n TickmarkStyle.regular;\n @property({type: Array, attribute: false}) advices: AngleAdvice[] = [];\n @property({type: Boolean}) zoomToFitArc: boolean = false;\n @property({type: Number, attribute: 'face-diameter'})\n faceDiameter: number | undefined;\n\n private _radiusOffset = 0;\n private _frame: RadialFrame | undefined;\n\n /** Whether the host size styles were set by applyPinnedHostSize. */\n private _hostSizePinned = false;\n\n private _resizeController = new ResizeController(this, {});\n\n override firstUpdated(changed: PropertyValues): void {\n super.firstUpdated(changed);\n observeInnerBox(this._resizeController, this.renderRoot);\n }\n\n override updated(changed: PropertyValues): void {\n super.updated(changed);\n // The host IS the canvas, so its box follows the frame the render used.\n const frame = this._frame;\n if (frame) {\n this.style.setProperty(\n '--obc-rudder-aspect',\n `${frame.width} / ${frame.height}`\n );\n }\n this._hostSizePinned = applyPinnedHostSize(\n this,\n this._frame,\n this._hostSizePinned\n );\n }\n\n /**\n * Radial reach of the needle path about the watch centre, and its half\n * width — the zoomed arc's own box stops short of the inner end.\n */\n private static readonly NEEDLE_INNER_RADIUS = -16.5;\n private static readonly NEEDLE_OUTER_RADIUS = 160.65;\n private static readonly NEEDLE_HALF_WIDTH = 16.5;\n\n /** Box the zoomed frame must keep visible, in SVG units. */\n private _needleIncludeBox(radiusOffset: number) {\n if (this.variant !== ObcRudderVariant.Needle) {\n return undefined;\n }\n const rad = degToRad(this.getAngle(this.angle));\n const u = {x: Math.sin(rad), y: -Math.cos(rad)};\n const inner = ObcRudder.NEEDLE_INNER_RADIUS + radiusOffset;\n const outer = ObcRudder.NEEDLE_OUTER_RADIUS + radiusOffset;\n const w = ObcRudder.NEEDLE_HALF_WIDTH;\n return {\n xMin: Math.min(inner * u.x, outer * u.x) - w,\n xMax: Math.max(inner * u.x, outer * u.x) + w,\n yMin: Math.min(inner * u.y, outer * u.y) - w,\n yMax: Math.max(inner * u.y, outer * u.y) + w,\n };\n }\n\n private get _needleTransform(): string {\n const rOff = this._radiusOffset;\n if (rOff > 0) {\n return `translate(-256, -256) rotate(${-this.angle} 256 256) translate(0, ${rOff})`;\n }\n return `translate(-256, -256) rotate(${-this.angle} 256 256)`;\n }\n\n getAngle(value: number) {\n return 180 - value;\n }\n\n get barColor() {\n if (this.variant === ObcRudderVariant.Needle) {\n if (\n this.state === InstrumentState.loading ||\n this.state === InstrumentState.off\n ) {\n return 'var(--instrument-frame-tertiary-color)';\n }\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-tertiary-color)'\n : 'var(--instrument-regular-tertiary-color)';\n } else {\n if (\n this.state === InstrumentState.loading ||\n this.state === InstrumentState.off\n ) {\n return 'var(--instrument-frame-tertiary-color)';\n }\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n }\n\n renderNeedle() {\n if (this.variant === ObcRudderVariant.Bar) {\n return nothing;\n }\n let color: string;\n if (\n this.state === InstrumentState.loading ||\n this.state === InstrumentState.off\n ) {\n color = 'var(--instrument-frame-tertiary-color)';\n } else {\n color =\n this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n return svg`\n <path\n transform=\"${this._needleTransform}\"\n d=\"M260.462 411.447C259.81 416.73 251.933 416.645 251.514 411.191L239.826 259.24C239.618 258.192 239.508 257.109 239.508 256C239.508 255.764 239.514 255.528 239.524 255.294L239.503 255.039L239.462 254.5H239.576C240.334 246.09 247.401 239.5 256.008 239.5C264.615 239.5 271.681 246.09 272.439 254.5H272.542L272.5 255.039L272.488 255.196C272.501 255.462 272.508 255.731 272.508 256C272.508 257.144 272.391 258.261 272.169 259.339L260.487 411.191L260.462 411.447Z\"\n fill=\"${color}\"\n stroke=\"var(--border-silhouette-color)\"\n />\n `;\n }\n\n override render() {\n const maxAngle = Math.max(2, this.maxAngle);\n const areas = [\n {\n startAngle: 180 - maxAngle,\n endAngle: 180 + maxAngle,\n roundInsideCut: true,\n roundOutsideCut: true,\n },\n ];\n\n const barAreas = [\n {\n startAngle: this.getAngle(0),\n endAngle: this.getAngle(this.angle),\n fillColor: this.barColor,\n },\n ];\n\n const setpointAngle =\n this.setpoint !== undefined ? 180 - this.setpoint : undefined;\n\n const tickmarks: Tickmark[] = [\n {\n angle: 180,\n type: TickmarkType.primary,\n text: this.showLabels ? '0' : undefined,\n },\n {\n angle: 180,\n type: TickmarkType.zeroLineThick,\n color: this.barColor,\n },\n {\n angle: 180 - maxAngle,\n type: TickmarkType.secondary,\n text: this.showLabels ? maxAngle.toFixed(0) : undefined,\n },\n {\n angle: 180 + maxAngle,\n type: TickmarkType.secondary,\n text: this.showLabels ? (-maxAngle).toFixed(0) : undefined,\n },\n ];\n\n let helpAngle: null | number = null;\n if (maxAngle > 70) {\n helpAngle = 45;\n } else if (maxAngle > 50) {\n helpAngle = 30;\n } else if (maxAngle > 40) {\n helpAngle = 22.5;\n }\n\n if (helpAngle !== null) {\n tickmarks.push({angle: 180 - helpAngle, type: TickmarkType.primary});\n tickmarks.push({angle: 180 + helpAngle, type: TickmarkType.primary});\n }\n\n const advices = this.advices.map<AngleAdviceRaw>((adv): AngleAdviceRaw => {\n const startAngle = 180 - adv.maxAngle;\n const endAngle = 180 - adv.minAngle;\n const isInRange =\n this.setpoint !== undefined &&\n this.setpoint >= adv.minAngle &&\n this.setpoint <= adv.maxAngle;\n let state;\n if (isInRange) {\n state = AdviceState.triggered;\n } else if (adv.hinted) {\n state = AdviceState.hinted;\n } else {\n state = AdviceState.regular;\n }\n return {\n minAngle: startAngle,\n maxAngle: endAngle,\n type: adv.type,\n state: state,\n };\n });\n\n const frameOptions = {\n basePadding: 48,\n labelWidthPx: this.tickmarksInside\n ? 0\n : estimateLabelWidthPx(tickmarks.map((t) => t.text)),\n clips: this.zoomToFitArc\n ? undefined\n : {top: 40, bottom: 0, left: 0, right: 0},\n containerPx: measureContainerPx(this),\n faceDiameter: this.faceDiameter,\n zoomToFitArc: this.zoomToFitArc,\n // The zoomed arc is flat; a square box would be mostly empty height.\n zoomFit: ArcFrameFit.bbox,\n areas,\n innerRadius: innerRingRadiusFor(WatchCircleType.double),\n };\n // `includeBox` never feeds the radius search, so the offset the first pass\n // returns is the one the needle box is drawn against.\n const probe = computeRadialFrame(frameOptions);\n const zoomIncludeBox = this.zoomToFitArc\n ? this._needleIncludeBox(probe.radiusOffset)\n : undefined;\n const frame = zoomIncludeBox\n ? computeRadialFrame({...frameOptions, zoomIncludeBox})\n : probe;\n this._radiusOffset = frame.radiusOffset;\n this._frame = frame;\n const shownTickmarks = frame.labelsHidden\n ? tickmarks.map((t) => ({...t, text: undefined}))\n : tickmarks;\n const overlayViewBox = frame.viewBox;\n\n return html`\n <div class=\"container\">\n <obc-watch\n .touching=${this.touching}\n .arcFrame=${frame}\n .areas=${areas}\n .angleSetpoint=${setpointAngle}\n .newAngleSetpoint=${\n this.newSetpoint !== undefined ? 180 - this.newSetpoint : undefined\n }\n .atAngleSetpoint=${this.computeAtSetpoint(this.angle)}\n .angleSetpointAtZeroDeadband=${this.setpointAtZeroDeadband}\n .setpointOverride=${this.setpointOverride}\n .animateSetpoint=${this.animateSetpoint}\n .tickmarks=${shownTickmarks}\n .tickmarksInside=${this.tickmarksInside}\n .tickmarkStyle=${this.tickmarkStyle}\n .watchCircleType=${WatchCircleType.double}\n .barAreas=${barAreas}\n .state=${this.state}\n .priority=${this.priority}\n .advices=${advices}\n ></obc-watch>\n <svg viewBox=\"${overlayViewBox}\">${this.renderNeedle()}</svg>\n </div>\n `;\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-rudder': ObcRudder;\n }\n}\n"],"names":["ObcRudderVariant"],"mappings":"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"}
@@ -15,6 +15,12 @@ svg {
15
15
  display: block;
16
16
  }
17
17
 
18
+ svg.cropped {
19
+ /* A cropped frame paints its arc outside the viewBox before \`rotation\`
20
+ swings it into view; the host's overflow rule is what clips. */
21
+ overflow: visible;
22
+ }
23
+
18
24
  .label {
19
25
  font-family: var(--global-typography-font-family);
20
26
  font-weight: var(--global-typography-ui-body-font-weight);
@@ -1 +1 @@
1
- {"version":3,"file":"watch.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"watch.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/watch/watch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/watch/watch.ts"],"names":[],"mappings":"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"}
@@ -618,6 +618,8 @@ let ObcWatch = class extends LitElement {
618
618
  render() {
619
619
  let width;
620
620
  let height;
621
+ let frameX;
622
+ let frameY;
621
623
  let viewBox;
622
624
  if (this.arcFrame) {
623
625
  this._rOff = this.arcFrame.radiusOffset;
@@ -625,6 +627,8 @@ let ObcWatch = class extends LitElement {
625
627
  this._ownFrame = void 0;
626
628
  width = this.arcFrame.width;
627
629
  height = this.arcFrame.height;
630
+ frameX = this.arcFrame.x;
631
+ frameY = this.arcFrame.y;
628
632
  viewBox = this.arcFrame.viewBox;
629
633
  } else {
630
634
  const frame = computeRadialFrame({
@@ -647,10 +651,15 @@ let ObcWatch = class extends LitElement {
647
651
  this._ownFrame = frame;
648
652
  width = frame.width;
649
653
  height = frame.height;
654
+ frameX = frame.x;
655
+ frameY = frame.y;
650
656
  viewBox = frame.viewBox;
651
657
  }
652
658
  const rOff = this._rOff;
653
659
  const scale = this.getScale({ width, height });
660
+ const pivotX = width > 0 ? -frameX / width * 100 : 50;
661
+ const pivotY = height > 0 ? -frameY / height * 100 : 50;
662
+ const cropped = pivotX !== 50 || pivotY !== 50;
654
663
  const angleSetpoint = this.renderSetpoint();
655
664
  const textRadius = this.tickmarksInside ? this._bandRadius(this.innerRingRadius) : this._bandRadius(OUTER_RING_RADIUS);
656
665
  const maxDigits = Math.max(
@@ -715,10 +724,11 @@ let ObcWatch = class extends LitElement {
715
724
  }) : nothing;
716
725
  return html`
717
726
  <svg
727
+ class=${cropped ? "cropped" : nothing}
718
728
  width="100%"
719
729
  height="100%"
720
730
  viewBox=${viewBox}
721
- style="--scale: ${scale}"
731
+ style="--scale: ${scale}; transform-origin: ${pivotX}% ${pivotY}%"
722
732
  transform="rotate(${this.rotation ?? 0})"
723
733
  >
724
734
  ${this.watchCircle()} ${this.renderBars()}