@oicl/openbridge-webcomponents 2.0.0-next.101 → 2.0.0-next.103

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 (77) hide show
  1. package/bundle/openbridge-webcomponents.bundle.js +580 -143
  2. package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
  3. package/custom-elements.json +629 -407
  4. package/dist/bars-graphs/donut-chart/donut-chart.d.ts +18 -16
  5. package/dist/bars-graphs/donut-chart/donut-chart.d.ts.map +1 -1
  6. package/dist/bars-graphs/donut-chart/donut-chart.js.map +1 -1
  7. package/dist/bars-graphs/pie-chart/pie-chart.d.ts +14 -12
  8. package/dist/bars-graphs/pie-chart/pie-chart.d.ts.map +1 -1
  9. package/dist/bars-graphs/pie-chart/pie-chart.js.map +1 -1
  10. package/dist/bars-graphs/polar-chart/polar-chart.d.ts +19 -16
  11. package/dist/bars-graphs/polar-chart/polar-chart.d.ts.map +1 -1
  12. package/dist/bars-graphs/polar-chart/polar-chart.js.map +1 -1
  13. package/dist/bars-graphs/radial-bar-chart/radial-bar-chart.d.ts +8 -8
  14. package/dist/bars-graphs/radial-bar-chart/radial-bar-chart.d.ts.map +1 -1
  15. package/dist/bars-graphs/radial-bar-chart/radial-bar-chart.js.map +1 -1
  16. package/dist/building-blocks/chart-line/chart-line-base.d.ts +8 -25
  17. package/dist/building-blocks/chart-line/chart-line-base.d.ts.map +1 -1
  18. package/dist/building-blocks/chart-line/chart-line-base.js.map +1 -1
  19. package/dist/building-blocks/instrument-radial/instrument-radial.d.ts +22 -2
  20. package/dist/building-blocks/instrument-radial/instrument-radial.d.ts.map +1 -1
  21. package/dist/building-blocks/instrument-radial/instrument-radial.js +61 -37
  22. package/dist/building-blocks/instrument-radial/instrument-radial.js.map +1 -1
  23. package/dist/integration-systems/integration-bar/integration-bar.d.ts +20 -24
  24. package/dist/integration-systems/integration-bar/integration-bar.d.ts.map +1 -1
  25. package/dist/integration-systems/integration-bar/integration-bar.js.map +1 -1
  26. package/dist/integration-systems/integration-button/integration-button.d.ts +15 -13
  27. package/dist/integration-systems/integration-button/integration-button.d.ts.map +1 -1
  28. package/dist/integration-systems/integration-button/integration-button.js.map +1 -1
  29. package/dist/navigation-instruments/azimuth-thruster/azimuth-thruster.d.ts +14 -0
  30. package/dist/navigation-instruments/azimuth-thruster/azimuth-thruster.d.ts.map +1 -1
  31. package/dist/navigation-instruments/azimuth-thruster/azimuth-thruster.js +30 -11
  32. package/dist/navigation-instruments/azimuth-thruster/azimuth-thruster.js.map +1 -1
  33. package/dist/navigation-instruments/compass/compass.d.ts +68 -31
  34. package/dist/navigation-instruments/compass/compass.d.ts.map +1 -1
  35. package/dist/navigation-instruments/compass/compass.js +36 -16
  36. package/dist/navigation-instruments/compass/compass.js.map +1 -1
  37. package/dist/navigation-instruments/compass-flat/compass-flat.d.ts +8 -9
  38. package/dist/navigation-instruments/compass-flat/compass-flat.d.ts.map +1 -1
  39. package/dist/navigation-instruments/compass-flat/compass-flat.js.map +1 -1
  40. package/dist/navigation-instruments/compass-sector/compass-sector.d.ts.map +1 -1
  41. package/dist/navigation-instruments/compass-sector/compass-sector.js.map +1 -1
  42. package/dist/navigation-instruments/gauge-radial/gauge-radial.css.js +34 -2
  43. package/dist/navigation-instruments/gauge-radial/gauge-radial.css.js.map +1 -1
  44. package/dist/navigation-instruments/gauge-radial/gauge-radial.d.ts +15 -0
  45. package/dist/navigation-instruments/gauge-radial/gauge-radial.d.ts.map +1 -1
  46. package/dist/navigation-instruments/gauge-radial/gauge-radial.js +35 -1
  47. package/dist/navigation-instruments/gauge-radial/gauge-radial.js.map +1 -1
  48. package/dist/navigation-instruments/gauge-trend/gauge-trend.d.ts +0 -5
  49. package/dist/navigation-instruments/gauge-trend/gauge-trend.d.ts.map +1 -1
  50. package/dist/navigation-instruments/gauge-trend/gauge-trend.js.map +1 -1
  51. package/dist/navigation-instruments/graph-mini/graph-mini.d.ts +1 -1
  52. package/dist/navigation-instruments/graph-mini/graph-mini.d.ts.map +1 -1
  53. package/dist/navigation-instruments/graph-mini/graph-mini.js.map +1 -1
  54. package/dist/navigation-instruments/heading/heading.d.ts +19 -1
  55. package/dist/navigation-instruments/heading/heading.d.ts.map +1 -1
  56. package/dist/navigation-instruments/heading/heading.js +34 -16
  57. package/dist/navigation-instruments/heading/heading.js.map +1 -1
  58. package/dist/navigation-instruments/indicator-graph/indicator-graph.d.ts +1 -1
  59. package/dist/navigation-instruments/indicator-graph/indicator-graph.d.ts.map +1 -1
  60. package/dist/navigation-instruments/indicator-graph/indicator-graph.js.map +1 -1
  61. package/dist/navigation-instruments/rudder/rudder.d.ts +15 -2
  62. package/dist/navigation-instruments/rudder/rudder.d.ts.map +1 -1
  63. package/dist/navigation-instruments/rudder/rudder.js +36 -26
  64. package/dist/navigation-instruments/rudder/rudder.js.map +1 -1
  65. package/dist/navigation-instruments/speed-gauge/speed-gauge.d.ts +15 -1
  66. package/dist/navigation-instruments/speed-gauge/speed-gauge.d.ts.map +1 -1
  67. package/dist/navigation-instruments/speed-gauge/speed-gauge.js +31 -3
  68. package/dist/navigation-instruments/speed-gauge/speed-gauge.js.map +1 -1
  69. package/dist/navigation-instruments/watch/watch.d.ts +45 -17
  70. package/dist/navigation-instruments/watch/watch.d.ts.map +1 -1
  71. package/dist/navigation-instruments/watch/watch.js +53 -38
  72. package/dist/navigation-instruments/watch/watch.js.map +1 -1
  73. package/dist/svghelpers/radial-frame.d.ts +122 -0
  74. package/dist/svghelpers/radial-frame.d.ts.map +1 -0
  75. package/dist/svghelpers/radial-frame.js +259 -0
  76. package/dist/svghelpers/radial-frame.js.map +1 -0
  77. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"compass.js","sources":["../../../src/navigation-instruments/compass/compass.ts"],"sourcesContent":["import {LitElement, PropertyValues, css, html} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport '../watch/watch.js';\nimport {Tickmark, TickmarkType} from '../watch/tickmark.js';\nimport {arrow, ArrowStyle} from './arrow.js';\nimport {AdviceState, AngleAdvice, AngleAdviceRaw} from '../watch/advice.js';\nimport {ResizeController} from '@lit-labs/observers/resize-controller.js';\nimport {\n VesselImage,\n VesselImageSize,\n WatchCircleType,\n RotType,\n RotPosition,\n} from '../watch/watch.js';\nimport {SetpointBundle} from '../../svghelpers/setpoint-bundle.js';\nimport {ROT_ZERO_DEADBAND_DEG} from '../rate-of-turn/rot-renderer.js';\nimport {customElement} from '../../decorator.js';\nimport {InstrumentState, Priority} from '../types.js';\nexport {RotType};\n\nexport enum CompassDirection {\n NorthUp = 'northUp',\n HeadingUp = 'headingUp',\n CourseUp = 'courseUp',\n}\n\nexport enum CompassPriorityElement {\n hdg = 'hdg',\n cog = 'cog',\n rot = 'rot',\n wind = 'wind',\n current = 'current',\n}\n\n/**\n * `<obc-compass>` – Full-featured compass with HDG/COG arrows, rate-of-turn indicator, and environmental overlays.\n *\n * Renders a circular compass instrument that displays heading (HDG) and\n * course-over-ground (COG) as rotating arrows over a triple-ring watch face.\n * It supports wind and current indicators, a vessel silhouette, heading\n * setpoint with auto at-setpoint detection, advice zones, and a rate-of-turn\n * (ROT) dot indicator. The compass can be oriented north-up, heading-up, or\n * course-up.\n *\n * ## Features\n *\n * - **Direction modes**: `northUp` (default), `headingUp`, or `courseUp`\n * via the `direction` property.\n * - **HDG / COG arrows**: Two styled arrows overlay the watch face,\n * rotating independently.\n * - **Heading setpoint**: Optional setpoint marker with auto at-setpoint\n * detection via `headingSetpoint`, `atHeadingSetpoint`, and deadband\n * tuning properties.\n * - **Advice zones**: Pass `headingAdvices` to render caution/alert arcs;\n * triggered state is derived from whether the current heading falls\n * inside the advice range.\n * - **Rate of turn**: Animated ROT indicator driven by\n * `rateOfTurnDegreesPerMinute` (deg/min, the maritime / AIS convention).\n * Supports spinning dots (`rotType=\"dots\"`) — the dot animation is\n * amplified by `rotDotAnimationFactor` so small physical values still\n * read at a glance — and a banana-shaped arc bar (`rotType=\"bar\"`)\n * showing the HDG→COG span. Bar extent is driven by the physical value\n * only (gain is not applied). Position on the outer scale ring or inner\n * circle via `rotPosition`.\n * - **Environmental overlays**: Wind speed/direction and current\n * speed/direction indicators on the watch face.\n * - **Vessel image**: Configurable vessel silhouette centered on the\n * compass, rotating with heading.\n * - **Color priority**: Set `priority` to `Priority.enhanced` to use the\n * blue/enhanced color palette instead of the default gray/regular palette\n * (default: `Priority.regular`).\n *\n * ## Usage Guidelines\n *\n * - Set `heading` and `courseOverGround` to the current sensor values\n * in degrees.\n * - Use `direction` to control the compass orientation mode.\n * - Use `headingSetpoint` to show a target heading marker.\n * - Pass `headingAdvices` as an array of `AngleAdvice` objects for\n * caution/alert zones.\n * - Set `currentWindSpeedKnots` / `windFromDirection` and `currentSpeed` /\n * `currentFromDirection` to display environmental indicators.\n *\n * ## Example\n *\n * ```html\n * <obc-compass\n * heading=\"45\"\n * courseOverGround=\"50\"\n * direction=\"northUp\"\n * headingSetpoint=\"90\"\n * priority=\"regular\"\n * vesselImage=\"genericTop\"\n * ></obc-compass>\n * ```\n *\n * @property {number} heading - The current heading of the vessel in degrees.\n * @property {number} courseOverGround - The current course over ground in degrees.\n * @property {number | null} headingSetpoint - The set point for the heading in degrees.\n * @property {boolean} atHeadingSetpoint - Indicates if the vessel is at the heading set point.\n * @property {boolean} autoAtHeadingSetpoint - Enables automatic at heading set point calculation.\n * @property {number} autoAtHeadingSetpointDeadband - The deadband for the heading set point in degrees.\n * @property {boolean} touching - Indicates if the compass is being touched.\n * @property {Array<AngleAdvice>} headingAdvices - An array of angle advices for the compass.\n * @property {number | null} currentWindSpeedKnots - The wind speed in knots.\n * @property {number | null} windFromDirection - The direction the wind is coming from in degrees.\n * @property {number | null} currentSpeed - The current speed, number of arrows.\n * @property {number | null} currentFromDirection - The direction the current is coming from in degrees.\n * @property {VesselImage} vesselImage - The image of the vessel.\n * @property {number|undefined} rateOfTurnDegreesPerMinute - Measured rate of turn in degrees per minute (the AIS / ITU-R M.1371 convention). Sign controls direction (positive = starboard / clockwise). Drives both the bar extent and the dot animation.\n * @property {number} rotDotAnimationFactor - Visual amplification for the dot animation only. Default `18` (≈1 rpm at 20°/min).\n * @property {number} rotationsPerMinute - **Deprecated.** Use `rateOfTurnDegreesPerMinute` instead. Kept as a backward-compatible fallback when `rateOfTurnDegreesPerMinute` is `undefined`.\n * @property {RotType} rotType - ROT display mode: `'dots'` (spinning dots, default) or `'bar'` (arc bar from HDG to COG).\n * @property {RotPosition} rotPosition - ROT track position: `'innerCircle'` (default) or `'scale'` (on the outer ring).\n * @property {Priority} priority - Color priority: `Priority.enhanced` uses the blue/enhanced color palette, `Priority.regular` (default) uses the standard palette.\n *\n * @ignition-base-height: 512px\n * @ignition-base-width: 512px\n * @stable\n */\n@customElement('obc-compass')\nexport class ObcCompass extends LitElement {\n @property({type: Number}) heading = 0;\n @property({type: Number}) courseOverGround = 0;\n\n @property({type: Number}) headingSetpoint: number | null = null;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Number}) newHeadingSetpoint: number | undefined;\n /** @availableWhen headingSetpoint!=null && autoAtHeadingSetpoint==false */\n @property({type: Boolean}) atHeadingSetpoint: boolean = false;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Number}) headingSetpointAtZeroDeadband: number = 0.5;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Boolean}) headingSetpointOverride: boolean = false;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Boolean, attribute: false}) autoAtHeadingSetpoint: boolean =\n true;\n /** @availableWhen headingSetpoint!=null && autoAtHeadingSetpoint==true */\n @property({type: Number}) autoAtHeadingSetpointDeadband: number = 2;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Boolean}) animateSetpoint: boolean = false;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Boolean}) touching: boolean = false;\n @property({type: Array, attribute: false}) headingAdvices: AngleAdvice[] = [];\n /** @availableWhen windFromDirection!=null */\n @property({type: Number}) currentWindSpeedKnots: number | null = null;\n /** @availableWhen currentWindSpeedKnots!=null */\n @property({type: Number}) windFromDirection: number | null = null;\n /** @availableWhen currentFromDirection!=null */\n @property({type: Number}) currentSpeed: number | null = null;\n /** @availableWhen currentSpeed!=null */\n @property({type: Number}) currentFromDirection: number | null = null;\n @property({type: String}) vesselImage: VesselImage = VesselImage.genericTop;\n /**\n * 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.\n * When `undefined`, falls back to the deprecated `rotationsPerMinute`.\n */\n @property({type: Number}) rateOfTurnDegreesPerMinute: number | undefined;\n /**\n * 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 rotType==dots\n */\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 */\n @property({type: Number}) rotationsPerMinute: number = 1;\n @property({type: String}) rotType: RotType = RotType.dots;\n @property({type: String}) rotPosition: RotPosition = RotPosition.innerCircle;\n /**\n * Bar-extent reference value in **degrees per minute**. The bar fills the\n * full ±`rotArcExtent` arc when the measured ROT equals ±`rotMaxValue`.\n * Default `60` aligns with ES-TRIN 2025/1 Art. 3.02.\n *\n * Note: prior to the introduction of `rateOfTurnDegreesPerMinute` this\n * property was interpreted in rotations per minute. The unit changed when\n * the physical ROT API was introduced.\n * @availableWhen rotType==bar\n */\n @property({type: Number}) rotMaxValue: number = 60;\n /** @availableWhen rotType==bar */\n @property({type: Number}) rotArcExtent: number = 60;\n @property({type: Boolean}) rotPortStarboard: boolean = false;\n /** @availableWhen rotType==bar */\n @property({type: Number}) rotAtZeroDeadband: number = ROT_ZERO_DEADBAND_DEG;\n @property({type: String}) direction: CompassDirection =\n CompassDirection.NorthUp;\n @property({type: String}) state: InstrumentState = InstrumentState.active;\n @property({type: String}) priority: Priority = Priority.regular;\n /** @availableWhen priority==enhanced */\n @property({type: Array, attribute: false})\n priorityElements: CompassPriorityElement[] = [CompassPriorityElement.hdg];\n /** Show compass NSEW labels and north arrow. */\n @property({type: Boolean}) showLabels: boolean = false;\n /** When true, labels and north arrow are placed inside the outer ring. */\n @property({type: Boolean}) tickmarksInside: boolean = false;\n\n private _headingSp = new SetpointBundle({\n angularWraparound: true,\n onAnimationEnd: () => this.requestUpdate(),\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\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this._headingSp.dispose();\n }\n\n // @ts-expect-error TS6133: The controller ensures that the render\n // function is called on resize of the element\n private _resizeController = new ResizeController(this, {});\n\n /**\n * Resolved rate of turn in degrees per minute, used to compute the bar\n * extent. Prefers the new physical API; falls back to the deprecated\n * `rotationsPerMinute` so existing consumers keep their visuals during\n * the deprecation window.\n */\n private get _effectiveRotDegPerMin(): number {\n return this.rateOfTurnDegreesPerMinute ?? this.rotationsPerMinute;\n }\n\n private getPadding() {\n const size = Math.min(this.clientHeight, this.clientWidth);\n const deltaWidth = 512 - size;\n const steps = deltaWidth / 128;\n let deltaPadding;\n if (deltaWidth > 0) {\n deltaPadding = steps * 48;\n } else {\n deltaPadding = steps * 6;\n }\n\n return 72 + deltaPadding;\n }\n\n private get angleAdviceRaw(): AngleAdviceRaw[] {\n return this.headingAdvices.map(({minAngle, maxAngle, hinted, type}) => {\n const state =\n this.heading >= minAngle && this.heading <= maxAngle\n ? AdviceState.triggered\n : hinted\n ? AdviceState.hinted\n : AdviceState.regular;\n return {minAngle, maxAngle, type, state};\n });\n }\n\n private priorityFor(element: CompassPriorityElement): 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 colorFor(element: CompassPriorityElement): string | undefined {\n return this.priorityFor(element) === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : undefined;\n }\n\n private getRotation(): number | undefined {\n if (this.direction === CompassDirection.NorthUp) {\n return undefined;\n } else if (this.direction === CompassDirection.HeadingUp) {\n return -this.heading;\n } else if (this.direction === CompassDirection.CourseUp) {\n return -this.courseOverGround;\n }\n return undefined;\n }\n\n override render() {\n const tickmarks: Tickmark[] = [\n {angle: 0, type: TickmarkType.main},\n {angle: 90, type: TickmarkType.main},\n {angle: 180, type: TickmarkType.main},\n {angle: 270, type: TickmarkType.main},\n ];\n\n const padding = this.getPadding();\n const width = (176 + padding) * 2;\n const viewBox = `-${width / 2} -${width / 2} ${width} ${width}`;\n\n return html`\n <div class=\"container\">\n <obc-watch\n .touching=${this.touching}\n .padding=${padding}\n .advices=${this.angleAdviceRaw}\n .tickmarks=${tickmarks}\n .state=${this.state}\n .watchCircleType=${WatchCircleType.triple}\n .showLabels=${this.showLabels}\n .tickmarksInside=${this.tickmarksInside}\n .crosshairEnabled=${true}\n .northArrow=${true}\n .angleSetpoint=${this.headingSetpoint ?? undefined}\n .newAngleSetpoint=${this.newHeadingSetpoint}\n .atAngleSetpoint=${this._headingSp.computeAtSetpoint(this.heading)}\n .angleSetpointAtZeroDeadband=${this.headingSetpointAtZeroDeadband}\n .setpointOverride=${this.headingSetpointOverride}\n .priority=${this.priority}\n .animateSetpoint=${this.animateSetpoint}\n .vessels=${[\n {\n size: VesselImageSize.medium,\n vesselImage: this.vesselImage,\n transform: `rotate(${this.heading}deg)`,\n },\n ]}\n .windKnots=${this.currentWindSpeedKnots}\n .windFromDirectionDeg=${this.windFromDirection}\n .windColor=${this.colorFor(CompassPriorityElement.wind)}\n .current=${this.currentSpeed}\n .currentFromDirectionDeg=${this.currentFromDirection}\n .currentColor=${this.colorFor(CompassPriorityElement.current)}\n .rotation=${this.getRotation()}\n .rotType=${this.rotType}\n .rotPosition=${this.rotPosition}\n .rotStartAngle=${this.heading + (this.getRotation() ?? 0)}\n .rotEndAngle=${this.heading +\n (this._effectiveRotDegPerMin / (this.rotMaxValue || 1)) *\n this.rotArcExtent +\n (this.getRotation() ?? 0)}\n .rotPriority=${this.priorityFor(CompassPriorityElement.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}\">\n ${arrow(\n ArrowStyle.HDG,\n this.heading + (this.getRotation() ?? 0),\n this.priorityFor(CompassPriorityElement.hdg)\n )}\n ${arrow(\n ArrowStyle.COG,\n this.courseOverGround + (this.getRotation() ?? 0),\n this.priorityFor(CompassPriorityElement.cog)\n )}\n </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 :host {\n display: block;\n width: 100%;\n height: 100%;\n }\n `;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-compass': ObcCompass;\n }\n}\n"],"names":["CompassDirection","CompassPriorityElement"],"mappings":"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"}
1
+ {"version":3,"file":"compass.js","sources":["../../../src/navigation-instruments/compass/compass.ts"],"sourcesContent":["import {LitElement, PropertyValues, css, html} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport '../watch/watch.js';\nimport {Tickmark, TickmarkType} from '../watch/tickmark.js';\nimport {arrow, ArrowStyle} from './arrow.js';\nimport {AdviceState, AngleAdvice, AngleAdviceRaw} from '../watch/advice.js';\nimport {ResizeController} from '@lit-labs/observers/resize-controller.js';\nimport {\n applyPinnedHostSize,\n computeRadialFrame,\n measureContainerPx,\n NORTH_ARROW_WIDTH_PX,\n NSWE_LABEL_WIDTH_PX,\n type RadialFrame,\n} from '../../svghelpers/radial-frame.js';\nimport {\n VesselImage,\n VesselImageSize,\n WatchCircleType,\n RotType,\n RotPosition,\n} from '../watch/watch.js';\nimport {SetpointBundle} from '../../svghelpers/setpoint-bundle.js';\nimport {ROT_ZERO_DEADBAND_DEG} from '../rate-of-turn/rot-renderer.js';\nimport {customElement} from '../../decorator.js';\nimport {InstrumentState, Priority} from '../types.js';\nexport {RotType};\n\nexport enum CompassDirection {\n NorthUp = 'northUp',\n HeadingUp = 'headingUp',\n CourseUp = 'courseUp',\n}\n\nexport enum CompassPriorityElement {\n hdg = 'hdg',\n cog = 'cog',\n rot = 'rot',\n wind = 'wind',\n current = 'current',\n}\n\n/**\n * `<obc-compass>` – Full-featured compass with HDG/COG arrows, rate-of-turn indicator, and environmental overlays.\n *\n * Renders a circular compass instrument that displays heading (HDG) and\n * course-over-ground (COG) as rotating arrows over a triple-ring watch face.\n * It supports wind and current indicators, a vessel silhouette, heading\n * setpoint with auto at-setpoint detection, advice zones, and a rate-of-turn\n * (ROT) dot indicator. The compass can be oriented north-up, heading-up, or\n * course-up.\n *\n * ## Features\n *\n * - **Direction modes**: `northUp` (default), `headingUp`, or `courseUp`\n * via the `direction` property.\n * - **HDG / COG arrows**: Two styled arrows overlay the watch face,\n * rotating independently.\n * - **Heading setpoint**: Optional setpoint marker with auto at-setpoint\n * detection via `headingSetpoint`, `atHeadingSetpoint`, and deadband\n * tuning properties.\n * - **Advice zones**: Pass `headingAdvices` to render caution/alert arcs;\n * triggered state is derived from whether the current heading falls\n * inside the advice range.\n * - **Rate of turn**: Animated ROT indicator driven by\n * `rateOfTurnDegreesPerMinute` (deg/min, the maritime / AIS convention).\n * Supports spinning dots (`rotType=\"dots\"`) — the dot animation is\n * amplified by `rotDotAnimationFactor` so small physical values still\n * read at a glance — and a banana-shaped arc bar (`rotType=\"bar\"`)\n * showing the rate of turn as an arc anchored at the current heading.\n * Bar extent is driven by the physical value only (gain is not applied).\n * Position on the outer scale ring or inner circle via `rotPosition`.\n * - **Environmental overlays**: Wind speed/direction and current\n * speed/direction indicators on the watch face.\n * - **Vessel image**: Configurable vessel silhouette centered on the\n * compass, rotating with heading.\n * - **Color priority**: Set `priority` to `Priority.enhanced` to use the\n * blue/enhanced color palette instead of the default gray/regular palette\n * (default: `Priority.regular`).\n *\n * ## Usage Guidelines\n *\n * - Set `heading` and `courseOverGround` to the current sensor values\n * in degrees.\n * - Use `direction` to control the compass orientation mode.\n * - Use `headingSetpoint` to show a target heading marker.\n * - Pass `headingAdvices` as an array of `AngleAdvice` objects for\n * caution/alert zones.\n * - Set `currentWindSpeedKnots` / `windFromDirection` and `currentSpeed` /\n * `currentFromDirection` to display environmental indicators.\n *\n * ## Example\n *\n * ```html\n * <obc-compass\n * heading=\"45\"\n * courseOverGround=\"50\"\n * direction=\"northUp\"\n * headingSetpoint=\"90\"\n * priority=\"regular\"\n * vesselImage=\"genericTop\"\n * ></obc-compass>\n * ```\n *\n *\n * @ignition-base-height: 512px\n * @ignition-base-width: 512px\n * @stable\n */\n@customElement('obc-compass')\nexport class ObcCompass extends LitElement {\n /** The current heading of the vessel in degrees. */\n @property({type: Number}) heading = 0;\n /** The current course over ground in degrees. */\n @property({type: Number}) courseOverGround = 0;\n\n /** The set point for the heading in degrees. */\n @property({type: Number}) headingSetpoint: number | null = null;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Number}) newHeadingSetpoint: number | undefined;\n /**\n * Indicates if the vessel is at the heading set point.\n * @availableWhen headingSetpoint!=null && autoAtHeadingSetpoint==false\n */\n @property({type: Boolean}) atHeadingSetpoint: boolean = false;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Number}) headingSetpointAtZeroDeadband: number = 0.5;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Boolean}) headingSetpointOverride: boolean = false;\n /**\n * Enables automatic at heading set point calculation.\n * @availableWhen headingSetpoint!=null\n */\n @property({type: Boolean, attribute: false}) autoAtHeadingSetpoint: boolean =\n true;\n /**\n * The deadband for the heading set point in degrees.\n * @availableWhen headingSetpoint!=null && autoAtHeadingSetpoint==true\n */\n @property({type: Number}) autoAtHeadingSetpointDeadband: number = 2;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Boolean}) animateSetpoint: boolean = false;\n /**\n * Indicates if the compass is being touched.\n * @availableWhen headingSetpoint!=null\n */\n @property({type: Boolean}) touching: boolean = false;\n /** An array of angle advices for the compass. */\n @property({type: Array, attribute: false}) headingAdvices: AngleAdvice[] = [];\n /**\n * The wind speed in knots.\n * @availableWhen windFromDirection!=null\n */\n @property({type: Number}) currentWindSpeedKnots: number | null = null;\n /**\n * The direction the wind is coming from in degrees.\n * @availableWhen currentWindSpeedKnots!=null\n */\n @property({type: Number}) windFromDirection: number | null = null;\n /**\n * The current speed, number of arrows.\n * @availableWhen currentFromDirection!=null\n */\n @property({type: Number}) currentSpeed: number | null = null;\n /**\n * The direction the current is coming from in degrees.\n * @availableWhen currentSpeed!=null\n */\n @property({type: Number}) currentFromDirection: number | null = null;\n /** The image of the vessel. */\n @property({type: String}) vesselImage: VesselImage = VesselImage.genericTop;\n /**\n * 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.\n * When `undefined`, falls back to the deprecated `rotationsPerMinute`.\n */\n @property({type: Number}) rateOfTurnDegreesPerMinute: number | undefined;\n /**\n * 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 rotType==dots\n */\n @property({type: Number}) rotDotAnimationFactor: number = 18;\n /**\n * Legacy rate-of-turn input, in rotations per minute. When\n * `rateOfTurnDegreesPerMinute` is `undefined`, this value is used\n * (unconverted) as the fallback ROT, driving both the spinning dot ring\n * and the bar extent.\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 /** ROT display mode: `'dots'` (spinning dots, default) or `'bar'` (a rate-of-turn arc anchored at the current heading, its length proportional to the rate of turn). */\n @property({type: String}) rotType: RotType = RotType.dots;\n /** ROT track position: `'innerCircle'` (default) or `'scale'` (on the outer ring). */\n @property({type: String}) rotPosition: RotPosition = RotPosition.innerCircle;\n /**\n * Bar-extent reference value in **degrees per minute**. The bar fills the\n * full ±`rotArcExtent` arc when the measured ROT equals ±`rotMaxValue`.\n * Default `60` aligns with ES-TRIN 2025/1 Art. 3.02.\n *\n * Note: prior to the introduction of `rateOfTurnDegreesPerMinute` this\n * property was interpreted in rotations per minute. The unit changed when\n * the physical ROT API was introduced.\n * @availableWhen rotType==bar\n */\n @property({type: Number}) rotMaxValue: number = 60;\n /** @availableWhen rotType==bar */\n @property({type: Number}) rotArcExtent: number = 60;\n @property({type: Boolean}) rotPortStarboard: boolean = false;\n /** @availableWhen rotType==bar */\n @property({type: Number}) rotAtZeroDeadband: number = ROT_ZERO_DEADBAND_DEG;\n @property({type: String}) direction: CompassDirection =\n CompassDirection.NorthUp;\n @property({type: String}) state: InstrumentState = InstrumentState.active;\n /** Color priority: `Priority.enhanced` uses the blue/enhanced color palette, `Priority.regular` (default) uses the standard palette. */\n @property({type: String}) priority: Priority = Priority.regular;\n /** @availableWhen priority==enhanced */\n @property({type: Array, attribute: false})\n priorityElements: CompassPriorityElement[] = [CompassPriorityElement.hdg];\n /** Show compass NSEW labels and north arrow. */\n @property({type: Boolean}) showLabels: boolean = false;\n /** When true, labels and north arrow are placed inside the outer ring. */\n @property({type: Boolean}) tickmarksInside: boolean = false;\n /**\n * 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 */\n @property({type: Number, attribute: 'face-diameter'})\n faceDiameter: number | undefined;\n\n private _headingSp = new SetpointBundle({\n angularWraparound: true,\n onAnimationEnd: () => this.requestUpdate(),\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\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this._headingSp.dispose();\n }\n\n // @ts-expect-error TS6133: The controller ensures that the render\n // function is called on resize of the element\n private _resizeController = new ResizeController(this, {});\n\n /**\n * Resolved rate of turn in degrees per minute, used to compute the bar\n * extent. Prefers the new physical API; falls back to the deprecated\n * `rotationsPerMinute` so existing consumers keep their visuals during\n * the deprecation window.\n */\n private get _effectiveRotDegPerMin(): number {\n return this.rateOfTurnDegreesPerMinute ?? this.rotationsPerMinute;\n }\n\n /**\n * Pixel cost of the outside decor: the always-rendered north-arrow glyph\n * plus, only while shown, the NSWE labels (both keep a constant on-screen\n * size via `1/scale` terms). Feeds the frame's width-aware reserve,\n * replacing the former empirical `72 + delta(clientSize)` padding.\n * Wind/current symbols at their default radius are covered by the base\n * padding of 72.\n */\n private getOutsideDecorPx(): number {\n if (this.tickmarksInside) {\n return 0;\n }\n return NORTH_ARROW_WIDTH_PX + (this.showLabels ? NSWE_LABEL_WIDTH_PX : 0);\n }\n\n /** Whether the host size styles were set by applyPinnedHostSize. */\n private _hostSizePinned = false;\n private _frame: RadialFrame | undefined;\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 angleAdviceRaw(): AngleAdviceRaw[] {\n return this.headingAdvices.map(({minAngle, maxAngle, hinted, type}) => {\n const state =\n this.heading >= minAngle && this.heading <= maxAngle\n ? AdviceState.triggered\n : hinted\n ? AdviceState.hinted\n : AdviceState.regular;\n return {minAngle, maxAngle, type, state};\n });\n }\n\n private priorityFor(element: CompassPriorityElement): 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 colorFor(element: CompassPriorityElement): string | undefined {\n return this.priorityFor(element) === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : undefined;\n }\n\n private getRotation(): number | undefined {\n if (this.direction === CompassDirection.NorthUp) {\n return undefined;\n } else if (this.direction === CompassDirection.HeadingUp) {\n return -this.heading;\n } else if (this.direction === CompassDirection.CourseUp) {\n return -this.courseOverGround;\n }\n return undefined;\n }\n\n override render() {\n const tickmarks: Tickmark[] = [\n {angle: 0, type: TickmarkType.main},\n {angle: 90, type: TickmarkType.main},\n {angle: 180, type: TickmarkType.main},\n {angle: 270, type: TickmarkType.main},\n ];\n\n const frame = computeRadialFrame({\n basePadding: 72,\n labelWidthPx: this.getOutsideDecorPx(),\n containerPx: measureContainerPx(this),\n faceDiameter: this.faceDiameter,\n });\n this._frame = frame;\n const viewBox = frame.viewBox;\n\n return html`\n <div class=\"container\">\n <obc-watch\n .touching=${this.touching}\n .arcFrame=${frame}\n .advices=${this.angleAdviceRaw}\n .tickmarks=${tickmarks}\n .state=${this.state}\n .watchCircleType=${WatchCircleType.triple}\n .showLabels=${this.showLabels && !frame.labelsHidden}\n .tickmarksInside=${this.tickmarksInside}\n .crosshairEnabled=${true}\n .northArrow=${!frame.labelsHidden}\n .angleSetpoint=${this.headingSetpoint ?? undefined}\n .newAngleSetpoint=${this.newHeadingSetpoint}\n .atAngleSetpoint=${this._headingSp.computeAtSetpoint(this.heading)}\n .angleSetpointAtZeroDeadband=${this.headingSetpointAtZeroDeadband}\n .setpointOverride=${this.headingSetpointOverride}\n .priority=${this.priority}\n .animateSetpoint=${this.animateSetpoint}\n .vessels=${[\n {\n size: VesselImageSize.medium,\n vesselImage: this.vesselImage,\n transform: `rotate(${this.heading}deg)`,\n },\n ]}\n .windKnots=${this.currentWindSpeedKnots}\n .windFromDirectionDeg=${this.windFromDirection}\n .windColor=${this.colorFor(CompassPriorityElement.wind)}\n .current=${this.currentSpeed}\n .currentFromDirectionDeg=${this.currentFromDirection}\n .currentColor=${this.colorFor(CompassPriorityElement.current)}\n .rotation=${this.getRotation()}\n .rotType=${this.rotType}\n .rotPosition=${this.rotPosition}\n .rotStartAngle=${this.heading + (this.getRotation() ?? 0)}\n .rotEndAngle=${this.heading +\n (this._effectiveRotDegPerMin / (this.rotMaxValue || 1)) *\n this.rotArcExtent +\n (this.getRotation() ?? 0)}\n .rotPriority=${this.priorityFor(CompassPriorityElement.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}\">\n ${arrow(\n ArrowStyle.HDG,\n this.heading + (this.getRotation() ?? 0),\n this.priorityFor(CompassPriorityElement.hdg)\n )}\n ${arrow(\n ArrowStyle.COG,\n this.courseOverGround + (this.getRotation() ?? 0),\n this.priorityFor(CompassPriorityElement.cog)\n )}\n </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 :host {\n display: block;\n width: 100%;\n height: 100%;\n }\n `;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-compass': ObcCompass;\n }\n}\n"],"names":["CompassDirection","CompassPriorityElement"],"mappings":"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"}
@@ -44,14 +44,6 @@ export interface Label {
44
44
  * - **Color priority**: Per-element priority for HDG, COG, and ROT via
45
45
  * `priorityElements`.
46
46
  *
47
- * @property {number} heading - Current heading in degrees.
48
- * @property {number} courseOverGround - Current COG in degrees.
49
- * @property {RotType|undefined} rotType - ROT display mode: `'dots'`, `'bar'`, or `undefined` (hidden).
50
- * @property {number|undefined} rateOfTurnDegreesPerMinute - Measured rate of turn in degrees per minute (positive = starboard). Drives the bar extent and (after `× rotDotAnimationFactor`) the dot animation.
51
- * @property {number} rotDotAnimationFactor - Visual amplification for the dot animation only. Default `18` (≈1 rpm at 20°/min).
52
- * @property {number} rotationsPerMinute - **Deprecated.** Use `rateOfTurnDegreesPerMinute` instead.
53
- * @property {number} rotMaxValue - Bar-extent reference value in **degrees per minute**. Default `60` per ES-TRIN 2025/1 Art. 3.02.
54
- * @property {number} rotArcExtent - Degrees of bar arc per max-value ROT (default 60).
55
47
  *
56
48
  * @ignition-base-height: 170px
57
49
  * @ignition-base-width: 512px
@@ -59,7 +51,9 @@ export interface Label {
59
51
  */
60
52
  export declare class ObcCompassFlat extends LitElement {
61
53
  FOVIndicator: boolean;
54
+ /** Current heading in degrees. */
62
55
  heading: number;
56
+ /** Current COG in degrees. */
63
57
  courseOverGround: number;
64
58
  tickInterval: number;
65
59
  FOV: number;
@@ -67,6 +61,7 @@ export declare class ObcCompassFlat extends LitElement {
67
61
  maxFOV: number;
68
62
  priority: Priority;
69
63
  priorityElements: CompassFlatPriorityElement[];
64
+ /** ROT display mode: `'dots'`, `'bar'`, or `undefined` (hidden). */
70
65
  rotType: RotType | undefined;
71
66
  /**
72
67
  * Measured rate of turn in degrees per minute (positive = starboard).
@@ -80,6 +75,7 @@ export declare class ObcCompassFlat extends LitElement {
80
75
  */
81
76
  rotDotAnimationFactor: number;
82
77
  /**
78
+ * **Deprecated.** Use `rateOfTurnDegreesPerMinute` instead.
83
79
  * @deprecated Use `rateOfTurnDegreesPerMinute` instead.
84
80
  * @availableWhen rotType!=undefined
85
81
  */
@@ -90,7 +86,10 @@ export declare class ObcCompassFlat extends LitElement {
90
86
  * @availableWhen rotType!=undefined
91
87
  */
92
88
  rotMaxValue: number;
93
- /** @availableWhen rotType!=undefined */
89
+ /**
90
+ * Degrees of bar arc per max-value ROT (default 60).
91
+ * @availableWhen rotType!=undefined
92
+ */
94
93
  rotArcExtent: number;
95
94
  /** @availableWhen rotType!=undefined */
96
95
  rotPortStarboard: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"compass-flat.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/compass-flat/compass-flat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAA0C,MAAM,KAAK,CAAC;AAIxE,OAAO,6BAA6B,CAAC;AAErC,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AACrC,OAAO,EACL,OAAO,EAGR,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAAC,OAAO,EAAC,CAAC;AAEjB,oBAAY,0BAA0B;IACpC,GAAG,QAAQ;IACX,GAAG,QAAQ;IACX,GAAG,QAAQ;CACZ;AAED,oBAAY,aAAa;IACvB,GAAG,MAAM;IACT,MAAM,KAAK;CACZ;AAED,oBAAY,UAAU;IACpB,OAAO,gDAAgD;CACxD;AAED,MAAM,WAAW,KAAK;IACpB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,aAAa,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,qBACa,cAAe,SAAQ,UAAU;IACjB,YAAY,EAAE,OAAO,CAAS;IAC/B,OAAO,SAAK;IACZ,gBAAgB,SAAK;IACrB,YAAY,SAAK;IACjB,GAAG,SAAM;IACT,MAAM,SAAM;IACZ,MAAM,SAAO;IACb,QAAQ,EAAE,QAAQ,CAAoB;IAEhE,gBAAgB,EAAE,0BAA0B,EAAE,CAE5C;IACwB,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC;IACvD;;;;OAIG;IACuB,0BAA0B,EAAE,MAAM,GAAG,SAAS,CAAC;IACzE;;;OAGG;IACuB,qBAAqB,EAAE,MAAM,CAAM;IAC7D;;;OAGG;IACuB,kBAAkB,EAAE,MAAM,CAAK;IACzD;;;;OAIG;IACuB,WAAW,EAAE,MAAM,CAAM;IACnD,wCAAwC;IACd,YAAY,EAAE,MAAM,CAAM;IACpD,wCAAwC;IACb,gBAAgB,EAAE,OAAO,CAAS;IAC7D,wCAAwC;IACd,iBAAiB,EAAE,MAAM,CAAyB;IAEnE,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,iBAAiB,CAAK;IAEvC,OAAO,CAAC,cAAc,CASnB;IAEM,iBAAiB;IAKjB,oBAAoB;IAK7B,cAAc;;;;;IAsCd,OAAO,CAAC,yBAAyB;IAiCjC,OAAO,CAAC,yBAAyB;IAajC,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,kBAAkB;IAmC1B,OAAO,CAAC,WAAW;IAOnB,OAAO,KAAK,sBAAsB,GAEjC;IAED,OAAO,CAAC,aAAa;IAMrB,OAAO,KAAK,MAAM,GAIjB;IAED,OAAO,CAAC,MAAM;IAQL,MAAM;IAyDf,OAAgB,MAAM,0BAA6B;CACpD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,kBAAkB,EAAE,cAAc,CAAC;KACpC;CACF"}
1
+ {"version":3,"file":"compass-flat.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/compass-flat/compass-flat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAA0C,MAAM,KAAK,CAAC;AAIxE,OAAO,6BAA6B,CAAC;AAErC,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AACrC,OAAO,EACL,OAAO,EAGR,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAAC,OAAO,EAAC,CAAC;AAEjB,oBAAY,0BAA0B;IACpC,GAAG,QAAQ;IACX,GAAG,QAAQ;IACX,GAAG,QAAQ;CACZ;AAED,oBAAY,aAAa;IACvB,GAAG,MAAM;IACT,MAAM,KAAK;CACZ;AAED,oBAAY,UAAU;IACpB,OAAO,gDAAgD;CACxD;AAED,MAAM,WAAW,KAAK;IACpB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,aAAa,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBACa,cAAe,SAAQ,UAAU;IACjB,YAAY,EAAE,OAAO,CAAS;IACzD,kCAAkC;IACR,OAAO,SAAK;IACtC,8BAA8B;IACJ,gBAAgB,SAAK;IACrB,YAAY,SAAK;IACjB,GAAG,SAAM;IACT,MAAM,SAAM;IACZ,MAAM,SAAO;IACb,QAAQ,EAAE,QAAQ,CAAoB;IAEhE,gBAAgB,EAAE,0BAA0B,EAAE,CAE5C;IACF,oEAAoE;IAC1C,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC;IACvD;;;;OAIG;IACuB,0BAA0B,EAAE,MAAM,GAAG,SAAS,CAAC;IACzE;;;OAGG;IACuB,qBAAqB,EAAE,MAAM,CAAM;IAC7D;;;;OAIG;IACuB,kBAAkB,EAAE,MAAM,CAAK;IACzD;;;;OAIG;IACuB,WAAW,EAAE,MAAM,CAAM;IACnD;;;OAGG;IACuB,YAAY,EAAE,MAAM,CAAM;IACpD,wCAAwC;IACb,gBAAgB,EAAE,OAAO,CAAS;IAC7D,wCAAwC;IACd,iBAAiB,EAAE,MAAM,CAAyB;IAEnE,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,iBAAiB,CAAK;IAEvC,OAAO,CAAC,cAAc,CASnB;IAEM,iBAAiB;IAKjB,oBAAoB;IAK7B,cAAc;;;;;IAsCd,OAAO,CAAC,yBAAyB;IAiCjC,OAAO,CAAC,yBAAyB;IAajC,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,kBAAkB;IAmC1B,OAAO,CAAC,WAAW;IAOnB,OAAO,KAAK,sBAAsB,GAEjC;IAED,OAAO,CAAC,aAAa;IAMrB,OAAO,KAAK,MAAM,GAIjB;IAED,OAAO,CAAC,MAAM;IAQL,MAAM;IAyDf,OAAgB,MAAM,0BAA6B;CACpD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,kBAAkB,EAAE,cAAc,CAAC;KACpC;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"compass-flat.js","sources":["../../../src/navigation-instruments/compass-flat/compass-flat.ts"],"sourcesContent":["import {LitElement, html, svg, SVGTemplateResult, unsafeCSS} from 'lit';\nimport componentStyle from './compass-flat.css?inline';\nimport {property, state} from 'lit/decorators.js';\nimport {Tickmark, TickmarkType} from '../watch-flat/tickmark-flat.js';\nimport '../watch-flat/watch-flat.js';\nimport {customElement} from '../../decorator.js';\nimport {Priority} from '../types.js';\nimport {\n RotType,\n LINEAR_DOT_ANGLE_SPACING,\n ROT_ZERO_DEADBAND_DEG,\n} from '../rate-of-turn/rot-renderer.js';\n\nexport {RotType};\n\nexport enum CompassFlatPriorityElement {\n hdg = 'hdg',\n cog = 'cog',\n rot = 'rot',\n}\n\nexport enum LabelPosition {\n top = -45,\n bottom = 50,\n}\n\nexport enum LabelStyle {\n regular = 'var(--instrument-tick-mark-secondary-color)',\n}\n\nexport interface Label {\n x: number;\n y: LabelPosition;\n text: string;\n}\n\n/**\n * `<obc-compass-flat>` — Horizontal strip compass with HDG/COG arrows and optional rate-of-turn indicator.\n *\n * Renders a flat (non-circular) compass strip that scrolls horizontally to\n * display the current heading. A filled HDG arrow sits at the center while a\n * hollow COG arrow is positioned at the angular difference. The strip\n * auto-scales its field of view so both arrows remain visible. Cardinal\n * labels (N, S, E, W) and tickmarks are generated at densities responsive to\n * the strip width.\n *\n * ## Features\n *\n * - **Auto-scaling FOV**: The visible compass range widens to keep both HDG\n * and COG arrows in view, bounded by `minFOV` / `maxFOV`.\n * - **HDG / COG arrows**: Filled (HDG) and hollow (COG) arrow SVGs positioned\n * along the strip.\n * - **FOV indicator**: Optional numeric labels showing the port/starboard\n * bearing range and current heading.\n * - **Rate of turn**: Animated linear ROT indicator (spinning dots or\n * horizontal bar) via `rotType`. When enabled, a bottom bar is added to\n * the strip to house the indicator.\n * - **Color priority**: Per-element priority for HDG, COG, and ROT via\n * `priorityElements`.\n *\n * @property {number} heading - Current heading in degrees.\n * @property {number} courseOverGround - Current COG in degrees.\n * @property {RotType|undefined} rotType - ROT display mode: `'dots'`, `'bar'`, or `undefined` (hidden).\n * @property {number|undefined} rateOfTurnDegreesPerMinute - Measured rate of turn in degrees per minute (positive = starboard). Drives the bar extent and (after `× rotDotAnimationFactor`) the dot animation.\n * @property {number} rotDotAnimationFactor - Visual amplification for the dot animation only. Default `18` (≈1 rpm at 20°/min).\n * @property {number} rotationsPerMinute - **Deprecated.** Use `rateOfTurnDegreesPerMinute` instead.\n * @property {number} rotMaxValue - Bar-extent reference value in **degrees per minute**. Default `60` per ES-TRIN 2025/1 Art. 3.02.\n * @property {number} rotArcExtent - Degrees of bar arc per max-value ROT (default 60).\n *\n * @ignition-base-height: 170px\n * @ignition-base-width: 512px\n * @stable\n */\n@customElement('obc-compass-flat')\nexport class ObcCompassFlat extends LitElement {\n @property({type: Boolean}) FOVIndicator: boolean = false;\n @property({type: Number}) heading = 0;\n @property({type: Number}) courseOverGround = 0;\n @property({type: Number}) tickInterval = 5;\n @property({type: Number}) FOV = 45;\n @property({type: Number}) minFOV = 45;\n @property({type: Number}) maxFOV = 180;\n @property({type: String}) priority: Priority = Priority.regular;\n @property({type: Array, attribute: false})\n priorityElements: CompassFlatPriorityElement[] = [\n CompassFlatPriorityElement.hdg,\n ];\n @property({type: String}) rotType: RotType | undefined;\n /**\n * Measured rate of turn in degrees per minute (positive = starboard).\n * When `undefined`, falls back to the deprecated `rotationsPerMinute`.\n * @availableWhen rotType!=undefined\n */\n @property({type: Number}) rateOfTurnDegreesPerMinute: number | undefined;\n /**\n * Visual amplification applied only to the spinning dot animation.\n * @availableWhen rotType!=undefined\n */\n @property({type: Number}) rotDotAnimationFactor: number = 18;\n /**\n * @deprecated Use `rateOfTurnDegreesPerMinute` instead.\n * @availableWhen rotType!=undefined\n */\n @property({type: Number}) rotationsPerMinute: number = 1;\n /**\n * Bar-extent reference value in **degrees per minute**. Default `60`\n * per ES-TRIN 2025/1 Art. 3.02.\n * @availableWhen rotType!=undefined\n */\n @property({type: Number}) rotMaxValue: number = 60;\n /** @availableWhen rotType!=undefined */\n @property({type: Number}) rotArcExtent: number = 60;\n /** @availableWhen rotType!=undefined */\n @property({type: Boolean}) rotPortStarboard: boolean = false;\n /** @availableWhen rotType!=undefined */\n @property({type: Number}) rotAtZeroDeadband: number = ROT_ZERO_DEADBAND_DEG;\n\n @state() private containerWidth = 0;\n @state() private maxContainerWidth = 0;\n\n private resizeObserver: ResizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n // Made by chatGPT so that the text is inside the wrapper\n this.maxContainerWidth = -125.36 + 3.79 * entry.contentRect.height;\n this.containerWidth = Math.min(\n entry.contentRect.width,\n this.maxContainerWidth\n );\n }\n });\n\n override connectedCallback() {\n super.connectedCallback();\n this.resizeObserver.observe(this);\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this.resizeObserver.unobserve(this);\n }\n\n generateLabels() {\n if (this.containerWidth < 192) {\n return [];\n } else if (this.containerWidth <= 300) {\n return [\n {x: -180, y: LabelPosition.top, text: 'S'},\n {x: -90, y: LabelPosition.top, text: 'W'},\n {x: 0, y: LabelPosition.top, text: 'N'},\n {x: 90, y: LabelPosition.top, text: 'E'},\n {x: 180, y: LabelPosition.top, text: 'S'},\n {x: 270, y: LabelPosition.top, text: 'W'},\n {x: 360, y: LabelPosition.top, text: 'N'},\n {x: 450, y: LabelPosition.top, text: 'E'},\n {x: 540, y: LabelPosition.top, text: 'S'},\n ];\n } else {\n return [\n {x: -180, y: LabelPosition.top, text: 'S'},\n {x: -135, y: LabelPosition.top, text: 'SW'},\n {x: -90, y: LabelPosition.top, text: 'W'},\n {x: -45, y: LabelPosition.top, text: 'NW'},\n {x: 0, y: LabelPosition.top, text: 'N'},\n {x: 45, y: LabelPosition.top, text: 'NE'},\n {x: 90, y: LabelPosition.top, text: 'E'},\n {x: 135, y: LabelPosition.top, text: 'SE'},\n {x: 180, y: LabelPosition.top, text: 'S'},\n {x: 225, y: LabelPosition.top, text: 'SW'},\n {x: 270, y: LabelPosition.top, text: 'W'},\n {x: 315, y: LabelPosition.top, text: 'NW'},\n {x: 360, y: LabelPosition.top, text: 'N'},\n {x: 405, y: LabelPosition.top, text: 'NE'},\n {x: 450, y: LabelPosition.top, text: 'E'},\n {x: 495, y: LabelPosition.top, text: 'SE'},\n {x: 540, y: LabelPosition.top, text: 'S'},\n ];\n }\n }\n\n private generateIntervalTickmarks(scale: number): Tickmark[] {\n const tickmarks: Tickmark[] = [];\n let cardinalInterval = 90;\n\n if (this.containerWidth > 300) {\n cardinalInterval = 45;\n } else if (this.containerWidth < 192) {\n cardinalInterval = 0;\n }\n\n // Guard against zero/negative/non-finite interval to prevent infinite loops\n if (\n !this.tickInterval ||\n this.tickInterval <= 0 ||\n !Number.isFinite(this.tickInterval)\n ) {\n return tickmarks;\n }\n\n for (\n let angle = -180;\n angle < this.maxFOV * 3;\n angle += this.tickInterval\n ) {\n if (cardinalInterval !== 0 && angle % cardinalInterval === 0) {\n continue;\n }\n tickmarks.push({angle: angle * scale, type: TickmarkType.secondary});\n }\n\n return tickmarks;\n }\n\n private generateCardinalTickmarks(\n scale: number,\n labels: Label[]\n ): Tickmark[] {\n const tickmarks: Tickmark[] = [];\n\n for (const label of labels) {\n tickmarks.push({angle: label.x * scale, type: TickmarkType.main});\n }\n\n return tickmarks;\n }\n\n private generateTickmarks(scale: number, labels: Label[]): Tickmark[] {\n return [\n ...this.generateCardinalTickmarks(scale, labels),\n ...this.generateIntervalTickmarks(scale),\n ];\n }\n\n private renderFOVIndicator(): SVGTemplateResult[] {\n const indicators: SVGTemplateResult[] = [];\n\n const maxAdjustment = 10;\n const minContainerWidth = 300;\n const maxContainerWidth = 512;\n\n let yAdjustment = 0;\n if (this.containerWidth < maxContainerWidth) {\n const widthRange = maxContainerWidth - minContainerWidth;\n const scaleFactor =\n (maxContainerWidth - this.containerWidth) / widthRange;\n yAdjustment = scaleFactor * maxAdjustment;\n }\n\n const y = LabelPosition.bottom + yAdjustment + (this.rotType ? 12 : 0);\n\n indicators.push(svg`\n <text x=\"-175\" y=${y} class=\"label left\" fill=${LabelStyle.regular}>\n ${-this.FOV}\\u00B0\n </text>`);\n\n indicators.push(svg`\n <text x=\"0\" y=${y} class=\"label\" fill=${LabelStyle.regular}>\n ${this.heading}\\u00B0\n </text>`);\n\n indicators.push(svg`\n <text x=\"175\" y=${y} class=\"label right\" fill=${LabelStyle.regular}>\n ${this.FOV}\\u00B0\n </text>`);\n\n return indicators;\n }\n\n private priorityFor(element: CompassFlatPriorityElement): 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 get _effectiveRotDegPerMin(): number {\n return this.rateOfTurnDegreesPerMinute ?? this.rotationsPerMinute;\n }\n\n private arrowColorFor(element: CompassFlatPriorityElement): string {\n return this.priorityFor(element) === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n\n private get HDGSvg(): SVGTemplateResult {\n return svg`<g transform=\"translate(-24, -74)\">\n <path d=\"M36.7011 44.1445L36.6898 44.1379L36.6781 44.1318L24.2301 37.6823L24.0001 37.5631L23.7701 37.6823L11.3221 44.1318L11.3104 44.1379L11.2991 44.1445C9.25497 45.3438 6.78661 43.308 7.68828 41.0919L22.6036 4.43285C23.1096 3.18905 24.8906 3.18905 25.3967 4.43284L40.3119 41.0919C41.2136 43.308 38.7452 45.3438 36.7011 44.1445Z\" fill=\"${this.arrowColorFor(CompassFlatPriorityElement.hdg)}\" stroke=\"var(--border-silhouette-color)\"/>\n </g>`;\n }\n\n private COGSvg(translation: number): SVGTemplateResult {\n return svg`\n <g transform=\"translate(${-24 + translation}, -74)\">\n <path d=\"M31.9025 36.0262L33.1068 36.6502L32.5956 35.3938L24.4632 15.406L24.0001 14.2677L23.537 15.406L15.4046 35.3938L14.8935 36.6502L16.0978 36.0262L24.0001 31.9319L31.9025 36.0262ZM36.7011 44.1445L36.6898 44.1379L36.6781 44.1318L24.2301 37.6823L24.0001 37.5631L23.7701 37.6823L11.3221 44.1318L11.3104 44.1379L11.2991 44.1445C9.25497 45.3438 6.78661 43.308 7.68828 41.0919L22.6036 4.43285C23.1096 3.18905 24.8906 3.18905 25.3967 4.43284L40.3119 41.0919C41.2136 43.308 38.7452 45.3438 36.7011 44.1445Z\" fill=\"${this.arrowColorFor(CompassFlatPriorityElement.cog)}\" stroke=\"var(--border-silhouette-color)\"/>\n </g>\n `;\n }\n\n override render() {\n let angleDiff = this.courseOverGround - this.heading;\n\n if (angleDiff > this.maxFOV) {\n angleDiff -= 360;\n } else if (angleDiff < -this.maxFOV) {\n angleDiff += 360;\n }\n\n this.FOV = Math.max(this.minFOV, Math.abs(angleDiff));\n\n const baseOffset = 5;\n const translationScale = (baseOffset * 35) / this.FOV;\n\n const translation = angleDiff * translationScale;\n const labels = this.generateLabels();\n const tickmarks = this.generateTickmarks(translationScale, labels);\n const scaledLabels = labels.map((l) => ({\n ...l,\n x: l.x * translationScale,\n }));\n\n const hasBottomBar = !!this.rotType;\n const arrowViewBoxY = hasBottomBar\n ? -128 + Math.round((12 * 384) / 352)\n : -128;\n const viewBox = `-192 ${arrowViewBoxY} 384 128`;\n\n return html`\n <div class=\"container\" style=\"max-width:${this.maxContainerWidth}px\">\n <obc-watch-flat\n .FOVIndicator=${this.FOVIndicator ? this.renderFOVIndicator() : []}\n .labels=${scaledLabels}\n .rotation=${this.heading}\n .tickmarks=${tickmarks}\n .tickmarkSpacing=${translationScale}\n .bottomBar=${!!this.rotType}\n .rotType=${this.rotType}\n .rotStartX=${0}\n .rotEndX=${(this._effectiveRotDegPerMin / (this.rotMaxValue || 1)) *\n this.rotArcExtent *\n translationScale}\n .rotDotSpacing=${LINEAR_DOT_ANGLE_SPACING * translationScale}\n .rateOfTurnDegreesPerMinute=${this.rateOfTurnDegreesPerMinute}\n .rotDotAnimationFactor=${this.rotDotAnimationFactor}\n .rotationsPerMinute=${this.rotationsPerMinute}\n .rotPriority=${this.priorityFor(CompassFlatPriorityElement.rot)}\n .rotPortStarboard=${this.rotPortStarboard}\n .rotAtZeroDeadband=${this.rotAtZeroDeadband * translationScale}\n ></obc-watch-flat>\n <svg viewBox=${viewBox} xmlns=\"http://www.w3.org/2000/svg\">\n ${this.HDGSvg}${this.COGSvg(translation)}\n </svg>\n </div>\n `;\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-compass-flat': ObcCompassFlat;\n }\n}\n"],"names":["CompassFlatPriorityElement","LabelPosition","LabelStyle"],"mappings":"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"}
1
+ {"version":3,"file":"compass-flat.js","sources":["../../../src/navigation-instruments/compass-flat/compass-flat.ts"],"sourcesContent":["import {LitElement, html, svg, SVGTemplateResult, unsafeCSS} from 'lit';\nimport componentStyle from './compass-flat.css?inline';\nimport {property, state} from 'lit/decorators.js';\nimport {Tickmark, TickmarkType} from '../watch-flat/tickmark-flat.js';\nimport '../watch-flat/watch-flat.js';\nimport {customElement} from '../../decorator.js';\nimport {Priority} from '../types.js';\nimport {\n RotType,\n LINEAR_DOT_ANGLE_SPACING,\n ROT_ZERO_DEADBAND_DEG,\n} from '../rate-of-turn/rot-renderer.js';\n\nexport {RotType};\n\nexport enum CompassFlatPriorityElement {\n hdg = 'hdg',\n cog = 'cog',\n rot = 'rot',\n}\n\nexport enum LabelPosition {\n top = -45,\n bottom = 50,\n}\n\nexport enum LabelStyle {\n regular = 'var(--instrument-tick-mark-secondary-color)',\n}\n\nexport interface Label {\n x: number;\n y: LabelPosition;\n text: string;\n}\n\n/**\n * `<obc-compass-flat>` — Horizontal strip compass with HDG/COG arrows and optional rate-of-turn indicator.\n *\n * Renders a flat (non-circular) compass strip that scrolls horizontally to\n * display the current heading. A filled HDG arrow sits at the center while a\n * hollow COG arrow is positioned at the angular difference. The strip\n * auto-scales its field of view so both arrows remain visible. Cardinal\n * labels (N, S, E, W) and tickmarks are generated at densities responsive to\n * the strip width.\n *\n * ## Features\n *\n * - **Auto-scaling FOV**: The visible compass range widens to keep both HDG\n * and COG arrows in view, bounded by `minFOV` / `maxFOV`.\n * - **HDG / COG arrows**: Filled (HDG) and hollow (COG) arrow SVGs positioned\n * along the strip.\n * - **FOV indicator**: Optional numeric labels showing the port/starboard\n * bearing range and current heading.\n * - **Rate of turn**: Animated linear ROT indicator (spinning dots or\n * horizontal bar) via `rotType`. When enabled, a bottom bar is added to\n * the strip to house the indicator.\n * - **Color priority**: Per-element priority for HDG, COG, and ROT via\n * `priorityElements`.\n *\n *\n * @ignition-base-height: 170px\n * @ignition-base-width: 512px\n * @stable\n */\n@customElement('obc-compass-flat')\nexport class ObcCompassFlat extends LitElement {\n @property({type: Boolean}) FOVIndicator: boolean = false;\n /** Current heading in degrees. */\n @property({type: Number}) heading = 0;\n /** Current COG in degrees. */\n @property({type: Number}) courseOverGround = 0;\n @property({type: Number}) tickInterval = 5;\n @property({type: Number}) FOV = 45;\n @property({type: Number}) minFOV = 45;\n @property({type: Number}) maxFOV = 180;\n @property({type: String}) priority: Priority = Priority.regular;\n @property({type: Array, attribute: false})\n priorityElements: CompassFlatPriorityElement[] = [\n CompassFlatPriorityElement.hdg,\n ];\n /** ROT display mode: `'dots'`, `'bar'`, or `undefined` (hidden). */\n @property({type: String}) rotType: RotType | undefined;\n /**\n * Measured rate of turn in degrees per minute (positive = starboard).\n * When `undefined`, falls back to the deprecated `rotationsPerMinute`.\n * @availableWhen rotType!=undefined\n */\n @property({type: Number}) rateOfTurnDegreesPerMinute: number | undefined;\n /**\n * Visual amplification applied only to the spinning dot animation.\n * @availableWhen rotType!=undefined\n */\n @property({type: Number}) rotDotAnimationFactor: number = 18;\n /**\n * **Deprecated.** Use `rateOfTurnDegreesPerMinute` instead.\n * @deprecated Use `rateOfTurnDegreesPerMinute` instead.\n * @availableWhen rotType!=undefined\n */\n @property({type: Number}) rotationsPerMinute: number = 1;\n /**\n * Bar-extent reference value in **degrees per minute**. Default `60`\n * per ES-TRIN 2025/1 Art. 3.02.\n * @availableWhen rotType!=undefined\n */\n @property({type: Number}) rotMaxValue: number = 60;\n /**\n * Degrees of bar arc per max-value ROT (default 60).\n * @availableWhen rotType!=undefined\n */\n @property({type: Number}) rotArcExtent: number = 60;\n /** @availableWhen rotType!=undefined */\n @property({type: Boolean}) rotPortStarboard: boolean = false;\n /** @availableWhen rotType!=undefined */\n @property({type: Number}) rotAtZeroDeadband: number = ROT_ZERO_DEADBAND_DEG;\n\n @state() private containerWidth = 0;\n @state() private maxContainerWidth = 0;\n\n private resizeObserver: ResizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n // Made by chatGPT so that the text is inside the wrapper\n this.maxContainerWidth = -125.36 + 3.79 * entry.contentRect.height;\n this.containerWidth = Math.min(\n entry.contentRect.width,\n this.maxContainerWidth\n );\n }\n });\n\n override connectedCallback() {\n super.connectedCallback();\n this.resizeObserver.observe(this);\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this.resizeObserver.unobserve(this);\n }\n\n generateLabels() {\n if (this.containerWidth < 192) {\n return [];\n } else if (this.containerWidth <= 300) {\n return [\n {x: -180, y: LabelPosition.top, text: 'S'},\n {x: -90, y: LabelPosition.top, text: 'W'},\n {x: 0, y: LabelPosition.top, text: 'N'},\n {x: 90, y: LabelPosition.top, text: 'E'},\n {x: 180, y: LabelPosition.top, text: 'S'},\n {x: 270, y: LabelPosition.top, text: 'W'},\n {x: 360, y: LabelPosition.top, text: 'N'},\n {x: 450, y: LabelPosition.top, text: 'E'},\n {x: 540, y: LabelPosition.top, text: 'S'},\n ];\n } else {\n return [\n {x: -180, y: LabelPosition.top, text: 'S'},\n {x: -135, y: LabelPosition.top, text: 'SW'},\n {x: -90, y: LabelPosition.top, text: 'W'},\n {x: -45, y: LabelPosition.top, text: 'NW'},\n {x: 0, y: LabelPosition.top, text: 'N'},\n {x: 45, y: LabelPosition.top, text: 'NE'},\n {x: 90, y: LabelPosition.top, text: 'E'},\n {x: 135, y: LabelPosition.top, text: 'SE'},\n {x: 180, y: LabelPosition.top, text: 'S'},\n {x: 225, y: LabelPosition.top, text: 'SW'},\n {x: 270, y: LabelPosition.top, text: 'W'},\n {x: 315, y: LabelPosition.top, text: 'NW'},\n {x: 360, y: LabelPosition.top, text: 'N'},\n {x: 405, y: LabelPosition.top, text: 'NE'},\n {x: 450, y: LabelPosition.top, text: 'E'},\n {x: 495, y: LabelPosition.top, text: 'SE'},\n {x: 540, y: LabelPosition.top, text: 'S'},\n ];\n }\n }\n\n private generateIntervalTickmarks(scale: number): Tickmark[] {\n const tickmarks: Tickmark[] = [];\n let cardinalInterval = 90;\n\n if (this.containerWidth > 300) {\n cardinalInterval = 45;\n } else if (this.containerWidth < 192) {\n cardinalInterval = 0;\n }\n\n // Guard against zero/negative/non-finite interval to prevent infinite loops\n if (\n !this.tickInterval ||\n this.tickInterval <= 0 ||\n !Number.isFinite(this.tickInterval)\n ) {\n return tickmarks;\n }\n\n for (\n let angle = -180;\n angle < this.maxFOV * 3;\n angle += this.tickInterval\n ) {\n if (cardinalInterval !== 0 && angle % cardinalInterval === 0) {\n continue;\n }\n tickmarks.push({angle: angle * scale, type: TickmarkType.secondary});\n }\n\n return tickmarks;\n }\n\n private generateCardinalTickmarks(\n scale: number,\n labels: Label[]\n ): Tickmark[] {\n const tickmarks: Tickmark[] = [];\n\n for (const label of labels) {\n tickmarks.push({angle: label.x * scale, type: TickmarkType.main});\n }\n\n return tickmarks;\n }\n\n private generateTickmarks(scale: number, labels: Label[]): Tickmark[] {\n return [\n ...this.generateCardinalTickmarks(scale, labels),\n ...this.generateIntervalTickmarks(scale),\n ];\n }\n\n private renderFOVIndicator(): SVGTemplateResult[] {\n const indicators: SVGTemplateResult[] = [];\n\n const maxAdjustment = 10;\n const minContainerWidth = 300;\n const maxContainerWidth = 512;\n\n let yAdjustment = 0;\n if (this.containerWidth < maxContainerWidth) {\n const widthRange = maxContainerWidth - minContainerWidth;\n const scaleFactor =\n (maxContainerWidth - this.containerWidth) / widthRange;\n yAdjustment = scaleFactor * maxAdjustment;\n }\n\n const y = LabelPosition.bottom + yAdjustment + (this.rotType ? 12 : 0);\n\n indicators.push(svg`\n <text x=\"-175\" y=${y} class=\"label left\" fill=${LabelStyle.regular}>\n ${-this.FOV}\\u00B0\n </text>`);\n\n indicators.push(svg`\n <text x=\"0\" y=${y} class=\"label\" fill=${LabelStyle.regular}>\n ${this.heading}\\u00B0\n </text>`);\n\n indicators.push(svg`\n <text x=\"175\" y=${y} class=\"label right\" fill=${LabelStyle.regular}>\n ${this.FOV}\\u00B0\n </text>`);\n\n return indicators;\n }\n\n private priorityFor(element: CompassFlatPriorityElement): 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 get _effectiveRotDegPerMin(): number {\n return this.rateOfTurnDegreesPerMinute ?? this.rotationsPerMinute;\n }\n\n private arrowColorFor(element: CompassFlatPriorityElement): string {\n return this.priorityFor(element) === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n\n private get HDGSvg(): SVGTemplateResult {\n return svg`<g transform=\"translate(-24, -74)\">\n <path d=\"M36.7011 44.1445L36.6898 44.1379L36.6781 44.1318L24.2301 37.6823L24.0001 37.5631L23.7701 37.6823L11.3221 44.1318L11.3104 44.1379L11.2991 44.1445C9.25497 45.3438 6.78661 43.308 7.68828 41.0919L22.6036 4.43285C23.1096 3.18905 24.8906 3.18905 25.3967 4.43284L40.3119 41.0919C41.2136 43.308 38.7452 45.3438 36.7011 44.1445Z\" fill=\"${this.arrowColorFor(CompassFlatPriorityElement.hdg)}\" stroke=\"var(--border-silhouette-color)\"/>\n </g>`;\n }\n\n private COGSvg(translation: number): SVGTemplateResult {\n return svg`\n <g transform=\"translate(${-24 + translation}, -74)\">\n <path d=\"M31.9025 36.0262L33.1068 36.6502L32.5956 35.3938L24.4632 15.406L24.0001 14.2677L23.537 15.406L15.4046 35.3938L14.8935 36.6502L16.0978 36.0262L24.0001 31.9319L31.9025 36.0262ZM36.7011 44.1445L36.6898 44.1379L36.6781 44.1318L24.2301 37.6823L24.0001 37.5631L23.7701 37.6823L11.3221 44.1318L11.3104 44.1379L11.2991 44.1445C9.25497 45.3438 6.78661 43.308 7.68828 41.0919L22.6036 4.43285C23.1096 3.18905 24.8906 3.18905 25.3967 4.43284L40.3119 41.0919C41.2136 43.308 38.7452 45.3438 36.7011 44.1445Z\" fill=\"${this.arrowColorFor(CompassFlatPriorityElement.cog)}\" stroke=\"var(--border-silhouette-color)\"/>\n </g>\n `;\n }\n\n override render() {\n let angleDiff = this.courseOverGround - this.heading;\n\n if (angleDiff > this.maxFOV) {\n angleDiff -= 360;\n } else if (angleDiff < -this.maxFOV) {\n angleDiff += 360;\n }\n\n this.FOV = Math.max(this.minFOV, Math.abs(angleDiff));\n\n const baseOffset = 5;\n const translationScale = (baseOffset * 35) / this.FOV;\n\n const translation = angleDiff * translationScale;\n const labels = this.generateLabels();\n const tickmarks = this.generateTickmarks(translationScale, labels);\n const scaledLabels = labels.map((l) => ({\n ...l,\n x: l.x * translationScale,\n }));\n\n const hasBottomBar = !!this.rotType;\n const arrowViewBoxY = hasBottomBar\n ? -128 + Math.round((12 * 384) / 352)\n : -128;\n const viewBox = `-192 ${arrowViewBoxY} 384 128`;\n\n return html`\n <div class=\"container\" style=\"max-width:${this.maxContainerWidth}px\">\n <obc-watch-flat\n .FOVIndicator=${this.FOVIndicator ? this.renderFOVIndicator() : []}\n .labels=${scaledLabels}\n .rotation=${this.heading}\n .tickmarks=${tickmarks}\n .tickmarkSpacing=${translationScale}\n .bottomBar=${!!this.rotType}\n .rotType=${this.rotType}\n .rotStartX=${0}\n .rotEndX=${(this._effectiveRotDegPerMin / (this.rotMaxValue || 1)) *\n this.rotArcExtent *\n translationScale}\n .rotDotSpacing=${LINEAR_DOT_ANGLE_SPACING * translationScale}\n .rateOfTurnDegreesPerMinute=${this.rateOfTurnDegreesPerMinute}\n .rotDotAnimationFactor=${this.rotDotAnimationFactor}\n .rotationsPerMinute=${this.rotationsPerMinute}\n .rotPriority=${this.priorityFor(CompassFlatPriorityElement.rot)}\n .rotPortStarboard=${this.rotPortStarboard}\n .rotAtZeroDeadband=${this.rotAtZeroDeadband * translationScale}\n ></obc-watch-flat>\n <svg viewBox=${viewBox} xmlns=\"http://www.w3.org/2000/svg\">\n ${this.HDGSvg}${this.COGSvg(translation)}\n </svg>\n </div>\n `;\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-compass-flat': ObcCompassFlat;\n }\n}\n"],"names":["CompassFlatPriorityElement","LabelPosition","LabelStyle"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"compass-sector.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/compass-sector/compass-sector.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"compass-sector.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/compass-sector/compass-sector.ts"],"names":[],"mappings":"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"}
@@ -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 {renderInstrumentReadout} from '../readout/instrument-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 {InstrumentState, Priority} from '../types.js';\nexport {RotType, RotPosition};\n\nexport enum CompassSectorPriorityElement {\n hdg = 'hdg',\n cog = 'cog',\n rot = 'rot',\n}\n\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\nfunction normalizeAngle(a: number): number {\n return ((a % 360) + 360) % 360;\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 * @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 /** @availableWhen headingSetpoint!=null */\n @property({type: Number}) newHeadingSetpoint: number | undefined;\n /** @availableWhen headingSetpoint!=null && autoAtHeadingSetpoint==false */\n @property({type: Boolean}) atHeadingSetpoint: boolean = false;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Number}) headingSetpointAtZeroDeadband: number = 0.5;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Boolean}) headingSetpointOverride: boolean = false;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Boolean, attribute: false}) autoAtHeadingSetpoint = true;\n /** @availableWhen headingSetpoint!=null && autoAtHeadingSetpoint==true */\n @property({type: Number}) autoAtHeadingSetpointDeadband: number = 2;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Boolean}) animateSetpoint: boolean = false;\n /** @availableWhen headingSetpoint!=null */\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 /** @availableWhen rotType!=undefined */\n @property({type: String}) rotPosition: RotPosition = RotPosition.innerCircle;\n /**\n * 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 rotType!=undefined\n */\n @property({type: Number}) rateOfTurnDegreesPerMinute: number | undefined;\n /**\n * 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 rotType!=undefined\n */\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 /**\n * Bar-extent reference value in **degrees per minute**. The bar fills the\n * full ±`ARC_HALF_EXTENT` arc when the measured ROT equals\n * ±`rotMaxValue`. Default `60` aligns with ES-TRIN 2025/1 Art. 3.02.\n *\n * Note: the unit changed from rotations per minute to degrees per minute\n * with the introduction of `rateOfTurnDegreesPerMinute`.\n * @availableWhen rotType==bar\n */\n @property({type: Number}) rotMaxValue: number = 60;\n /** @availableWhen rotType!=undefined */\n @property({type: Boolean}) rotPortStarboard: boolean = false;\n /** @availableWhen rotType==bar */\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 /** @availableWhen priority==enhanced */\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 /**\n * 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 */\n @property({type: Boolean}) hasReadout: boolean = false;\n /**\n * Readout label. Default `HDG`.\n * @availableWhen hasReadout==true\n */\n @property({type: String}) label = 'HDG';\n /**\n * Readout unit. Default `DEG`.\n * @availableWhen hasReadout==true\n */\n @property({type: String}) unit = 'DEG';\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 _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 ${this.hasReadout\n ? html`<div class=\"readout\" style=\"top: ${this._readoutTopPercent}%\">\n ${renderInstrumentReadout({\n value: this.heading,\n priority: this.priorityFor(CompassSectorPriorityElement.hdg),\n label: this.label,\n unit: this.unit,\n fractionDigits: this.fractionDigits,\n centerValue: true,\n centerMeta: true,\n })}\n </div>`\n : nothing}\n </div>\n `;\n }\n\n static override styles = [\n unsafeCSS(instrumentReadoutStyle),\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 componentStyle from './compass-sector.css?inline';\nimport '../watch/watch.js';\nimport {renderInstrumentReadout} from '../readout/instrument-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 {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 both the zoomed and un-zoomed paths. This component\n// deliberately keeps its bespoke FOV-compression geometry and does NOT use\n// svghelpers/radial-frame.ts: the viewBox is cached per FOV (a\n// container-size-dependent label reserve would invalidate that), and the\n// 72-unit padding covers the 3-char degree labels at typical sizes.\n// TODO(#1021): adopt computeRadialFrame if degree labels ever clip when the\n// component is shrunk far below its design size.\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\nfunction normalizeAngle(a: number): number {\n return ((a % 360) + 360) % 360;\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 * @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 /** @availableWhen headingSetpoint!=null */\n @property({type: Number}) newHeadingSetpoint: number | undefined;\n /** @availableWhen headingSetpoint!=null && autoAtHeadingSetpoint==false */\n @property({type: Boolean}) atHeadingSetpoint: boolean = false;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Number}) headingSetpointAtZeroDeadband: number = 0.5;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Boolean}) headingSetpointOverride: boolean = false;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Boolean, attribute: false}) autoAtHeadingSetpoint = true;\n /** @availableWhen headingSetpoint!=null && autoAtHeadingSetpoint==true */\n @property({type: Number}) autoAtHeadingSetpointDeadband: number = 2;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Boolean}) animateSetpoint: boolean = false;\n /** @availableWhen headingSetpoint!=null */\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 /** @availableWhen rotType!=undefined */\n @property({type: String}) rotPosition: RotPosition = RotPosition.innerCircle;\n /**\n * 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 rotType!=undefined\n */\n @property({type: Number}) rateOfTurnDegreesPerMinute: number | undefined;\n /**\n * 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 rotType!=undefined\n */\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 /**\n * Bar-extent reference value in **degrees per minute**. The bar fills the\n * full ±`ARC_HALF_EXTENT` arc when the measured ROT equals\n * ±`rotMaxValue`. Default `60` aligns with ES-TRIN 2025/1 Art. 3.02.\n *\n * Note: the unit changed from rotations per minute to degrees per minute\n * with the introduction of `rateOfTurnDegreesPerMinute`.\n * @availableWhen rotType==bar\n */\n @property({type: Number}) rotMaxValue: number = 60;\n /** @availableWhen rotType!=undefined */\n @property({type: Boolean}) rotPortStarboard: boolean = false;\n /** @availableWhen rotType==bar */\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 /** @availableWhen priority==enhanced */\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 /**\n * 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 */\n @property({type: Boolean}) hasReadout: boolean = false;\n /**\n * Readout label. Default `HDG`.\n * @availableWhen hasReadout==true\n */\n @property({type: String}) label = 'HDG';\n /**\n * Readout unit. Default `DEG`.\n * @availableWhen hasReadout==true\n */\n @property({type: String}) unit = 'DEG';\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 _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 ${this.hasReadout\n ? html`<div class=\"readout\" style=\"top: ${this._readoutTopPercent}%\">\n ${renderInstrumentReadout({\n value: this.heading,\n priority: this.priorityFor(CompassSectorPriorityElement.hdg),\n label: this.label,\n unit: this.unit,\n fractionDigits: this.fractionDigits,\n centerValue: true,\n centerMeta: true,\n })}\n </div>`\n : nothing}\n </div>\n `;\n }\n\n static override styles = [\n unsafeCSS(instrumentReadoutStyle),\n unsafeCSS(componentStyle),\n ];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-compass-sector': ObcCompassSector;\n }\n}\n"],"names":["CompassSectorPriorityElement"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA2BO,IAAK,iDAAAA,kCAAL;AACLA,gCAAA,KAAA,IAAM;AACNA,gCAAA,KAAA,IAAM;AACNA,gCAAA,KAAA,IAAM;AAHI,SAAAA;AAAA,GAAA,gCAAA,CAAA,CAAA;AAaZ,MAAM,UAAU;AAChB,MAAM,aAAa,gBAAgB;AACnC,MAAM,eAAe,mBAAmB,UAAU;AAElD,MAAM,kBAAkB;AACxB,MAAM,qBAAqB,mBAAmB,gBAAgB,MAAM;AAQpE,SAAS,kBAAkB,KAA0B;AACnD,MAAI,OAAO,IAAI;AACb,WAAO,EAAC,cAAc,IAAI,iBAAiB,GAAG,mBAAmB,EAAA;AAAA,EACnE,WAAW,OAAO,IAAI;AACpB,WAAO,EAAC,cAAc,IAAI,iBAAiB,GAAG,mBAAmB,OAAA;AAAA,EACnE,WAAW,OAAO,KAAK;AACrB,WAAO,EAAC,cAAc,IAAI,iBAAiB,IAAI,mBAAmB,EAAA;AAAA,EACpE,OAAO;AACL,WAAO,EAAC,cAAc,IAAI,iBAAiB,IAAI,mBAAmB,GAAA;AAAA,EACpE;AACF;AAEA,SAAS,eAAe,GAAmB;AACzC,UAAS,IAAI,MAAO,OAAO;AAC7B;AAyCO,IAAM,mBAAN,cAA+B,WAAW;AAAA,EAA1C,cAAA;AAAA,UAAA,GAAA,SAAA;AACqB,SAAA,UAAU;AACV,SAAA,mBAAmB;AAEnB,SAAA,kBAAiC;AAIhC,SAAA,oBAA6B;AAE9B,SAAA,gCAAwC;AAEvC,SAAA,0BAAmC;AAEjB,SAAA,wBAAwB;AAE3C,SAAA,gCAAwC;AAEvC,SAAA,kBAA2B;AAE3B,SAAA,WAAoB;AACJ,SAAA,iBAAgC,CAAA;AAEjD,SAAA,SAAiB;AAIjB,SAAA,cAA2B,YAAY;AAevC,SAAA,wBAAgC;AAOhC,SAAA,qBAA6B;AAU7B,SAAA,cAAsB;AAErB,SAAA,mBAA4B;AAE7B,SAAA,oBAA4B;AAE5B,SAAA,QAAyB,gBAAgB;AACzC,SAAA,WAAqB,SAAS;AAGxD,SAAA,mBAAmD;AAAA,MACjD;AAAA;AAAA,IAAA;AAEyB,SAAA,kBAA2B;AAC3B,SAAA,eAAwB;AAMxB,SAAA,aAAsB;AAKvB,SAAA,QAAQ;AAKR,SAAA,OAAO;AAKP,SAAA,iBAAiB;AAE3C,SAAQ,aAAa,IAAI,eAAe;AAAA,MACtC,mBAAmB;AAAA,MACnB,gBAAgB,MAAM,KAAK,cAAA;AAAA,IAAc,CAC1C;AAGD,SAAQ,WAAW;AACnB,SAAQ,iBAAiB;AACzB,SAAQ,SAAS;AACjB,SAAQ,gBAAgB;AACxB,SAAQ,iBAAiB;AAEzB,SAAQ,eAA4B,CAAA;AACpC,SAAQ,mBAA+B,CAAA;AACvC,SAAQ,iBAAmC,CAAA;AAAA,EAAC;AAAA,EAEnC,WAAW,SAA+B;AACjD,UAAM,WAAW,OAAO;AACxB,SAAK,WAAW,KAAK;AAAA,MACnB,UAAU,KAAK,mBAAmB;AAAA,MAClC,aAAa,KAAK;AAAA,MAClB,YAAY,KAAK;AAAA,MACjB,UAAU,KAAK;AAAA,MACf,gBAAgB,KAAK;AAAA,MACrB,wBAAwB,KAAK;AAAA,MAC7B,wBAAwB,KAAK;AAAA,MAC7B,kBAAkB,KAAK;AAAA,MACvB,iBAAiB,KAAK;AAAA,IAAA,CACvB;AAED,UAAM,mBACJ,QAAQ,IAAI,SAAS,KACrB,QAAQ,IAAI,kBAAkB,KAC9B,QAAQ,IAAI,QAAQ,KACpB,QAAQ,IAAI,cAAc;AAE5B,QAAI,kBAAkB;AACpB,UAAI,OAAO,KAAK,mBAAmB,KAAK;AACxC,UAAI,OAAO,IAAK,SAAQ;AAAA,eACf,OAAO,KAAM,SAAQ;AAC9B,YAAM,SAAS,KAAK,IAAI,GAAG,KAAK,MAAM;AACtC,YAAM,SAAS;AAEf,UAAI,KAAK,cAAc;AACrB,cAAM,SAAS,KAAK,IAAI,QAAQ,KAAK,IAAI,IAAI,IAAI,MAAM;AACvD,YAAI,UAAU,iBAAiB;AAC7B,eAAK,WAAW;AAChB,eAAK,iBAAiB;AACtB,eAAK,SAAS;AAAA,QAChB,OAAO;AACL,eAAK,WAAW;AAChB,eAAK,iBAAiB;AACtB,eAAK,SAAS,kBAAkB;AAAA,QAClC;AAAA,MACF,OAAO;AACL,aAAK,WAAW,KAAK,IAAI,QAAQ,KAAK,IAAI,IAAI,CAAC;AAC/C,aAAK,iBAAiB;AACtB,aAAK,SAAS,kBAAkB,KAAK;AAAA,MACvC;AAEA,WAAK,eAAe;AAAA,QAClB;AAAA,UACE,YAAY,KAAK,UAAU,KAAK;AAAA,UAChC,UAAU,KAAK,UAAU,KAAK;AAAA,UAC9B,gBAAgB;AAAA,UAChB,iBAAiB;AAAA,QAAA;AAAA,MACnB;AAGF,WAAK,gBAAA;AACL,WAAK,mBAAmB,KAAK,gBAAA;AAAA,IAC/B;AAEA,QAAI,oBAAoB,QAAQ,IAAI,gBAAgB,GAAG;AACrD,WAAK,iBAAiB,KAAK,cAAA;AAAA,IAC7B;AAAA,EACF;AAAA,EAES,uBAA6B;AACpC,UAAM,qBAAA;AACN,SAAK,WAAW,QAAA;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAMQ,UAAU,YAA4B;AAC5C,QAAI,OAAO,aAAa,KAAK;AAC7B,QAAI,OAAO,IAAK,SAAQ;AAAA,aACf,OAAO,KAAM,SAAQ;AAC9B,WAAO,KAAK,UAAU,OAAO,KAAK;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,kBAA8B;AACpC,UAAM,MAAM,KAAK,WAAW;AAC5B,UAAM,EAAC,cAAc,iBAAiB,kBAAA,IACpC,kBAAkB,GAAG;AACvB,UAAM,UAAU,KAAK;AACrB,UAAM,eAAe,KAAK,UAAU;AACpC,UAAM,aAAa,KAAK,UAAU;AAElC,UAAM,YAAwB,CAAA;AAC9B,UAAM,4BAAY,IAAA;AAElB,UAAM,UAAU,CACd,UACA,MACA,SACS;AACT,YAAM,MAAM,KAAK,MAAM,WAAW,GAAI;AACtC,UAAI,MAAM,IAAI,GAAG,EAAG;AACpB,YAAM,IAAI,GAAG;AACb,gBAAU,KAAK,EAAC,OAAO,UAAU,MAAM,MAAK;AAAA,IAC9C;AAEA,UAAM,OAAO,qBAAqB;AAClC,UAAM,YAAY,KAAK,KAAK,eAAe,IAAI,IAAI;AAEnD,aACM,aAAa,WACjB,cAAc,YACd,cAAc,MACd;AACA,YAAM,OAAO,eAAe,UAAU;AACtC,YAAM,WAAW,KAAK,UAAU,UAAU;AAC1C,YAAM,SAAS,OAAO,iBAAiB;AACvC,YAAM,YAAY,OAAO,oBAAoB;AAE7C,UAAI,QAAQ;AACV,gBAAQ,UAAU,aAAa,MAAM,KAAK,MAAM,IAAI,EAAE,UAAU;AAAA,MAClE,WAAW,WAAW;AACpB,gBAAQ,UAAU,aAAa,OAAO;AAAA,MACxC,OAAO;AACL,gBAAQ,UAAU,aAAa,SAAS;AAAA,MAC1C;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAMQ,kBAAwB;AAC9B,QAAI,KAAK,cAAc;AACrB,YAAM,cAAc,MAAM,WAAW;AACrC,YAAM,QAAQ,yBAAyB;AAAA,QACrC,OAAO,KAAK;AAAA,QACZ,aAAa;AAAA,QACb,aAAa;AAAA,QACb,WAAW;AAAA,QACX;AAAA,MAAA,CACD;AACD,WAAK,gBAAgB,MAAM;AAC3B,WAAK,iBAAiB,MAAM;AAC5B,WAAK,kBAAkB;AAAA,IACzB,OAAO;AACL,WAAK,gBAAgB;AACrB,YAAM,SAAS,MAAM,WAAW;AAChC,WAAK,iBAAiB,IAAI,QAAQ,CAAC,KAAK,QAAQ,CAAC,IAAI,KAAK,IAAI,KAAK;AACnE,WAAK,kBAAkB;AAAA,IACzB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMQ,kBAAkB,MAAc;AACtC,QAAI,cAAc,CAAC,KAAK;AACxB,QAAI,cAAc,IAAK,gBAAe;AAAA,aAC7B,cAAc,KAAM,gBAAe;AAC5C,QAAI,KAAK,IAAI,WAAW,IAAI,KAAK,SAAU,QAAO;AAElD,UAAM,gBAAgB,KAAK,UAAU,CAAC;AACtC,UAAM,SAAS,oBAAoB;AACnC,WAAO;AAAA,6BACkB,aAAa,kBAAkB,CAAC,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMjE;AAAA;AAAA;AAAA;AAAA,EAMQ,cAAc,OAAe,KAAa,KAAsB;AACtE,UAAM,IAAI,eAAe,KAAK;AAC9B,UAAM,QAAQ,eAAe,GAAG;AAChC,UAAM,MAAM,eAAe,GAAG;AAC9B,WAAO,SAAS,MAAM,KAAK,SAAS,KAAK,MAAM,KAAK,SAAS,KAAK;AAAA,EACpE;AAAA,EAEQ,gBAAkC;AACxC,WAAO,KAAK,eAAe,IAAI,CAAC,EAAC,UAAU,UAAU,QAAQ,WAAU;AACrE,YAAM,QAAQ,KAAK,cAAc,KAAK,SAAS,UAAU,QAAQ,IAC7D,YAAY,YACZ,SACE,YAAY,SACZ,YAAY;AAClB,aAAO;AAAA,QACL,UAAU,KAAK,UAAU,QAAQ;AAAA,QACjC,UAAU,KAAK,UAAU,QAAQ;AAAA,QACjC;AAAA,QACA;AAAA,MAAA;AAAA,IAEJ,CAAC;AAAA,EACH;AAAA,EAEA,IAAY,yBAAiC;AAC3C,WAAO,KAAK,8BAA8B,KAAK;AAAA,EACjD;AAAA,EAEA,IAAY,eAAuB;AACjC,UAAM,SAAS,KAAK,eAAe;AACnC,UAAM,gBACH,KAAK,yBAAyB,SAAU;AAC3C,WAAO,KAAK,UAAU,KAAK,UAAU,aAAa;AAAA,EACpD;AAAA,EAEQ,YAAY,SAAiD;AACnE,UAAM,WAAW,MAAM,QAAQ,KAAK,gBAAgB,IAChD,KAAK,mBACL,CAAA;AACJ,WAAO,SAAS,SAAS,OAAO,IAAI,KAAK,WAAW,SAAS;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,IAAY,qBAA6B;AACvC,QAAI,KAAK,cAAc;AACrB,aAAO;AAAA,IACT;AACA,UAAM,CAAA,EAAG,MAAM,EAAE,IAAI,KAAK,eAAe,MAAM,GAAG,EAAE,IAAI,MAAM;AAC9D,QAAI,CAAC,MAAM,OAAO,MAAM,EAAE,GAAG;AAC3B,aAAO;AAAA,IACT;AACA,UAAM,UAAU,CAAC,eAAe;AAChC,WAAO,KAAK,OAAQ,UAAU,MAAM,KAAM,GAAI,IAAI;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAMS,SAAS;AAChB,UAAM,WAAW,CAAC,KAAK;AACvB,UAAM,UAAU,KAAK;AACrB,UAAM,OAAO,KAAK;AAElB,UAAM,YAAY,KAAK,UAAU,KAAK,gBAAgB;AACtD,UAAM,iBACJ,KAAK,mBAAmB,OACpB,KAAK,UAAU,KAAK,eAAe,IACnC;AACN,UAAM,oBACJ,KAAK,sBAAsB,OACvB,KAAK,UAAU,KAAK,kBAAkB,IACtC;AAEN,WAAO;AAAA;AAAA;AAAA,sBAGW,KAAK,QAAQ;AAAA,qBACd,OAAO;AAAA,qBACP,KAAK,cAAc;AAAA,uBACjB,KAAK,gBAAgB;AAAA,2BACjB,cAAc,OAAO;AAAA,6BACnB,KAAK,eAAe;AAAA,mBAC9B,KAAK,KAAK;AAAA,6BACA,UAAU;AAAA,wBACf,KAAK;AAAA,mBACV,KAAK,YAAY;AAAA,sBACd,KAAK,eAAe;AAAA,0BAChB,KAAK,YAAY;AAAA,2BAChB,KAAK,iBAAiB,GAAG;AAAA,sBAC9B,QAAQ;AAAA,2BACH,cAAc;AAAA,8BACX,iBAAiB;AAAA,6BAClB,KAAK,WAAW,kBAAkB,KAAK,OAAO,CAAC;AAAA,yCACnC,KAAK,6BAA6B;AAAA,8BAC7C,KAAK,uBAAuB;AAAA,sBACpC,KAAK,QAAQ;AAAA,6BACN,KAAK,eAAe;AAAA,qBAC5B,KAAK,OAAO;AAAA,yBACR,KAAK,WAAW;AAAA,2BACd,KAAK,OAAO;AAAA,yBACd,KAAK,YAAY;AAAA,yBACjB,KAAK;AAAA,MAAY;AAAA;AAAA,IAAA,CAAiC;AAAA,8BAC7C,KAAK,gBAAgB;AAAA,+BACpB,KAAK,iBAAiB;AAAA,wCACb,KAAK,0BAA0B;AAAA,mCACpC,KAAK,qBAAqB;AAAA,gCAC7B,KAAK,kBAAkB;AAAA;AAAA;AAAA,wBAG/B,OAAO,uBAAuB,QAAQ;AAAA,iCAC7B,KAAK,OAAO;AAAA;AAAA;AAAA,oBAGzB,EAAE,qBAAqB,KAAK;AAAA;AAAA,oBAE5B,EAAE,eAAe,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAM9B,KAAK,kBAAkB,IAAI,CAAC;AAAA,YAC5B;AAAA,MACA,WAAW;AAAA,MACX,KAAK;AAAA,MACL,KAAK;AAAA,QAAY;AAAA;AAAA,MAAA;AAAA,MACjB;AAAA,IAAA,CACD;AAAA,YACC;AAAA,MACA,WAAW;AAAA,MACX;AAAA,MACA,KAAK;AAAA,QAAY;AAAA;AAAA,MAAA;AAAA,MACjB;AAAA,IAAA,CACD;AAAA;AAAA,UAED,KAAK,aACH,wCAAwC,KAAK,kBAAkB;AAAA,gBAC3D,wBAAwB;AAAA,MACxB,OAAO,KAAK;AAAA,MACZ,UAAU,KAAK;AAAA,QAAY;AAAA;AAAA,MAAA;AAAA,MAC3B,OAAO,KAAK;AAAA,MACZ,MAAM,KAAK;AAAA,MACX,gBAAgB,KAAK;AAAA,MACrB,aAAa;AAAA,MACb,YAAY;AAAA,IAAA,CACb,CAAC;AAAA,sBAEJ,OAAO;AAAA;AAAA;AAAA,EAGjB;AAMF;AAjda,iBA6cK,SAAS;AAAA,EACvB,UAAU,sBAAsB;AAAA,EAChC,UAAU,cAAc;AAC1B;AA/c0B,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GADb,iBACe,WAAA,WAAA,CAAA;AACA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAFb,iBAEe,WAAA,oBAAA,CAAA;AAEA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAJb,iBAIe,WAAA,mBAAA,CAAA;AAEA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GANb,iBAMe,WAAA,sBAAA,CAAA;AAEC,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GARd,iBAQgB,WAAA,qBAAA,CAAA;AAED,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAVb,iBAUe,WAAA,iCAAA,CAAA;AAEC,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GAZd,iBAYgB,WAAA,2BAAA,CAAA;AAEkB,gBAAA;AAAA,EAA5C,SAAS,EAAC,MAAM,SAAS,WAAW,OAAM;AAAA,GAdhC,iBAckC,WAAA,yBAAA,CAAA;AAEnB,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAhBb,iBAgBe,WAAA,iCAAA,CAAA;AAEC,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GAlBd,iBAkBgB,WAAA,mBAAA,CAAA;AAEA,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GApBd,iBAoBgB,WAAA,YAAA,CAAA;AACgB,gBAAA;AAAA,EAA1C,SAAS,EAAC,MAAM,OAAO,WAAW,OAAM;AAAA,GArB9B,iBAqBgC,WAAA,kBAAA,CAAA;AAEjB,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAvBb,iBAuBe,WAAA,UAAA,CAAA;AAEA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAzBb,iBAyBe,WAAA,WAAA,CAAA;AAEA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GA3Bb,iBA2Be,WAAA,eAAA,CAAA;AAQA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAnCb,iBAmCe,WAAA,8BAAA,CAAA;AAOA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GA1Cb,iBA0Ce,WAAA,yBAAA,CAAA;AAOA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAjDb,iBAiDe,WAAA,sBAAA,CAAA;AAUA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GA3Db,iBA2De,WAAA,eAAA,CAAA;AAEC,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GA7Dd,iBA6DgB,WAAA,oBAAA,CAAA;AAED,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GA/Db,iBA+De,WAAA,qBAAA,CAAA;AAEA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAjEb,iBAiEe,WAAA,SAAA,CAAA;AACA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAlEb,iBAkEe,WAAA,YAAA,CAAA;AAG1B,gBAAA;AAAA,EADC,SAAS,EAAC,MAAM,OAAO,WAAW,OAAM;AAAA,GApE9B,iBAqEX,WAAA,oBAAA,CAAA;AAG2B,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GAxEd,iBAwEgB,WAAA,mBAAA,CAAA;AACA,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GAzEd,iBAyEgB,WAAA,gBAAA,CAAA;AAMA,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GA/Ed,iBA+EgB,WAAA,cAAA,CAAA;AAKD,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GApFb,iBAoFe,WAAA,SAAA,CAAA;AAKA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAzFb,iBAyFe,WAAA,QAAA,CAAA;AAKA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GA9Fb,iBA8Fe,WAAA,kBAAA,CAAA;AA9Ff,mBAAN,gBAAA;AAAA,EADN,cAAc,oBAAoB;AAAA,GACtB,gBAAA;"}
@@ -9,6 +9,14 @@ const componentStyle = css`* {
9
9
  height: 100%;
10
10
  }
11
11
 
12
+ /* With a pinned face the host shrink-wraps the fixed-size dial, so rows of
13
+ pinned instruments can sit side by side in flex layouts. */
14
+
15
+ :host([face-diameter]) {
16
+ width: fit-content;
17
+ height: fit-content;
18
+ }
19
+
12
20
  .gauge-radial-root {
13
21
  /* Readout vertical placement per layout (% of the cropped box), tuned to the
14
22
  watch geometry — re-check if the ring radii or the 448 box change. Which
@@ -29,7 +37,10 @@ const componentStyle = css`* {
29
37
  height: auto;
30
38
  max-width: 100%;
31
39
  max-height: 100%;
32
- aspect-ratio: 1;
40
+ /* --gauge-radial-aspect is set from TS only when the frame lowered a crop
41
+ for the label drop (frame.clipsAdjusted); otherwise the static sector
42
+ aspect below applies. */
43
+ aspect-ratio: var(--gauge-radial-aspect, 1);
33
44
 
34
45
  /* Defaults (centered both ways); overridden by the halign-* / valign-*
35
46
  classes. Horizontal alignment uses auto margins (which reference the host
@@ -45,7 +56,7 @@ const componentStyle = css`* {
45
56
  }
46
57
 
47
58
  .gauge-radial-root.sector-180 {
48
- aspect-ratio: 448 / 251;
59
+ aspect-ratio: var(--gauge-radial-aspect, 448 / 251);
49
60
  }
50
61
 
51
62
  .gauge-radial-root.halign-left {
@@ -78,6 +89,27 @@ const componentStyle = css`* {
78
89
  transform: translateY(-100%);
79
90
  }
80
91
 
92
+ /* faceDiameter pins the dial to a fixed intrinsic size: the inner
93
+ instrument sets its own px box and the root shrink-wraps it. The host
94
+ shrink-wraps too, so there is no slack to align within — neutralize the
95
+ alignment offsets (declared after the valign rules to win the cascade;
96
+ \`top: 50%\` would resolve to 0 in the auto-height host anyway while the
97
+ translateY still applied, shifting the dial up by half its height). */
98
+
99
+ .gauge-radial-root.face-pinned {
100
+ width: fit-content;
101
+ height: fit-content;
102
+ max-width: none;
103
+ max-height: none;
104
+ aspect-ratio: auto;
105
+ top: 0;
106
+ transform: none;
107
+ }
108
+
109
+ .gauge-radial-root.face-pinned.sector-180 {
110
+ aspect-ratio: auto;
111
+ }
112
+
81
113
  .gauge-radial-root .gauge-readout-value {
82
114
  position: absolute;
83
115
  left: 50%;
@@ -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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -145,6 +145,14 @@ export declare class ObcGaugeRadial extends ObcGaugeRadial_base {
145
145
  label: string;
146
146
  unit: string;
147
147
  fractionDigits: number;
148
+ /**
149
+ * Outer-ring diameter in CSS pixels. When set, the instrument renders at a
150
+ * fixed intrinsic size derived from the ring, arc shape and label reserve —
151
+ * so instruments sharing the same value have identical ring circumference
152
+ * regardless of label width or arc extent (like obc-donut-chart's
153
+ * fixedHeight). When unset (default), the instrument fills its container.
154
+ */
155
+ faceDiameter: number | undefined;
148
156
  private get sectorAngles();
149
157
  /**
150
158
  * Per-edge crop (%) of the shared, origin-centered 448 SVG box each sector
@@ -154,6 +162,13 @@ export declare class ObcGaugeRadial extends ObcGaugeRadial_base {
154
162
  */
155
163
  private get sectorClips();
156
164
  private get isSector90();
165
+ /** @internal */
166
+ private _rootEl?;
167
+ /**
168
+ * Re-anchor the %-positioned readouts against the frame the inner
169
+ * instrument actually rendered (the box grows when labels need room).
170
+ */
171
+ private _onFrameChanged;
157
172
  getAngle: (v: number) => number;
158
173
  /** Renders one gauge readout; `withMeta`/`withValue` pick parts. */
159
174
  private renderReadout;
@@ -1 +1 @@
1
- {"version":3,"file":"gauge-radial.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/gauge-radial/gauge-radial.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAA4B,KAAK,cAAc,EAAC,MAAM,KAAK,CAAC;AAK9E,OAAO,EAAC,UAAU,EAAC,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAC,eAAe,EAAE,QAAQ,EAAC,MAAM,aAAa,CAAC;AAEtD,OAAO,8DAA8D,CAAC;AACtE,OAAO,EAAC,aAAa,EAAC,MAAM,sBAAsB,CAAC;AAInD,oBAAY,kBAAkB;IAC5B,MAAM,WAAW;IACjB,GAAG,QAAQ;IACX,MAAM,WAAW;CAClB;AAED,oBAAY,iBAAiB;IAC3B,MAAM,QAAQ;IACd,MAAM,QAAQ;IACd,SAAS,YAAY;IACrB,UAAU,aAAa;CACxB;AAED,oBAAY,8BAA8B;IACxC,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,KAAK,UAAU;CAChB;AAED,oBAAY,4BAA4B;IACtC,GAAG,QAAQ;IACX,MAAM,WAAW;IACjB,MAAM,WAAW;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CACjB;;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwEG;AACH,qBACa,cAAe,SAAQ,mBAAyB;IACjC,KAAK,SAAK;IACV,QAAQ,SAAO;IACf,QAAQ,SAAK;IACZ,UAAU,EAAE,OAAO,CAAS;IAC7B,uBAAuB,SAAM;IAC7B,yBAAyB,SAAM;IACzD;;;OAGG;IACuB,wBAAwB,EAAE,MAAM,GAAG,SAAS,CAC1D;IACc,KAAK,EAAE,eAAe,CAA0B;IAChD,QAAQ,EAAE,QAAQ,CAAoB;IACtC,IAAI,EAAE,kBAAkB,CACtB;IACD,eAAe,EAAE,OAAO,CAAS;IAClC,aAAa,EAAE,aAAa,CAC9B;IACxB,qEAAqE;IAC1B,OAAO,EAAE,iBAAiB,EAAE,CAAM;IACpC,MAAM,EAAE,iBAAiB,CACvC;IAC3B;;;;OAIG;IAEH,mBAAmB,EAAE,8BAA8B,CACX;IACxC;;;;OAIG;IACuB,iBAAiB,EAAE,4BAA4B,CACnC;IACtC;;;;OAIG;IACwB,UAAU,UAAS;IACpB,KAAK,SAAM;IACX,IAAI,SAAM;IACV,cAAc,SAAK;IAE7C,OAAO,KAAK,YAAY,GAYvB;IAED;;;;;OAKG;IACH,OAAO,KAAK,WAAW,GAiBtB;IAED,OAAO,KAAK,UAAU,GAKrB;IAID,QAAQ,GAAI,GAAG,MAAM,KAAG,MAAM,CAQ5B;IAEF,oEAAoE;IACpE,OAAO,CAAC,aAAa;IA0BrB,OAAO,CAAC,cAAc;IA+Cb,MAAM;IAkDf,OAAgB,MAAM,0BAA6B;CACpD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,kBAAkB,EAAE,cAAc,CAAC;KACpC;CACF"}
1
+ {"version":3,"file":"gauge-radial.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/gauge-radial/gauge-radial.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAA4B,KAAK,cAAc,EAAC,MAAM,KAAK,CAAC;AAM9E,OAAO,EAAC,UAAU,EAAC,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAC,eAAe,EAAE,QAAQ,EAAC,MAAM,aAAa,CAAC;AAEtD,OAAO,8DAA8D,CAAC;AACtE,OAAO,EAAC,aAAa,EAAC,MAAM,sBAAsB,CAAC;AAInD,oBAAY,kBAAkB;IAC5B,MAAM,WAAW;IACjB,GAAG,QAAQ;IACX,MAAM,WAAW;CAClB;AAED,oBAAY,iBAAiB;IAC3B,MAAM,QAAQ;IACd,MAAM,QAAQ;IACd,SAAS,YAAY;IACrB,UAAU,aAAa;CACxB;AAED,oBAAY,8BAA8B;IACxC,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,KAAK,UAAU;CAChB;AAED,oBAAY,4BAA4B;IACtC,GAAG,QAAQ;IACX,MAAM,WAAW;IACjB,MAAM,WAAW;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CACjB;;AAaD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwEG;AACH,qBACa,cAAe,SAAQ,mBAAyB;IACjC,KAAK,SAAK;IACV,QAAQ,SAAO;IACf,QAAQ,SAAK;IACZ,UAAU,EAAE,OAAO,CAAS;IAC7B,uBAAuB,SAAM;IAC7B,yBAAyB,SAAM;IACzD;;;OAGG;IACuB,wBAAwB,EAAE,MAAM,GAAG,SAAS,CAC1D;IACc,KAAK,EAAE,eAAe,CAA0B;IAChD,QAAQ,EAAE,QAAQ,CAAoB;IACtC,IAAI,EAAE,kBAAkB,CACtB;IACD,eAAe,EAAE,OAAO,CAAS;IAClC,aAAa,EAAE,aAAa,CAC9B;IACxB,qEAAqE;IAC1B,OAAO,EAAE,iBAAiB,EAAE,CAAM;IACpC,MAAM,EAAE,iBAAiB,CACvC;IAC3B;;;;OAIG;IAEH,mBAAmB,EAAE,8BAA8B,CACX;IACxC;;;;OAIG;IACuB,iBAAiB,EAAE,4BAA4B,CACnC;IACtC;;;;OAIG;IACwB,UAAU,UAAS;IACpB,KAAK,SAAM;IACX,IAAI,SAAM;IACV,cAAc,SAAK;IAC7C;;;;;;OAMG;IAEH,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IAEjC,OAAO,KAAK,YAAY,GAYvB;IAED;;;;;OAKG;IACH,OAAO,KAAK,WAAW,GAiBtB;IAED,OAAO,KAAK,UAAU,GAKrB;IAED,gBAAgB;IACa,OAAO,CAAC,OAAO,CAAC,CAAc;IAE3D;;;OAGG;IACH,OAAO,CAAC,eAAe,CAyBrB;IAIF,QAAQ,GAAI,GAAG,MAAM,KAAG,MAAM,CAQ5B;IAEF,oEAAoE;IACpE,OAAO,CAAC,aAAa;IA0BrB,OAAO,CAAC,cAAc;IA+Cb,MAAM;IAqDf,OAAgB,MAAM,0BAA6B;CACpD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,kBAAkB,EAAE,cAAc,CAAC;KACpC;CACF"}