@oicl/openbridge-webcomponents 2.0.0-next.102 → 2.0.0-next.104

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 (46) hide show
  1. package/bundle/openbridge-webcomponents.bundle.js +583 -145
  2. package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
  3. package/custom-elements.json +338 -8
  4. package/dist/building-blocks/instrument-radial/instrument-radial.d.ts +22 -2
  5. package/dist/building-blocks/instrument-radial/instrument-radial.d.ts.map +1 -1
  6. package/dist/building-blocks/instrument-radial/instrument-radial.js +61 -37
  7. package/dist/building-blocks/instrument-radial/instrument-radial.js.map +1 -1
  8. package/dist/components/modal-window/modal-window.css.js +4 -2
  9. package/dist/components/modal-window/modal-window.css.js.map +1 -1
  10. package/dist/navigation-instruments/azimuth-thruster/azimuth-thruster.d.ts +14 -0
  11. package/dist/navigation-instruments/azimuth-thruster/azimuth-thruster.d.ts.map +1 -1
  12. package/dist/navigation-instruments/azimuth-thruster/azimuth-thruster.js +30 -11
  13. package/dist/navigation-instruments/azimuth-thruster/azimuth-thruster.js.map +1 -1
  14. package/dist/navigation-instruments/compass/compass.d.ts +21 -1
  15. package/dist/navigation-instruments/compass/compass.d.ts.map +1 -1
  16. package/dist/navigation-instruments/compass/compass.js +36 -16
  17. package/dist/navigation-instruments/compass/compass.js.map +1 -1
  18. package/dist/navigation-instruments/compass-sector/compass-sector.d.ts.map +1 -1
  19. package/dist/navigation-instruments/compass-sector/compass-sector.js.map +1 -1
  20. package/dist/navigation-instruments/gauge-radial/gauge-radial.css.js +34 -2
  21. package/dist/navigation-instruments/gauge-radial/gauge-radial.css.js.map +1 -1
  22. package/dist/navigation-instruments/gauge-radial/gauge-radial.d.ts +15 -0
  23. package/dist/navigation-instruments/gauge-radial/gauge-radial.d.ts.map +1 -1
  24. package/dist/navigation-instruments/gauge-radial/gauge-radial.js +35 -1
  25. package/dist/navigation-instruments/gauge-radial/gauge-radial.js.map +1 -1
  26. package/dist/navigation-instruments/heading/heading.d.ts +19 -1
  27. package/dist/navigation-instruments/heading/heading.d.ts.map +1 -1
  28. package/dist/navigation-instruments/heading/heading.js +34 -16
  29. package/dist/navigation-instruments/heading/heading.js.map +1 -1
  30. package/dist/navigation-instruments/rudder/rudder.d.ts +15 -2
  31. package/dist/navigation-instruments/rudder/rudder.d.ts.map +1 -1
  32. package/dist/navigation-instruments/rudder/rudder.js +36 -26
  33. package/dist/navigation-instruments/rudder/rudder.js.map +1 -1
  34. package/dist/navigation-instruments/speed-gauge/speed-gauge.d.ts +15 -1
  35. package/dist/navigation-instruments/speed-gauge/speed-gauge.d.ts.map +1 -1
  36. package/dist/navigation-instruments/speed-gauge/speed-gauge.js +31 -3
  37. package/dist/navigation-instruments/speed-gauge/speed-gauge.js.map +1 -1
  38. package/dist/navigation-instruments/watch/watch.d.ts +29 -1
  39. package/dist/navigation-instruments/watch/watch.d.ts.map +1 -1
  40. package/dist/navigation-instruments/watch/watch.js +52 -38
  41. package/dist/navigation-instruments/watch/watch.js.map +1 -1
  42. package/dist/svghelpers/radial-frame.d.ts +122 -0
  43. package/dist/svghelpers/radial-frame.d.ts.map +1 -0
  44. package/dist/svghelpers/radial-frame.js +259 -0
  45. package/dist/svghelpers/radial-frame.js.map +1 -0
  46. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"gauge-radial.js","sources":["../../../src/navigation-instruments/gauge-radial/gauge-radial.ts"],"sourcesContent":["import {LitElement, html, nothing, unsafeCSS, type TemplateResult} from 'lit';\nimport {classMap} from 'lit/directives/class-map.js';\nimport componentStyle from './gauge-radial.css?inline';\nimport {customElement} from '../../decorator.js';\nimport {property} from 'lit/decorators.js';\nimport {AdviceType} from '../watch/advice.js';\nimport {InstrumentState, Priority} from '../types.js';\nimport {SetpointMixin} from '../../svghelpers/setpoint-mixin.js';\nimport '../../building-blocks/instrument-radial/instrument-radial.js';\nimport {TickmarkStyle} from '../watch/tickmark.js';\nimport {renderInstrumentReadout} from '../readout/instrument-readout.js';\nimport {ReadoutAlignment, ReadoutStacking} from '../readout/readout.js';\n\nexport enum ObcGaugeRadialType {\n filled = 'filled',\n bar = 'bar',\n needle = 'needle',\n}\n\nexport enum GaugeRadialSector {\n deg270 = '270',\n deg180 = '180',\n deg90Left = '90-left',\n deg90Right = '90-right',\n}\n\nexport enum GaugeRadialHorizontalAlignment {\n left = 'left',\n center = 'center',\n right = 'right',\n}\n\nexport enum GaugeRadialVerticalAlignment {\n top = 'top',\n center = 'center',\n bottom = 'bottom',\n}\n\nexport interface GaugeRadialAdvice {\n minValue: number;\n maxValue: number;\n type: AdviceType;\n hinted: boolean;\n}\n\n/**\n * `<obc-gauge-radial>` — Configurable radial gauge for generic numeric values.\n *\n * `ObcGaugeRadial` is a thin wrapper around `<obc-instrument-radial>` that adds\n * domain-independent value-to-angle mapping with automatic range handling for\n * both positive-only and bipolar (negative-to-positive) scales. It inherits a\n * full setpoint property bundle from {@link SetpointMixin}, including\n * auto at-setpoint detection, dual-marker adjustment preview, and deadband\n * tuning — no manual wiring required.\n *\n * ## Features\n *\n * - **Three display types**: `filled` (solid arc), `bar` (thinner arc), and\n * `needle` (pointer indicator) via the `type` property.\n * - **Sector sweep**: `sector` selects the arc span (`270`, `180`, `90-left`, or `90-right`).\n * The configured `minValue..maxValue` always spans the full sector. For the\n * centered sectors (`270`, `180`) a symmetric range places `0` at 12 o'clock;\n * for `90-left`/`90-right` the range midpoint sits at the middle of the quadrant.\n * - **Setpoint via mixin**: `setpoint`, `newSetpoint`, `touching`,\n * `autoAtSetpointDeadband`, `setpointOverride`, and all other setpoint\n * properties are provided by `SetpointMixin` and forwarded to the inner\n * `<obc-instrument-radial>`.\n * - **Advice zones**: Pass an array of {@link GaugeRadialAdvice} objects to\n * render caution/alert arcs on the gauge. Not shown on the `90-left` /\n * `90-right` sectors.\n * - **Alignment**: The host always fills its container and the dial shrinks to\n * fit the smaller of the available width/height, so a short, wide (or tall,\n * narrow) container leaves slack on one axis. `horizontalAlignment`\n * (`left` | `center` | `right`) and `verticalAlignment`\n * (`top` | `center` | `bottom`) position the dial within that slack; both\n * default to `center`.\n *\n * ## Usage Guidelines\n *\n * - Set `minValue` / `maxValue` to define the scale range.\n * - Use `priority` to switch between regular and enhanced color palettes.\n * - Provide `primaryTickmarkInterval` and `secondaryTickmarkInterval` to\n * control tickmark density.\n * - Enable `showLabels` to show numeric labels at primary tickmarks.\n * - Enable `hasReadout` with optional `label` and `unit`. Layout depends on `sector`\n * and `type`: **270** filled/bar — value at center + a label-only `meta` row in\n * the bottom gap (two separate readouts); **180** filled/bar — a single centered\n * stack (value + label/unit) at the bottom; **270** needle — bottom stack;\n * **180** needle — no readout; **90-left** / **90-right** filled/bar — corner\n * readout in a square host; **90** needle — no readout.\n *\n * ## Best Practices\n *\n * - Prefer `SetpointMixin` properties (`setpoint`, `touching`, etc.) over\n * any legacy aliases — the mixin is the single source of truth.\n * - Keep domain-specific logic (units, formatting) in the parent view; this\n * component is intentionally unit-agnostic.\n *\n * ## Example\n *\n * ```html\n * <obc-gauge-radial\n * value=\"42\"\n * minValue=\"0\"\n * maxValue=\"100\"\n * type=\"filled\"\n * priority=\"enhanced\"\n * showLabels\n * primaryTickmarkInterval=\"25\"\n * secondaryTickmarkInterval=\"5\"\n * setpoint=\"60\"\n * ></obc-gauge-radial>\n * ```\n *\n * @element obc-gauge-radial\n * @typedef {import('./gauge-radial.js').GaugeRadialAdvice} GaugeRadialAdvice\n * @stable\n */\n@customElement('obc-gauge-radial')\nexport class ObcGaugeRadial extends SetpointMixin(LitElement) {\n @property({type: Number}) value = 0;\n @property({type: Number}) maxValue = 100;\n @property({type: Number}) minValue = 0;\n @property({type: Boolean}) showLabels: boolean = false;\n @property({type: Number}) primaryTickmarkInterval = 50;\n @property({type: Number}) secondaryTickmarkInterval = 10;\n /**\n * Interval for tertiary tickmarks in value units.\n * When undefined or <= 0, no tertiary tickmarks are shown.\n */\n @property({type: Number}) tertiaryTickmarkInterval: number | undefined =\n undefined;\n @property({type: String}) state: InstrumentState = InstrumentState.active;\n @property({type: String}) priority: Priority = Priority.regular;\n @property({type: String}) type: ObcGaugeRadialType =\n ObcGaugeRadialType.filled;\n @property({type: Boolean}) tickmarksInside: boolean = false;\n @property({type: String}) tickmarkStyle: TickmarkStyle =\n TickmarkStyle.regular;\n /** Caution/alert arcs. Ignored on `sector: 90-left` / `90-right`. */\n @property({type: Array, attribute: false}) advices: GaugeRadialAdvice[] = [];\n @property({type: String, reflect: true}) sector: GaugeRadialSector =\n GaugeRadialSector.deg270;\n /**\n * Horizontal placement of the dial when the host is wider than the dial\n * (e.g. a short, wide container shrinks the dial to fit the height, leaving\n * horizontal slack). Default `center`.\n */\n @property({type: String})\n horizontalAlignment: GaugeRadialHorizontalAlignment =\n GaugeRadialHorizontalAlignment.center;\n /**\n * Vertical placement of the dial when the host is taller than the dial\n * (e.g. a tall, narrow container shrinks the dial to fit the width, leaving\n * vertical slack). Default `center`.\n */\n @property({type: String}) verticalAlignment: GaugeRadialVerticalAlignment =\n GaugeRadialVerticalAlignment.center;\n /**\n * When `true`, shows the centre `<obc-readout>`(s) with the current value\n * (and optional `label`/`unit`). Layout depends on `sector` and `type`.\n * Default `false`.\n */\n @property({type: Boolean}) hasReadout = false;\n @property({type: String}) label = '';\n @property({type: String}) unit = '';\n @property({type: Number}) fractionDigits = 0;\n\n private get sectorAngles(): {sweep: number; start: number} {\n switch (this.sector) {\n case GaugeRadialSector.deg180:\n return {sweep: 180, start: -90};\n case GaugeRadialSector.deg90Left:\n return {sweep: 90, start: -90};\n case GaugeRadialSector.deg90Right:\n return {sweep: 90, start: 0};\n case GaugeRadialSector.deg270:\n default:\n return {sweep: 270, start: -135};\n }\n }\n\n /**\n * Per-edge crop (%) of the shared, origin-centered 448 SVG box each sector\n * shows. All sectors render at the same natural scale, so the dial stays the\n * same size; the sector only windows a different part (270 whole, 180 wide,\n * 90 a quadrant).\n */\n private get sectorClips(): {\n top: number;\n bottom: number;\n left: number;\n right: number;\n } {\n switch (this.sector) {\n case GaugeRadialSector.deg180:\n return {top: 0, bottom: 44, left: 0, right: 0};\n case GaugeRadialSector.deg90Left:\n return {top: 0, bottom: 45, left: 0, right: 45};\n case GaugeRadialSector.deg90Right:\n return {top: 0, bottom: 45, left: 45, right: 0};\n case GaugeRadialSector.deg270:\n default:\n return {top: 0, bottom: 0, left: 0, right: 0};\n }\n }\n\n private get isSector90(): boolean {\n return (\n this.sector === GaugeRadialSector.deg90Left ||\n this.sector === GaugeRadialSector.deg90Right\n );\n }\n\n // Arrow form so `this` binds when passed as `.getAngle=${this.getAngle}`\n // to <obc-instrument-radial>. Do not convert to a method.\n getAngle = (v: number): number => {\n const {sweep, start} = this.sectorAngles;\n const span = this.maxValue - this.minValue;\n if (!Number.isFinite(span) || span <= 0) {\n return start;\n }\n\n return ((v - this.minValue) / span) * sweep + start;\n };\n\n /** Renders one gauge readout; `withMeta`/`withValue` pick parts. */\n private renderReadout({\n className,\n stacking,\n alignment = ReadoutAlignment.vertical,\n withMeta = true,\n withValue = true,\n }: {\n className: string;\n stacking?: ReadoutStacking;\n alignment?: ReadoutAlignment;\n withMeta?: boolean;\n withValue?: boolean;\n }): TemplateResult {\n return renderInstrumentReadout({\n className,\n stacking,\n alignment,\n hasValue: withValue,\n value: withValue ? this.value : undefined,\n priority: withValue ? this.priority : undefined,\n fractionDigits: this.fractionDigits,\n label: withMeta ? this.label : '',\n unit: withMeta ? this.unit : '',\n });\n }\n\n private renderReadouts() {\n if (!this.hasReadout) {\n return nothing;\n }\n\n const isNeedle = this.type === ObcGaugeRadialType.needle;\n const is90 = this.isSector90;\n const is180 = this.sector === GaugeRadialSector.deg180;\n\n if (isNeedle && (is180 || is90)) {\n return nothing;\n }\n\n // 90 filled/bar: enhanced corner readout (bold value + label/unit).\n if (is90) {\n return this.renderReadout({\n className: 'gauge-readout-meta',\n });\n }\n\n // 270 needle and 180 filled/bar: centered stack (value weight follows `priority`).\n if (isNeedle || is180) {\n return this.renderReadout({\n className: 'gauge-readout-meta',\n stacking: ReadoutStacking.stacked,\n alignment: ReadoutAlignment.center,\n });\n }\n\n // 270 filled/bar: the value sits at the circle center and the label/unit row\n // lower in the bottom gap, so they are two separately-positioned readouts.\n return html`\n ${this.renderReadout({\n className: 'gauge-readout-value',\n withMeta: false,\n })}\n ${this.label || this.unit\n ? this.renderReadout({\n className: 'gauge-readout-meta',\n stacking: ReadoutStacking.stacked,\n alignment: ReadoutAlignment.center,\n withValue: false,\n })\n : nothing}\n `;\n }\n\n override render() {\n const clips = this.sectorClips;\n return html`\n <div\n class=${classMap({\n 'gauge-radial-root': true,\n 'type-needle': this.type === ObcGaugeRadialType.needle,\n 'sector-180': this.sector === GaugeRadialSector.deg180,\n 'sector-90-left': this.sector === GaugeRadialSector.deg90Left,\n 'sector-90-right': this.sector === GaugeRadialSector.deg90Right,\n [`halign-${this.horizontalAlignment}`]: true,\n [`valign-${this.verticalAlignment}`]: true,\n })}\n >\n <obc-instrument-radial\n .value=${this.value}\n .state=${this.state}\n .priority=${this.priority}\n .setpoint=${this.setpoint}\n .newSetpoint=${this.newSetpoint}\n .setpointAtZeroDeadband=${this.setpointAtZeroDeadband}\n .setpointOverride=${this.setpointOverride}\n .touching=${this.touching}\n .autoAtSetpoint=${this.autoAtSetpoint}\n .autoAtSetpointDeadband=${this.autoAtSetpointDeadband}\n .animateSetpoint=${this.animateSetpoint}\n .maxValue=${this.maxValue}\n .minValue=${this.minValue}\n .getAngle=${this.getAngle}\n .showLabels=${this.showLabels}\n .primaryTickmarkInterval=${this.primaryTickmarkInterval}\n .secondaryTickmarkInterval=${this.secondaryTickmarkInterval}\n .tertiaryTickmarkInterval=${this.tertiaryTickmarkInterval}\n .type=${this.type}\n .needleType=${this.type}\n .tickmarksInside=${this.tickmarksInside}\n .tickmarkStyle=${this.tickmarkStyle}\n .advices=${this.isSector90 ? [] : this.advices}\n .clipTop=${clips.top}\n .clipBottom=${clips.bottom}\n .clipLeft=${clips.left}\n .clipRight=${clips.right}\n .endLabelsMaxMin=${this.sector === GaugeRadialSector.deg180}\n >\n </obc-instrument-radial>\n ${this.renderReadouts()}\n </div>\n `;\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-gauge-radial': ObcGaugeRadial;\n }\n}\n"],"names":["ObcGaugeRadialType","GaugeRadialSector","GaugeRadialHorizontalAlignment","GaugeRadialVerticalAlignment"],"mappings":"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"}
1
+ {"version":3,"file":"gauge-radial.js","sources":["../../../src/navigation-instruments/gauge-radial/gauge-radial.ts"],"sourcesContent":["import {LitElement, html, nothing, unsafeCSS, type TemplateResult} from 'lit';\nimport {classMap} from 'lit/directives/class-map.js';\nimport componentStyle from './gauge-radial.css?inline';\nimport {customElement} from '../../decorator.js';\nimport {property, query} from 'lit/decorators.js';\nimport type {RadialFrame} from '../../svghelpers/radial-frame.js';\nimport {AdviceType} from '../watch/advice.js';\nimport {InstrumentState, Priority} from '../types.js';\nimport {SetpointMixin} from '../../svghelpers/setpoint-mixin.js';\nimport '../../building-blocks/instrument-radial/instrument-radial.js';\nimport {TickmarkStyle} from '../watch/tickmark.js';\nimport {renderInstrumentReadout} from '../readout/instrument-readout.js';\nimport {ReadoutAlignment, ReadoutStacking} from '../readout/readout.js';\n\nexport enum ObcGaugeRadialType {\n filled = 'filled',\n bar = 'bar',\n needle = 'needle',\n}\n\nexport enum GaugeRadialSector {\n deg270 = '270',\n deg180 = '180',\n deg90Left = '90-left',\n deg90Right = '90-right',\n}\n\nexport enum GaugeRadialHorizontalAlignment {\n left = 'left',\n center = 'center',\n right = 'right',\n}\n\nexport enum GaugeRadialVerticalAlignment {\n top = 'top',\n center = 'center',\n bottom = 'bottom',\n}\n\nexport interface GaugeRadialAdvice {\n minValue: number;\n maxValue: number;\n type: AdviceType;\n hinted: boolean;\n}\n\n/**\n * Readout meta-row anchors in SVG units, derived from the legacy CSS\n * percentages against the default 448 box (72% → 98.56, 63% → 58.24; the 180°\n * sector's 60% of its 250.88-high crop → −73.472). Converted back to\n * percentages against the actual frame so readouts stay put when the box\n * grows for the label reserve (issue #1021).\n */\nconst READOUT_META_Y = 98.56;\nconst READOUT_META_Y_NEEDLE = 58.24;\nconst READOUT_META_Y_180 = -73.472;\n\n/**\n * `<obc-gauge-radial>` — Configurable radial gauge for generic numeric values.\n *\n * `ObcGaugeRadial` is a thin wrapper around `<obc-instrument-radial>` that adds\n * domain-independent value-to-angle mapping with automatic range handling for\n * both positive-only and bipolar (negative-to-positive) scales. It inherits a\n * full setpoint property bundle from {@link SetpointMixin}, including\n * auto at-setpoint detection, dual-marker adjustment preview, and deadband\n * tuning — no manual wiring required.\n *\n * ## Features\n *\n * - **Three display types**: `filled` (solid arc), `bar` (thinner arc), and\n * `needle` (pointer indicator) via the `type` property.\n * - **Sector sweep**: `sector` selects the arc span (`270`, `180`, `90-left`, or `90-right`).\n * The configured `minValue..maxValue` always spans the full sector. For the\n * centered sectors (`270`, `180`) a symmetric range places `0` at 12 o'clock;\n * for `90-left`/`90-right` the range midpoint sits at the middle of the quadrant.\n * - **Setpoint via mixin**: `setpoint`, `newSetpoint`, `touching`,\n * `autoAtSetpointDeadband`, `setpointOverride`, and all other setpoint\n * properties are provided by `SetpointMixin` and forwarded to the inner\n * `<obc-instrument-radial>`.\n * - **Advice zones**: Pass an array of {@link GaugeRadialAdvice} objects to\n * render caution/alert arcs on the gauge. Not shown on the `90-left` /\n * `90-right` sectors.\n * - **Alignment**: The host always fills its container and the dial shrinks to\n * fit the smaller of the available width/height, so a short, wide (or tall,\n * narrow) container leaves slack on one axis. `horizontalAlignment`\n * (`left` | `center` | `right`) and `verticalAlignment`\n * (`top` | `center` | `bottom`) position the dial within that slack; both\n * default to `center`.\n *\n * ## Usage Guidelines\n *\n * - Set `minValue` / `maxValue` to define the scale range.\n * - Use `priority` to switch between regular and enhanced color palettes.\n * - Provide `primaryTickmarkInterval` and `secondaryTickmarkInterval` to\n * control tickmark density.\n * - Enable `showLabels` to show numeric labels at primary tickmarks.\n * - Enable `hasReadout` with optional `label` and `unit`. Layout depends on `sector`\n * and `type`: **270** filled/bar — value at center + a label-only `meta` row in\n * the bottom gap (two separate readouts); **180** filled/bar — a single centered\n * stack (value + label/unit) at the bottom; **270** needle — bottom stack;\n * **180** needle — no readout; **90-left** / **90-right** filled/bar — corner\n * readout in a square host; **90** needle — no readout.\n *\n * ## Best Practices\n *\n * - Prefer `SetpointMixin` properties (`setpoint`, `touching`, etc.) over\n * any legacy aliases — the mixin is the single source of truth.\n * - Keep domain-specific logic (units, formatting) in the parent view; this\n * component is intentionally unit-agnostic.\n *\n * ## Example\n *\n * ```html\n * <obc-gauge-radial\n * value=\"42\"\n * minValue=\"0\"\n * maxValue=\"100\"\n * type=\"filled\"\n * priority=\"enhanced\"\n * showLabels\n * primaryTickmarkInterval=\"25\"\n * secondaryTickmarkInterval=\"5\"\n * setpoint=\"60\"\n * ></obc-gauge-radial>\n * ```\n *\n * @element obc-gauge-radial\n * @typedef {import('./gauge-radial.js').GaugeRadialAdvice} GaugeRadialAdvice\n * @stable\n */\n@customElement('obc-gauge-radial')\nexport class ObcGaugeRadial extends SetpointMixin(LitElement) {\n @property({type: Number}) value = 0;\n @property({type: Number}) maxValue = 100;\n @property({type: Number}) minValue = 0;\n @property({type: Boolean}) showLabels: boolean = false;\n @property({type: Number}) primaryTickmarkInterval = 50;\n @property({type: Number}) secondaryTickmarkInterval = 10;\n /**\n * Interval for tertiary tickmarks in value units.\n * When undefined or <= 0, no tertiary tickmarks are shown.\n */\n @property({type: Number}) tertiaryTickmarkInterval: number | undefined =\n undefined;\n @property({type: String}) state: InstrumentState = InstrumentState.active;\n @property({type: String}) priority: Priority = Priority.regular;\n @property({type: String}) type: ObcGaugeRadialType =\n ObcGaugeRadialType.filled;\n @property({type: Boolean}) tickmarksInside: boolean = false;\n @property({type: String}) tickmarkStyle: TickmarkStyle =\n TickmarkStyle.regular;\n /** Caution/alert arcs. Ignored on `sector: 90-left` / `90-right`. */\n @property({type: Array, attribute: false}) advices: GaugeRadialAdvice[] = [];\n @property({type: String, reflect: true}) sector: GaugeRadialSector =\n GaugeRadialSector.deg270;\n /**\n * Horizontal placement of the dial when the host is wider than the dial\n * (e.g. a short, wide container shrinks the dial to fit the height, leaving\n * horizontal slack). Default `center`.\n */\n @property({type: String})\n horizontalAlignment: GaugeRadialHorizontalAlignment =\n GaugeRadialHorizontalAlignment.center;\n /**\n * Vertical placement of the dial when the host is taller than the dial\n * (e.g. a tall, narrow container shrinks the dial to fit the width, leaving\n * vertical slack). Default `center`.\n */\n @property({type: String}) verticalAlignment: GaugeRadialVerticalAlignment =\n GaugeRadialVerticalAlignment.center;\n /**\n * When `true`, shows the centre `<obc-readout>`(s) with the current value\n * (and optional `label`/`unit`). Layout depends on `sector` and `type`.\n * Default `false`.\n */\n @property({type: Boolean}) hasReadout = false;\n @property({type: String}) label = '';\n @property({type: String}) unit = '';\n @property({type: Number}) fractionDigits = 0;\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', reflect: true})\n faceDiameter: number | undefined;\n\n private get sectorAngles(): {sweep: number; start: number} {\n switch (this.sector) {\n case GaugeRadialSector.deg180:\n return {sweep: 180, start: -90};\n case GaugeRadialSector.deg90Left:\n return {sweep: 90, start: -90};\n case GaugeRadialSector.deg90Right:\n return {sweep: 90, start: 0};\n case GaugeRadialSector.deg270:\n default:\n return {sweep: 270, start: -135};\n }\n }\n\n /**\n * Per-edge crop (%) of the shared, origin-centered 448 SVG box each sector\n * shows. All sectors render at the same natural scale, so the dial stays the\n * same size; the sector only windows a different part (270 whole, 180 wide,\n * 90 a quadrant).\n */\n private get sectorClips(): {\n top: number;\n bottom: number;\n left: number;\n right: number;\n } {\n switch (this.sector) {\n case GaugeRadialSector.deg180:\n return {top: 0, bottom: 44, left: 0, right: 0};\n case GaugeRadialSector.deg90Left:\n return {top: 0, bottom: 45, left: 0, right: 45};\n case GaugeRadialSector.deg90Right:\n return {top: 0, bottom: 45, left: 45, right: 0};\n case GaugeRadialSector.deg270:\n default:\n return {top: 0, bottom: 0, left: 0, right: 0};\n }\n }\n\n private get isSector90(): boolean {\n return (\n this.sector === GaugeRadialSector.deg90Left ||\n this.sector === GaugeRadialSector.deg90Right\n );\n }\n\n /** @internal */\n @query('.gauge-radial-root') private _rootEl?: HTMLElement;\n\n /**\n * Re-anchor the %-positioned readouts against the frame the inner\n * instrument actually rendered (the box grows when labels need room).\n */\n private _onFrameChanged = (e: Event): void => {\n const frame = (e as CustomEvent<RadialFrame>).detail;\n const root = this._rootEl;\n if (!root || !(frame.height > 0)) {\n return;\n }\n const pct = (anchorY: number) =>\n `${(((anchorY - frame.y) / frame.height) * 100).toFixed(4)}%`;\n root.style.setProperty('--readout-meta-top', pct(READOUT_META_Y));\n root.style.setProperty(\n '--readout-meta-top-needle',\n pct(READOUT_META_Y_NEEDLE)\n );\n root.style.setProperty('--readout-meta-top-180', pct(READOUT_META_Y_180));\n // When the frame lowered a crop for the label drop, the sector's static\n // aspect-ratio no longer matches the viewBox — follow the frame so the\n // dial keeps hugging the root box (contain behavior, issue #992).\n if (frame.clipsAdjusted) {\n root.style.setProperty(\n '--gauge-radial-aspect',\n `${frame.width} / ${frame.height}`\n );\n } else {\n root.style.removeProperty('--gauge-radial-aspect');\n }\n };\n\n // Arrow form so `this` binds when passed as `.getAngle=${this.getAngle}`\n // to <obc-instrument-radial>. Do not convert to a method.\n getAngle = (v: number): number => {\n const {sweep, start} = this.sectorAngles;\n const span = this.maxValue - this.minValue;\n if (!Number.isFinite(span) || span <= 0) {\n return start;\n }\n\n return ((v - this.minValue) / span) * sweep + start;\n };\n\n /** Renders one gauge readout; `withMeta`/`withValue` pick parts. */\n private renderReadout({\n className,\n stacking,\n alignment = ReadoutAlignment.vertical,\n withMeta = true,\n withValue = true,\n }: {\n className: string;\n stacking?: ReadoutStacking;\n alignment?: ReadoutAlignment;\n withMeta?: boolean;\n withValue?: boolean;\n }): TemplateResult {\n return renderInstrumentReadout({\n className,\n stacking,\n alignment,\n hasValue: withValue,\n value: withValue ? this.value : undefined,\n priority: withValue ? this.priority : undefined,\n fractionDigits: this.fractionDigits,\n label: withMeta ? this.label : '',\n unit: withMeta ? this.unit : '',\n });\n }\n\n private renderReadouts() {\n if (!this.hasReadout) {\n return nothing;\n }\n\n const isNeedle = this.type === ObcGaugeRadialType.needle;\n const is90 = this.isSector90;\n const is180 = this.sector === GaugeRadialSector.deg180;\n\n if (isNeedle && (is180 || is90)) {\n return nothing;\n }\n\n // 90 filled/bar: enhanced corner readout (bold value + label/unit).\n if (is90) {\n return this.renderReadout({\n className: 'gauge-readout-meta',\n });\n }\n\n // 270 needle and 180 filled/bar: centered stack (value weight follows `priority`).\n if (isNeedle || is180) {\n return this.renderReadout({\n className: 'gauge-readout-meta',\n stacking: ReadoutStacking.stacked,\n alignment: ReadoutAlignment.center,\n });\n }\n\n // 270 filled/bar: the value sits at the circle center and the label/unit row\n // lower in the bottom gap, so they are two separately-positioned readouts.\n return html`\n ${this.renderReadout({\n className: 'gauge-readout-value',\n withMeta: false,\n })}\n ${this.label || this.unit\n ? this.renderReadout({\n className: 'gauge-readout-meta',\n stacking: ReadoutStacking.stacked,\n alignment: ReadoutAlignment.center,\n withValue: false,\n })\n : nothing}\n `;\n }\n\n override render() {\n const clips = this.sectorClips;\n return html`\n <div\n class=${classMap({\n 'gauge-radial-root': true,\n 'face-pinned': this.faceDiameter !== undefined,\n 'type-needle': this.type === ObcGaugeRadialType.needle,\n 'sector-180': this.sector === GaugeRadialSector.deg180,\n 'sector-90-left': this.sector === GaugeRadialSector.deg90Left,\n 'sector-90-right': this.sector === GaugeRadialSector.deg90Right,\n [`halign-${this.horizontalAlignment}`]: true,\n [`valign-${this.verticalAlignment}`]: true,\n })}\n >\n <obc-instrument-radial\n .value=${this.value}\n .state=${this.state}\n .priority=${this.priority}\n .setpoint=${this.setpoint}\n .newSetpoint=${this.newSetpoint}\n .setpointAtZeroDeadband=${this.setpointAtZeroDeadband}\n .setpointOverride=${this.setpointOverride}\n .touching=${this.touching}\n .autoAtSetpoint=${this.autoAtSetpoint}\n .autoAtSetpointDeadband=${this.autoAtSetpointDeadband}\n .animateSetpoint=${this.animateSetpoint}\n .maxValue=${this.maxValue}\n .minValue=${this.minValue}\n .getAngle=${this.getAngle}\n .showLabels=${this.showLabels}\n .primaryTickmarkInterval=${this.primaryTickmarkInterval}\n .secondaryTickmarkInterval=${this.secondaryTickmarkInterval}\n .tertiaryTickmarkInterval=${this.tertiaryTickmarkInterval}\n .type=${this.type}\n .needleType=${this.type}\n .tickmarksInside=${this.tickmarksInside}\n .tickmarkStyle=${this.tickmarkStyle}\n .advices=${this.isSector90 ? [] : this.advices}\n .clipTop=${clips.top}\n .clipBottom=${clips.bottom}\n .clipLeft=${clips.left}\n .clipRight=${clips.right}\n .endLabelsMaxMin=${this.sector === GaugeRadialSector.deg180}\n .faceDiameter=${this.faceDiameter}\n @frame-changed=${this._onFrameChanged}\n >\n </obc-instrument-radial>\n ${this.renderReadouts()}\n </div>\n `;\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-gauge-radial': ObcGaugeRadial;\n }\n}\n"],"names":["ObcGaugeRadialType","GaugeRadialSector","GaugeRadialHorizontalAlignment","GaugeRadialVerticalAlignment"],"mappings":"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"}
@@ -43,11 +43,29 @@ export declare class ObcHeading extends LitElement {
43
43
  showLabels: boolean;
44
44
  /** When true, labels and north arrow are placed inside the outer ring. */
45
45
  tickmarksInside: boolean;
46
+ /**
47
+ * Outer-ring diameter in CSS pixels. When set, the instrument renders at a
48
+ * fixed intrinsic size derived from the ring, arc shape and label reserve —
49
+ * so instruments sharing the same value have identical ring circumference
50
+ * regardless of label width or arc extent (like obc-donut-chart's
51
+ * fixedHeight). When unset (default), the instrument fills its container.
52
+ */
53
+ faceDiameter: number | undefined;
46
54
  private _headingSp;
47
55
  willUpdate(changed: PropertyValues): void;
48
56
  disconnectedCallback(): void;
49
57
  private _resizeController;
50
- private getPadding;
58
+ /**
59
+ * Pixel cost of the outside decor: the always-rendered north-arrow glyph
60
+ * plus, only while shown, the NSWE labels (both keep a constant on-screen
61
+ * size via `1/scale` terms). Feeds the frame's width-aware reserve,
62
+ * replacing the former empirical `72 + delta(clientSize)` padding.
63
+ */
64
+ private getOutsideDecorPx;
65
+ /** Whether the host size styles were set by applyPinnedHostSize. */
66
+ private _hostSizePinned;
67
+ private _frame;
68
+ updated(changed: PropertyValues): void;
51
69
  private get angleAdviceRaw();
52
70
  private priorityFor;
53
71
  private getRotation;
@@ -1 +1 @@
1
- {"version":3,"file":"heading.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/heading/heading.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,cAAc,EAAY,MAAM,KAAK,CAAC;AAE1D,OAAO,mBAAmB,CAAC;AAG3B,OAAO,EAAc,WAAW,EAAiB,MAAM,oBAAoB,CAAC;AAI5E,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AAGrC,oBAAY,gBAAgB;IAC1B,OAAO,YAAY;IACnB,SAAS,cAAc;IACvB,QAAQ,aAAa;CACtB;AAED,oBAAY,sBAAsB;IAChC,GAAG,QAAQ;IACX,GAAG,QAAQ;CACZ;AAED;;GAEG;AACH,qBACa,UAAW,SAAQ,UAAU;IACd,OAAO,SAAK;IACZ,gBAAgB,SAAK;IAErB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAQ;IAChE,2CAA2C;IACjB,kBAAkB,EAAE,MAAM,GAAG,SAAS,CAAC;IACjE,2EAA2E;IAChD,iBAAiB,EAAE,OAAO,CAAS;IAC9D,2CAA2C;IACjB,6BAA6B,EAAE,MAAM,CAAO;IACtE,2CAA2C;IAChB,uBAAuB,EAAE,OAAO,CAAS;IACpE,2CAA2C;IACE,qBAAqB,EAAE,OAAO,CACpE;IACP,0EAA0E;IAChD,6BAA6B,EAAE,MAAM,CAAK;IACpE,2CAA2C;IAChB,eAAe,EAAE,OAAO,CAAS;IAC5D,2CAA2C;IAChB,QAAQ,EAAE,OAAO,CAAS;IACV,cAAc,EAAE,WAAW,EAAE,CAAM;IACpD,SAAS,EAAE,gBAAgB,CAC1B;IACD,QAAQ,EAAE,QAAQ,CAAoB;IAChE,wCAAwC;IAExC,gBAAgB,EAAE,sBAAsB,EAAE,CAAgC;IAC1E,gCAAgC;IACL,UAAU,EAAE,OAAO,CAAS;IACvD,0EAA0E;IAC/C,eAAe,EAAE,OAAO,CAAS;IAE5D,OAAO,CAAC,UAAU,CAGf;IAEM,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAezC,oBAAoB,IAAI,IAAI;IAOrC,OAAO,CAAC,iBAAiB,CAAkC;IAE3D,OAAO,CAAC,UAAU;IAclB,OAAO,KAAK,cAAc,GAUzB;IAED,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,WAAW;IAWV,MAAM;IAkDf,OAAgB,MAAM,0BAwBpB;CACH;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,aAAa,EAAE,UAAU,CAAC;KAC3B;CACF"}
1
+ {"version":3,"file":"heading.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/heading/heading.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,cAAc,EAAY,MAAM,KAAK,CAAC;AAE1D,OAAO,mBAAmB,CAAC;AAG3B,OAAO,EAAc,WAAW,EAAiB,MAAM,oBAAoB,CAAC;AAY5E,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AAGrC,oBAAY,gBAAgB;IAC1B,OAAO,YAAY;IACnB,SAAS,cAAc;IACvB,QAAQ,aAAa;CACtB;AAED,oBAAY,sBAAsB;IAChC,GAAG,QAAQ;IACX,GAAG,QAAQ;CACZ;AAED;;GAEG;AACH,qBACa,UAAW,SAAQ,UAAU;IACd,OAAO,SAAK;IACZ,gBAAgB,SAAK;IAErB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAQ;IAChE,2CAA2C;IACjB,kBAAkB,EAAE,MAAM,GAAG,SAAS,CAAC;IACjE,2EAA2E;IAChD,iBAAiB,EAAE,OAAO,CAAS;IAC9D,2CAA2C;IACjB,6BAA6B,EAAE,MAAM,CAAO;IACtE,2CAA2C;IAChB,uBAAuB,EAAE,OAAO,CAAS;IACpE,2CAA2C;IACE,qBAAqB,EAAE,OAAO,CACpE;IACP,0EAA0E;IAChD,6BAA6B,EAAE,MAAM,CAAK;IACpE,2CAA2C;IAChB,eAAe,EAAE,OAAO,CAAS;IAC5D,2CAA2C;IAChB,QAAQ,EAAE,OAAO,CAAS;IACV,cAAc,EAAE,WAAW,EAAE,CAAM;IACpD,SAAS,EAAE,gBAAgB,CAC1B;IACD,QAAQ,EAAE,QAAQ,CAAoB;IAChE,wCAAwC;IAExC,gBAAgB,EAAE,sBAAsB,EAAE,CAAgC;IAC1E,gCAAgC;IACL,UAAU,EAAE,OAAO,CAAS;IACvD,0EAA0E;IAC/C,eAAe,EAAE,OAAO,CAAS;IAC5D;;;;;;OAMG;IAEH,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IAEjC,OAAO,CAAC,UAAU,CAGf;IAEM,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAezC,oBAAoB,IAAI,IAAI;IAOrC,OAAO,CAAC,iBAAiB,CAAkC;IAE3D;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;IAOzB,oEAAoE;IACpE,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,MAAM,CAA0B;IAE/B,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAS/C,OAAO,KAAK,cAAc,GAUzB;IAED,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,WAAW;IAWV,MAAM;IAuDf,OAAgB,MAAM,0BAwBpB;CACH;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,aAAa,EAAE,UAAU,CAAC;KAC3B;CACF"}
@@ -5,6 +5,7 @@ import { TickmarkType } from "../watch/tickmark.js";
5
5
  import { arrow, ArrowStyle } from "./arrow.js";
6
6
  import { AdviceState } from "../watch/advice.js";
7
7
  import { ResizeController } from "@lit-labs/observers/resize-controller.js";
8
+ import { NORTH_ARROW_WIDTH_PX, NSWE_LABEL_WIDTH_PX, applyPinnedHostSize, computeRadialFrame, measureContainerPx } from "../../svghelpers/radial-frame.js";
8
9
  import { SetpointBundle } from "../../svghelpers/setpoint-bundle.js";
9
10
  import { Priority } from "../types.js";
10
11
  import { customElement } from "../../decorator.js";
@@ -56,6 +57,7 @@ let ObcHeading = class extends LitElement {
56
57
  onAnimationEnd: () => this.requestUpdate()
57
58
  });
58
59
  this._resizeController = new ResizeController(this, {});
60
+ this._hostSizePinned = false;
59
61
  }
60
62
  willUpdate(changed) {
61
63
  super.willUpdate(changed);
@@ -75,17 +77,25 @@ let ObcHeading = class extends LitElement {
75
77
  super.disconnectedCallback();
76
78
  this._headingSp.dispose();
77
79
  }
78
- getPadding() {
79
- const size = Math.min(this.clientHeight, this.clientWidth);
80
- const deltaWidth = 512 - size;
81
- const steps = deltaWidth / 128;
82
- let deltaPadding;
83
- if (deltaWidth > 0) {
84
- deltaPadding = steps * 48;
85
- } else {
86
- deltaPadding = steps * 6;
80
+ /**
81
+ * Pixel cost of the outside decor: the always-rendered north-arrow glyph
82
+ * plus, only while shown, the NSWE labels (both keep a constant on-screen
83
+ * size via `1/scale` terms). Feeds the frame's width-aware reserve,
84
+ * replacing the former empirical `72 + delta(clientSize)` padding.
85
+ */
86
+ getOutsideDecorPx() {
87
+ if (this.tickmarksInside) {
88
+ return 0;
87
89
  }
88
- return 72 + deltaPadding;
90
+ return NORTH_ARROW_WIDTH_PX + (this.showLabels ? NSWE_LABEL_WIDTH_PX : 0);
91
+ }
92
+ updated(changed) {
93
+ super.updated(changed);
94
+ this._hostSizePinned = applyPinnedHostSize(
95
+ this,
96
+ this._frame,
97
+ this._hostSizePinned
98
+ );
89
99
  }
90
100
  get angleAdviceRaw() {
91
101
  return this.headingAdvices.map(({ minAngle, maxAngle, hinted, type }) => {
@@ -114,21 +124,26 @@ let ObcHeading = class extends LitElement {
114
124
  { angle: 180, type: TickmarkType.main },
115
125
  { angle: 270, type: TickmarkType.main }
116
126
  ];
117
- const padding = this.getPadding();
118
- const width = (176 + padding) * 2;
119
- const viewBox = `-${width / 2} -${width / 2} ${width} ${width}`;
127
+ const frame = computeRadialFrame({
128
+ basePadding: 72,
129
+ labelWidthPx: this.getOutsideDecorPx(),
130
+ containerPx: measureContainerPx(this),
131
+ faceDiameter: this.faceDiameter
132
+ });
133
+ this._frame = frame;
134
+ const viewBox = frame.viewBox;
120
135
  return html`
121
136
  <div class="container">
122
137
  <obc-watch
123
138
  .touching=${this.touching}
124
- .padding=${padding}
139
+ .arcFrame=${frame}
125
140
  .advices=${this.angleAdviceRaw}
126
141
  .tickmarks=${tickmarks}
127
142
  .watchCircleType=${WatchCircleType.single}
128
- .showLabels=${this.showLabels}
143
+ .showLabels=${this.showLabels && !frame.labelsHidden}
129
144
  .tickmarksInside=${this.tickmarksInside}
130
145
  .crosshairEnabled=${true}
131
- .northArrow=${true}
146
+ .northArrow=${!frame.labelsHidden}
132
147
  .angleSetpoint=${this.headingSetpoint ?? void 0}
133
148
  .newAngleSetpoint=${this.newHeadingSetpoint}
134
149
  .atAngleSetpoint=${this._headingSp.computeAtSetpoint(this.heading)}
@@ -237,6 +252,9 @@ __decorateClass([
237
252
  __decorateClass([
238
253
  property({ type: Boolean })
239
254
  ], ObcHeading.prototype, "tickmarksInside", 2);
255
+ __decorateClass([
256
+ property({ type: Number, attribute: "face-diameter" })
257
+ ], ObcHeading.prototype, "faceDiameter", 2);
240
258
  ObcHeading = __decorateClass([
241
259
  customElement("obc-heading")
242
260
  ], ObcHeading);
@@ -1 +1 @@
1
- {"version":3,"file":"heading.js","sources":["../../../src/navigation-instruments/heading/heading.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 {WatchCircleType} from '../watch/watch.js';\nimport {SetpointBundle} from '../../svghelpers/setpoint-bundle.js';\nimport {Priority} from '../types.js';\nimport {customElement} from '../../decorator.js';\n\nexport enum CompassDirection {\n NorthUp = 'northUp',\n HeadingUp = 'headingUp',\n CourseUp = 'courseUp',\n}\n\nexport enum HeadingPriorityElement {\n hdg = 'hdg',\n cog = 'cog',\n}\n\n/**\n * @stable\n */\n@customElement('obc-heading')\nexport class ObcHeading 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 @property({type: String}) direction: CompassDirection =\n CompassDirection.NorthUp;\n @property({type: String}) priority: Priority = Priority.regular;\n /** @availableWhen priority==enhanced */\n @property({type: Array, attribute: false})\n priorityElements: HeadingPriorityElement[] = [HeadingPriorityElement.hdg];\n /** Show compass NSEW labels. */\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 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: HeadingPriorityElement): 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 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 .watchCircleType=${WatchCircleType.single}\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 .rotation=${this.getRotation()}\n >\n </obc-watch>\n <svg viewBox=\"${viewBox}\">\n ${arrow(\n ArrowStyle.HDG,\n this.heading + (this.getRotation() ?? 0),\n this.priorityFor(HeadingPriorityElement.hdg)\n )}\n ${arrow(\n ArrowStyle.COG,\n this.courseOverGround + (this.getRotation() ?? 0),\n this.priorityFor(HeadingPriorityElement.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-heading': ObcHeading;\n }\n}\n"],"names":["CompassDirection","HeadingPriorityElement"],"mappings":"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"}
1
+ {"version":3,"file":"heading.js","sources":["../../../src/navigation-instruments/heading/heading.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 {WatchCircleType} from '../watch/watch.js';\nimport {SetpointBundle} from '../../svghelpers/setpoint-bundle.js';\nimport {Priority} from '../types.js';\nimport {customElement} from '../../decorator.js';\n\nexport enum CompassDirection {\n NorthUp = 'northUp',\n HeadingUp = 'headingUp',\n CourseUp = 'courseUp',\n}\n\nexport enum HeadingPriorityElement {\n hdg = 'hdg',\n cog = 'cog',\n}\n\n/**\n * @stable\n */\n@customElement('obc-heading')\nexport class ObcHeading 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 @property({type: String}) direction: CompassDirection =\n CompassDirection.NorthUp;\n @property({type: String}) priority: Priority = Priority.regular;\n /** @availableWhen priority==enhanced */\n @property({type: Array, attribute: false})\n priorityElements: HeadingPriorityElement[] = [HeadingPriorityElement.hdg];\n /** Show compass NSEW labels. */\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 * 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 */\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: HeadingPriorityElement): 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 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 .watchCircleType=${WatchCircleType.single}\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 .rotation=${this.getRotation()}\n >\n </obc-watch>\n <svg viewBox=\"${viewBox}\">\n ${arrow(\n ArrowStyle.HDG,\n this.heading + (this.getRotation() ?? 0),\n this.priorityFor(HeadingPriorityElement.hdg)\n )}\n ${arrow(\n ArrowStyle.COG,\n this.courseOverGround + (this.getRotation() ?? 0),\n this.priorityFor(HeadingPriorityElement.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-heading': ObcHeading;\n }\n}\n"],"names":["CompassDirection","HeadingPriorityElement"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { LitElement, nothing } from 'lit';
1
+ import { LitElement, PropertyValues, nothing } from 'lit';
2
2
  import { TickmarkStyle } from '../watch/tickmark.js';
3
3
  import { InstrumentState, Priority } from '../types.js';
4
4
  import { AngleAdvice } from '../watch/advice.js';
@@ -80,8 +80,21 @@ export declare class ObcRudder extends ObcRudder_base {
80
80
  tickmarkStyle: TickmarkStyle;
81
81
  advices: AngleAdvice[];
82
82
  zoomToFitArc: boolean;
83
+ /**
84
+ * Outer-ring diameter in CSS pixels. When set, the instrument renders at a
85
+ * fixed intrinsic size derived from the ring, arc shape and label reserve —
86
+ * so instruments sharing the same value have identical ring circumference
87
+ * regardless of label width or arc extent (like obc-donut-chart's
88
+ * fixedHeight). When unset (default), the instrument fills its container.
89
+ */
90
+ faceDiameter: number | undefined;
83
91
  private _radiusOffset;
84
- private _arcFrame;
92
+ private _frame;
93
+ /** Whether the host size styles were set by applyPinnedHostSize. */
94
+ private _hostSizePinned;
95
+ private _resizeController;
96
+ firstUpdated(changed: PropertyValues): void;
97
+ updated(changed: PropertyValues): void;
85
98
  private get _needleTransform();
86
99
  getAngle(value: number): number;
87
100
  get barColor(): "var(--instrument-regular-secondary-color)" | "var(--instrument-enhanced-secondary-color)" | "var(--instrument-frame-tertiary-color)" | "var(--instrument-regular-tertiary-color)" | "var(--instrument-enhanced-tertiary-color)";
@@ -1 +1 @@
1
- {"version":3,"file":"rudder.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/rudder/rudder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAa,OAAO,EAAM,MAAM,KAAK,CAAC;AAExD,OAAO,mBAAmB,CAAC;AAC3B,OAAO,EAAW,aAAa,EAAe,MAAM,sBAAsB,CAAC;AAM3E,OAAO,EAAC,eAAe,EAAE,QAAQ,EAAC,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAc,WAAW,EAAiB,MAAM,oBAAoB,CAAC;AAO5E,oBAAY,gBAAgB;IAC1B,GAAG,QAAQ;IACX,MAAM,WAAW;CAClB;;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DG;AACH,qBACa,SAAU,SAAQ,cAAyB;IAC5B,KAAK,SAAK;IACV,OAAO,EAAE,gBAAgB,CAAwB;IACjD,QAAQ,SAAM;IACb,UAAU,EAAE,OAAO,CAAS;IACvD,mDAAmD;IACxB,eAAe,EAAE,OAAO,CAAS;IAClC,KAAK,EAAE,eAAe,CAA0B;IAChD,QAAQ,EAAE,QAAQ,CAAoB;IACtC,aAAa,EAAE,aAAa,CAC9B;IACmB,OAAO,EAAE,WAAW,EAAE,CAAM;IAC5C,YAAY,EAAE,OAAO,CAAS;IAEzD,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,SAAS,CAAgC;IAEjD,OAAO,KAAK,gBAAgB,GAM3B;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM;IAItB,IAAI,QAAQ,qOAsBX;IAED,YAAY;IA0BH,MAAM;IAqIf,OAAgB,MAAM,0BAkBpB;CACH;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,YAAY,EAAE,SAAS,CAAC;KACzB;CACF"}
1
+ {"version":3,"file":"rudder.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/rudder/rudder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,cAAc,EAAa,OAAO,EAAM,MAAM,KAAK,CAAC;AAGxE,OAAO,mBAAmB,CAAC;AAC3B,OAAO,EAAW,aAAa,EAAe,MAAM,sBAAsB,CAAC;AAE3E,OAAO,EAAC,eAAe,EAAE,QAAQ,EAAC,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAc,WAAW,EAAiB,MAAM,oBAAoB,CAAC;AAW5E,oBAAY,gBAAgB;IAC1B,GAAG,QAAQ;IACX,MAAM,WAAW;CAClB;;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DG;AACH,qBACa,SAAU,SAAQ,cAAyB;IAC5B,KAAK,SAAK;IACV,OAAO,EAAE,gBAAgB,CAAwB;IACjD,QAAQ,SAAM;IACb,UAAU,EAAE,OAAO,CAAS;IACvD,mDAAmD;IACxB,eAAe,EAAE,OAAO,CAAS;IAClC,KAAK,EAAE,eAAe,CAA0B;IAChD,QAAQ,EAAE,QAAQ,CAAoB;IACtC,aAAa,EAAE,aAAa,CAC9B;IACmB,OAAO,EAAE,WAAW,EAAE,CAAM;IAC5C,YAAY,EAAE,OAAO,CAAS;IACzD;;;;;;OAMG;IAEH,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IAEjC,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,MAAM,CAA0B;IAExC,oEAAoE;IACpE,OAAO,CAAC,eAAe,CAAS;IAEhC,OAAO,CAAC,iBAAiB,CAAkC;IAElD,YAAY,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAK3C,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAS/C,OAAO,KAAK,gBAAgB,GAM3B;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM;IAItB,IAAI,QAAQ,qOAsBX;IAED,YAAY;IA0BH,MAAM;IAmIf,OAAgB,MAAM,0BAkBpB;CACH;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,YAAY,EAAE,SAAS,CAAC;KACzB;CACF"}
@@ -1,12 +1,13 @@
1
1
  import { LitElement, nothing, svg, html, css } from "lit";
2
2
  import { property } from "lit/decorators.js";
3
- import { innerRingRadiusFor, WatchCircleType, OUTER_RING_RADIUS } from "../watch/watch.js";
3
+ import { ResizeController } from "@lit-labs/observers/resize-controller.js";
4
+ import { innerRingRadiusFor, WatchCircleType } from "../watch/watch.js";
4
5
  import { TickmarkStyle, TickmarkType } from "../watch/tickmark.js";
5
6
  import { InstrumentState, Priority } from "../types.js";
6
7
  import { SetpointMixin } from "../../svghelpers/setpoint-mixin.js";
7
8
  import { AdviceState } from "../watch/advice.js";
8
9
  import { customElement } from "../../decorator.js";
9
- import { computeZoomToFitArcFrame } from "../../svghelpers/arc-frame.js";
10
+ import { observeInnerBox, applyPinnedHostSize, computeRadialFrame, measureContainerPx, estimateLabelWidthPx } from "../../svghelpers/radial-frame.js";
10
11
  var __defProp = Object.defineProperty;
11
12
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
13
  var __decorateClass = (decorators, target, key, kind) => {
@@ -36,6 +37,20 @@ let ObcRudder = class extends SetpointMixin(LitElement) {
36
37
  this.advices = [];
37
38
  this.zoomToFitArc = false;
38
39
  this._radiusOffset = 0;
40
+ this._hostSizePinned = false;
41
+ this._resizeController = new ResizeController(this, {});
42
+ }
43
+ firstUpdated(changed) {
44
+ super.firstUpdated(changed);
45
+ observeInnerBox(this._resizeController, this.renderRoot);
46
+ }
47
+ updated(changed) {
48
+ super.updated(changed);
49
+ this._hostSizePinned = applyPinnedHostSize(
50
+ this,
51
+ this._frame,
52
+ this._hostSizePinned
53
+ );
39
54
  }
40
55
  get _needleTransform() {
41
56
  const rOff = this._radiusOffset;
@@ -150,32 +165,25 @@ let ObcRudder = class extends SetpointMixin(LitElement) {
150
165
  state
151
166
  };
152
167
  });
153
- let overlayViewBox;
154
- if (this.zoomToFitArc) {
155
- const ext = 48;
156
- const targetSize = (176 + ext) * 2;
157
- const frame = computeZoomToFitArcFrame({
158
- areas,
159
- outerRadius: OUTER_RING_RADIUS,
160
- innerRadius: innerRingRadiusFor(WatchCircleType.double),
161
- extension: ext,
162
- targetSize
163
- });
164
- overlayViewBox = frame.viewBox;
165
- this._radiusOffset = frame.radiusOffset;
166
- this._arcFrame = frame;
167
- } else {
168
- overlayViewBox = "-224 -44.8 448 268.8";
169
- this._radiusOffset = 0;
170
- this._arcFrame = void 0;
171
- }
168
+ const frame = computeRadialFrame({
169
+ basePadding: 48,
170
+ labelWidthPx: this.tickmarksInside ? 0 : estimateLabelWidthPx(tickmarks.map((t) => t.text)),
171
+ clips: this.zoomToFitArc ? void 0 : { top: 40, bottom: 0, left: 0, right: 0 },
172
+ containerPx: measureContainerPx(this),
173
+ faceDiameter: this.faceDiameter,
174
+ zoomToFitArc: this.zoomToFitArc,
175
+ areas,
176
+ innerRadius: innerRingRadiusFor(WatchCircleType.double)
177
+ });
178
+ this._radiusOffset = frame.radiusOffset;
179
+ this._frame = frame;
180
+ const shownTickmarks = frame.labelsHidden ? tickmarks.map((t) => ({ ...t, text: void 0 })) : tickmarks;
181
+ const overlayViewBox = frame.viewBox;
172
182
  return html`
173
183
  <div class="container">
174
184
  <obc-watch
175
185
  .touching=${this.touching}
176
- .clipTop=${this.zoomToFitArc ? 0 : 40}
177
- .zoomToFitArc=${this.zoomToFitArc}
178
- .arcFrame=${this._arcFrame}
186
+ .arcFrame=${frame}
179
187
  .areas=${areas}
180
188
  .angleSetpoint=${setpointAngle}
181
189
  .newAngleSetpoint=${this.newSetpoint !== void 0 ? 180 - this.newSetpoint : void 0}
@@ -183,8 +191,7 @@ let ObcRudder = class extends SetpointMixin(LitElement) {
183
191
  .angleSetpointAtZeroDeadband=${this.setpointAtZeroDeadband}
184
192
  .setpointOverride=${this.setpointOverride}
185
193
  .animateSetpoint=${this.animateSetpoint}
186
- .padding=${48}
187
- .tickmarks=${tickmarks}
194
+ .tickmarks=${shownTickmarks}
188
195
  .tickmarksInside=${this.tickmarksInside}
189
196
  .tickmarkStyle=${this.tickmarkStyle}
190
197
  .watchCircleType=${WatchCircleType.double}
@@ -247,6 +254,9 @@ __decorateClass([
247
254
  __decorateClass([
248
255
  property({ type: Boolean })
249
256
  ], ObcRudder.prototype, "zoomToFitArc", 2);
257
+ __decorateClass([
258
+ property({ type: Number, attribute: "face-diameter" })
259
+ ], ObcRudder.prototype, "faceDiameter", 2);
250
260
  ObcRudder = __decorateClass([
251
261
  customElement("obc-rudder")
252
262
  ], ObcRudder);
@@ -1 +1 @@
1
- {"version":3,"file":"rudder.js","sources":["../../../src/navigation-instruments/rudder/rudder.ts"],"sourcesContent":["import {LitElement, css, html, nothing, svg} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport '../watch/watch.js';\nimport {Tickmark, TickmarkStyle, TickmarkType} from '../watch/tickmark.js';\nimport {\n OUTER_RING_RADIUS,\n WatchCircleType,\n innerRingRadiusFor,\n} from '../watch/watch.js';\nimport {InstrumentState, Priority} from '../types.js';\nimport {SetpointMixin} from '../../svghelpers/setpoint-mixin.js';\nimport {AdviceState, AngleAdvice, AngleAdviceRaw} from '../watch/advice.js';\nimport {customElement} from '../../decorator.js';\nimport {\n computeZoomToFitArcFrame,\n type ZoomToFitArcFrame,\n} from '../../svghelpers/arc-frame.js';\n\nexport enum ObcRudderVariant {\n Bar = 'bar',\n Needle = 'needle',\n}\n\n/**\n * `<obc-rudder>` — Half-circle rudder angle indicator.\n *\n * `ObcRudder` renders a semicircular gauge (40% top-clipped) that displays\n * the current rudder angle with a configurable bar or needle variant. The\n * gauge maps rudder angles to the lower arc of an `<obc-watch>` and overlays\n * a domain-specific needle when the `needle` variant is selected. It inherits\n * a full setpoint property bundle from {@link SetpointMixin}, including\n * auto at-setpoint detection, dual-marker adjustment preview, and deadband\n * tuning.\n *\n * ## Features\n *\n * - **Two display variants**: `bar` (filled arc from zero, default) and\n * `needle` (rotating pointer with silhouette stroke) via the `variant`\n * property.\n * - **Symmetric range**: The gauge spans ±`maxAngle` around the 180° center\n * (zero position at bottom).\n * - **State-aware colors**: Bar and needle colors adapt to the current\n * `InstrumentState` (active, loading, off) and `Priority` (enhanced, regular).\n * - **Setpoint via mixin**: `setpoint`, `newSetpoint`, `touching`,\n * `autoAtSetpointDeadband`, `setpointOverride`, and all other setpoint\n * properties are provided by `SetpointMixin` and forwarded to `<obc-watch>`.\n * - **Advice zones**: Pass an array of `AngleAdvice` objects to render\n * caution/alert arcs; triggered state is derived from whether the setpoint\n * falls inside the advice range.\n *\n * ## Usage Guidelines\n *\n * - Set `maxAngle` to define the symmetric ± range (default: 90°).\n * - Use `priority` to switch between regular and enhanced color palettes\n * (default: `Priority.regular`).\n * - Use `state` to control the instrument color palette.\n * - Enable `showLabels` to show numeric angle labels at tickmarks.\n * - Enable `tickmarksInside` to render tickmarks inside the ring.\n * - Choose `variant` to switch between bar and needle display.\n *\n * ## Best Practices\n *\n * - Prefer `SetpointMixin` properties (`setpoint`, `touching`, etc.) over\n * any legacy aliases — the mixin is the single source of truth.\n * - The top 40% is always clipped; overlay SVGs use the matching clipped\n * viewBox (`-224 -44.8 448 268.8`) for layer alignment.\n *\n * ## Example\n *\n * ```html\n * <obc-rudder\n * angle=\"12\"\n * maxAngle=\"45\"\n * variant=\"needle\"\n * state=\"in-command\"\n * showLabels\n * setpoint=\"15\"\n * ></obc-rudder>\n * ```\n *\n * @element obc-rudder\n * @stable\n */\n@customElement('obc-rudder')\nexport class ObcRudder extends SetpointMixin(LitElement) {\n @property({type: Number}) angle = 0;\n @property({type: String}) variant: ObcRudderVariant = ObcRudderVariant.Bar;\n @property({type: Number}) maxAngle = 90;\n @property({type: Boolean}) showLabels: boolean = false;\n /** Whether to render tickmarks inside the ring. */\n @property({type: Boolean}) tickmarksInside: boolean = false;\n @property({type: String}) state: InstrumentState = InstrumentState.active;\n @property({type: String}) priority: Priority = Priority.regular;\n @property({type: String}) tickmarkStyle: TickmarkStyle =\n TickmarkStyle.regular;\n @property({type: Array, attribute: false}) advices: AngleAdvice[] = [];\n @property({type: Boolean}) zoomToFitArc: boolean = false;\n\n private _radiusOffset = 0;\n private _arcFrame: ZoomToFitArcFrame | undefined;\n\n private get _needleTransform(): string {\n const rOff = this._radiusOffset;\n if (rOff > 0) {\n return `translate(-256, -256) rotate(${-this.angle} 256 256) translate(0, ${rOff})`;\n }\n return `translate(-256, -256) rotate(${-this.angle} 256 256)`;\n }\n\n getAngle(value: number) {\n return 180 - value;\n }\n\n get barColor() {\n if (this.variant === ObcRudderVariant.Needle) {\n if (\n this.state === InstrumentState.loading ||\n this.state === InstrumentState.off\n ) {\n return 'var(--instrument-frame-tertiary-color)';\n }\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-tertiary-color)'\n : 'var(--instrument-regular-tertiary-color)';\n } else {\n if (\n this.state === InstrumentState.loading ||\n this.state === InstrumentState.off\n ) {\n return 'var(--instrument-frame-tertiary-color)';\n }\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n }\n\n renderNeedle() {\n if (this.variant === ObcRudderVariant.Bar) {\n return nothing;\n }\n let color: string;\n if (\n this.state === InstrumentState.loading ||\n this.state === InstrumentState.off\n ) {\n color = 'var(--instrument-frame-tertiary-color)';\n } else {\n color =\n this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n return svg`\n <path\n transform=\"${this._needleTransform}\"\n d=\"M260.462 411.447C259.81 416.73 251.933 416.645 251.514 411.191L239.826 259.24C239.618 258.192 239.508 257.109 239.508 256C239.508 255.764 239.514 255.528 239.524 255.294L239.503 255.039L239.462 254.5H239.576C240.334 246.09 247.401 239.5 256.008 239.5C264.615 239.5 271.681 246.09 272.439 254.5H272.542L272.5 255.039L272.488 255.196C272.501 255.462 272.508 255.731 272.508 256C272.508 257.144 272.391 258.261 272.169 259.339L260.487 411.191L260.462 411.447Z\"\n fill=\"${color}\"\n stroke=\"var(--border-silhouette-color)\"\n />\n `;\n }\n\n override render() {\n const maxAngle = Math.max(2, this.maxAngle);\n const areas = [\n {\n startAngle: 180 - maxAngle,\n endAngle: 180 + maxAngle,\n roundInsideCut: true,\n roundOutsideCut: true,\n },\n ];\n\n const barAreas = [\n {\n startAngle: this.getAngle(0),\n endAngle: this.getAngle(this.angle),\n fillColor: this.barColor,\n },\n ];\n\n const setpointAngle =\n this.setpoint !== undefined ? 180 - this.setpoint : undefined;\n\n const tickmarks: Tickmark[] = [\n {\n angle: 180,\n type: TickmarkType.primary,\n text: this.showLabels ? '0' : undefined,\n },\n {\n angle: 180,\n type: TickmarkType.zeroLineThick,\n color: this.barColor,\n },\n {\n angle: 180 - maxAngle,\n type: TickmarkType.secondary,\n text: this.showLabels ? maxAngle.toFixed(0) : undefined,\n },\n {\n angle: 180 + maxAngle,\n type: TickmarkType.secondary,\n text: this.showLabels ? (-maxAngle).toFixed(0) : undefined,\n },\n ];\n\n let helpAngle: null | number = null;\n if (maxAngle > 70) {\n helpAngle = 45;\n } else if (maxAngle > 50) {\n helpAngle = 30;\n } else if (maxAngle > 40) {\n helpAngle = 22.5;\n }\n\n if (helpAngle !== null) {\n tickmarks.push({angle: 180 - helpAngle, type: TickmarkType.primary});\n tickmarks.push({angle: 180 + helpAngle, type: TickmarkType.primary});\n }\n\n const advices = this.advices.map<AngleAdviceRaw>((adv): AngleAdviceRaw => {\n const startAngle = 180 - adv.maxAngle;\n const endAngle = 180 - adv.minAngle;\n const isInRange =\n this.setpoint !== undefined &&\n this.setpoint >= adv.minAngle &&\n this.setpoint <= adv.maxAngle;\n let state;\n if (isInRange) {\n state = AdviceState.triggered;\n } else if (adv.hinted) {\n state = AdviceState.hinted;\n } else {\n state = AdviceState.regular;\n }\n return {\n minAngle: startAngle,\n maxAngle: endAngle,\n type: adv.type,\n state: state,\n };\n });\n\n let overlayViewBox: string;\n if (this.zoomToFitArc) {\n const ext = 48;\n const targetSize = (176 + ext) * 2;\n const frame = computeZoomToFitArcFrame({\n areas,\n outerRadius: OUTER_RING_RADIUS,\n innerRadius: innerRingRadiusFor(WatchCircleType.double),\n extension: ext,\n targetSize,\n });\n overlayViewBox = frame.viewBox;\n this._radiusOffset = frame.radiusOffset;\n this._arcFrame = frame;\n } else {\n overlayViewBox = '-224 -44.8 448 268.8';\n this._radiusOffset = 0;\n this._arcFrame = undefined;\n }\n\n return html`\n <div class=\"container\">\n <obc-watch\n .touching=${this.touching}\n .clipTop=${this.zoomToFitArc ? 0 : 40}\n .zoomToFitArc=${this.zoomToFitArc}\n .arcFrame=${this._arcFrame}\n .areas=${areas}\n .angleSetpoint=${setpointAngle}\n .newAngleSetpoint=${this.newSetpoint !== undefined\n ? 180 - this.newSetpoint\n : undefined}\n .atAngleSetpoint=${this.computeAtSetpoint(this.angle)}\n .angleSetpointAtZeroDeadband=${this.setpointAtZeroDeadband}\n .setpointOverride=${this.setpointOverride}\n .animateSetpoint=${this.animateSetpoint}\n .padding=${48}\n .tickmarks=${tickmarks}\n .tickmarksInside=${this.tickmarksInside}\n .tickmarkStyle=${this.tickmarkStyle}\n .watchCircleType=${WatchCircleType.double}\n .barAreas=${barAreas}\n .state=${this.state}\n .priority=${this.priority}\n .advices=${advices}\n ></obc-watch>\n <svg viewBox=\"${overlayViewBox}\">${this.renderNeedle()}</svg>\n </div>\n `;\n }\n\n static override styles = css`\n * {\n box-sizing: border-box;\n }\n\n .container {\n position: relative;\n width: 100%;\n height: 100%;\n }\n\n .container > * {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n }\n `;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-rudder': ObcRudder;\n }\n}\n"],"names":["ObcRudderVariant"],"mappings":"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"}
1
+ {"version":3,"file":"rudder.js","sources":["../../../src/navigation-instruments/rudder/rudder.ts"],"sourcesContent":["import {LitElement, PropertyValues, css, html, nothing, svg} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport {ResizeController} from '@lit-labs/observers/resize-controller.js';\nimport '../watch/watch.js';\nimport {Tickmark, TickmarkStyle, TickmarkType} from '../watch/tickmark.js';\nimport {WatchCircleType, innerRingRadiusFor} from '../watch/watch.js';\nimport {InstrumentState, Priority} from '../types.js';\nimport {SetpointMixin} from '../../svghelpers/setpoint-mixin.js';\nimport {AdviceState, AngleAdvice, AngleAdviceRaw} from '../watch/advice.js';\nimport {customElement} from '../../decorator.js';\nimport {\n applyPinnedHostSize,\n computeRadialFrame,\n estimateLabelWidthPx,\n measureContainerPx,\n observeInnerBox,\n type RadialFrame,\n} from '../../svghelpers/radial-frame.js';\n\nexport enum ObcRudderVariant {\n Bar = 'bar',\n Needle = 'needle',\n}\n\n/**\n * `<obc-rudder>` — Half-circle rudder angle indicator.\n *\n * `ObcRudder` renders a semicircular gauge (40% top-clipped) that displays\n * the current rudder angle with a configurable bar or needle variant. The\n * gauge maps rudder angles to the lower arc of an `<obc-watch>` and overlays\n * a domain-specific needle when the `needle` variant is selected. It inherits\n * a full setpoint property bundle from {@link SetpointMixin}, including\n * auto at-setpoint detection, dual-marker adjustment preview, and deadband\n * tuning.\n *\n * ## Features\n *\n * - **Two display variants**: `bar` (filled arc from zero, default) and\n * `needle` (rotating pointer with silhouette stroke) via the `variant`\n * property.\n * - **Symmetric range**: The gauge spans ±`maxAngle` around the 180° center\n * (zero position at bottom).\n * - **State-aware colors**: Bar and needle colors adapt to the current\n * `InstrumentState` (active, loading, off) and `Priority` (enhanced, regular).\n * - **Setpoint via mixin**: `setpoint`, `newSetpoint`, `touching`,\n * `autoAtSetpointDeadband`, `setpointOverride`, and all other setpoint\n * properties are provided by `SetpointMixin` and forwarded to `<obc-watch>`.\n * - **Advice zones**: Pass an array of `AngleAdvice` objects to render\n * caution/alert arcs; triggered state is derived from whether the setpoint\n * falls inside the advice range.\n *\n * ## Usage Guidelines\n *\n * - Set `maxAngle` to define the symmetric ± range (default: 90°).\n * - Use `priority` to switch between regular and enhanced color palettes\n * (default: `Priority.regular`).\n * - Use `state` to control the instrument color palette.\n * - Enable `showLabels` to show numeric angle labels at tickmarks.\n * - Enable `tickmarksInside` to render tickmarks inside the ring.\n * - Choose `variant` to switch between bar and needle display.\n *\n * ## Best Practices\n *\n * - Prefer `SetpointMixin` properties (`setpoint`, `touching`, etc.) over\n * any legacy aliases — the mixin is the single source of truth.\n * - The top 40% is always clipped; overlay SVGs use the matching clipped\n * viewBox (`-224 -44.8 448 268.8`) for layer alignment.\n *\n * ## Example\n *\n * ```html\n * <obc-rudder\n * angle=\"12\"\n * maxAngle=\"45\"\n * variant=\"needle\"\n * state=\"in-command\"\n * showLabels\n * setpoint=\"15\"\n * ></obc-rudder>\n * ```\n *\n * @element obc-rudder\n * @stable\n */\n@customElement('obc-rudder')\nexport class ObcRudder extends SetpointMixin(LitElement) {\n @property({type: Number}) angle = 0;\n @property({type: String}) variant: ObcRudderVariant = ObcRudderVariant.Bar;\n @property({type: Number}) maxAngle = 90;\n @property({type: Boolean}) showLabels: boolean = false;\n /** Whether to render tickmarks inside the ring. */\n @property({type: Boolean}) tickmarksInside: boolean = false;\n @property({type: String}) state: InstrumentState = InstrumentState.active;\n @property({type: String}) priority: Priority = Priority.regular;\n @property({type: String}) tickmarkStyle: TickmarkStyle =\n TickmarkStyle.regular;\n @property({type: Array, attribute: false}) advices: AngleAdvice[] = [];\n @property({type: Boolean}) zoomToFitArc: boolean = false;\n /**\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 _radiusOffset = 0;\n private _frame: RadialFrame | undefined;\n\n /** Whether the host size styles were set by applyPinnedHostSize. */\n private _hostSizePinned = false;\n\n private _resizeController = new ResizeController(this, {});\n\n override firstUpdated(changed: PropertyValues): void {\n super.firstUpdated(changed);\n observeInnerBox(this._resizeController, this.renderRoot);\n }\n\n override updated(changed: PropertyValues): void {\n super.updated(changed);\n this._hostSizePinned = applyPinnedHostSize(\n this,\n this._frame,\n this._hostSizePinned\n );\n }\n\n private get _needleTransform(): string {\n const rOff = this._radiusOffset;\n if (rOff > 0) {\n return `translate(-256, -256) rotate(${-this.angle} 256 256) translate(0, ${rOff})`;\n }\n return `translate(-256, -256) rotate(${-this.angle} 256 256)`;\n }\n\n getAngle(value: number) {\n return 180 - value;\n }\n\n get barColor() {\n if (this.variant === ObcRudderVariant.Needle) {\n if (\n this.state === InstrumentState.loading ||\n this.state === InstrumentState.off\n ) {\n return 'var(--instrument-frame-tertiary-color)';\n }\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-tertiary-color)'\n : 'var(--instrument-regular-tertiary-color)';\n } else {\n if (\n this.state === InstrumentState.loading ||\n this.state === InstrumentState.off\n ) {\n return 'var(--instrument-frame-tertiary-color)';\n }\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n }\n\n renderNeedle() {\n if (this.variant === ObcRudderVariant.Bar) {\n return nothing;\n }\n let color: string;\n if (\n this.state === InstrumentState.loading ||\n this.state === InstrumentState.off\n ) {\n color = 'var(--instrument-frame-tertiary-color)';\n } else {\n color =\n this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n return svg`\n <path\n transform=\"${this._needleTransform}\"\n d=\"M260.462 411.447C259.81 416.73 251.933 416.645 251.514 411.191L239.826 259.24C239.618 258.192 239.508 257.109 239.508 256C239.508 255.764 239.514 255.528 239.524 255.294L239.503 255.039L239.462 254.5H239.576C240.334 246.09 247.401 239.5 256.008 239.5C264.615 239.5 271.681 246.09 272.439 254.5H272.542L272.5 255.039L272.488 255.196C272.501 255.462 272.508 255.731 272.508 256C272.508 257.144 272.391 258.261 272.169 259.339L260.487 411.191L260.462 411.447Z\"\n fill=\"${color}\"\n stroke=\"var(--border-silhouette-color)\"\n />\n `;\n }\n\n override render() {\n const maxAngle = Math.max(2, this.maxAngle);\n const areas = [\n {\n startAngle: 180 - maxAngle,\n endAngle: 180 + maxAngle,\n roundInsideCut: true,\n roundOutsideCut: true,\n },\n ];\n\n const barAreas = [\n {\n startAngle: this.getAngle(0),\n endAngle: this.getAngle(this.angle),\n fillColor: this.barColor,\n },\n ];\n\n const setpointAngle =\n this.setpoint !== undefined ? 180 - this.setpoint : undefined;\n\n const tickmarks: Tickmark[] = [\n {\n angle: 180,\n type: TickmarkType.primary,\n text: this.showLabels ? '0' : undefined,\n },\n {\n angle: 180,\n type: TickmarkType.zeroLineThick,\n color: this.barColor,\n },\n {\n angle: 180 - maxAngle,\n type: TickmarkType.secondary,\n text: this.showLabels ? maxAngle.toFixed(0) : undefined,\n },\n {\n angle: 180 + maxAngle,\n type: TickmarkType.secondary,\n text: this.showLabels ? (-maxAngle).toFixed(0) : undefined,\n },\n ];\n\n let helpAngle: null | number = null;\n if (maxAngle > 70) {\n helpAngle = 45;\n } else if (maxAngle > 50) {\n helpAngle = 30;\n } else if (maxAngle > 40) {\n helpAngle = 22.5;\n }\n\n if (helpAngle !== null) {\n tickmarks.push({angle: 180 - helpAngle, type: TickmarkType.primary});\n tickmarks.push({angle: 180 + helpAngle, type: TickmarkType.primary});\n }\n\n const advices = this.advices.map<AngleAdviceRaw>((adv): AngleAdviceRaw => {\n const startAngle = 180 - adv.maxAngle;\n const endAngle = 180 - adv.minAngle;\n const isInRange =\n this.setpoint !== undefined &&\n this.setpoint >= adv.minAngle &&\n this.setpoint <= adv.maxAngle;\n let state;\n if (isInRange) {\n state = AdviceState.triggered;\n } else if (adv.hinted) {\n state = AdviceState.hinted;\n } else {\n state = AdviceState.regular;\n }\n return {\n minAngle: startAngle,\n maxAngle: endAngle,\n type: adv.type,\n state: state,\n };\n });\n\n const frame = computeRadialFrame({\n basePadding: 48,\n labelWidthPx: this.tickmarksInside\n ? 0\n : estimateLabelWidthPx(tickmarks.map((t) => t.text)),\n clips: this.zoomToFitArc\n ? undefined\n : {top: 40, bottom: 0, left: 0, right: 0},\n containerPx: measureContainerPx(this),\n faceDiameter: this.faceDiameter,\n zoomToFitArc: this.zoomToFitArc,\n areas,\n innerRadius: innerRingRadiusFor(WatchCircleType.double),\n });\n this._radiusOffset = frame.radiusOffset;\n this._frame = frame;\n const shownTickmarks = frame.labelsHidden\n ? tickmarks.map((t) => ({...t, text: undefined}))\n : tickmarks;\n const overlayViewBox = frame.viewBox;\n\n return html`\n <div class=\"container\">\n <obc-watch\n .touching=${this.touching}\n .arcFrame=${frame}\n .areas=${areas}\n .angleSetpoint=${setpointAngle}\n .newAngleSetpoint=${this.newSetpoint !== undefined\n ? 180 - this.newSetpoint\n : undefined}\n .atAngleSetpoint=${this.computeAtSetpoint(this.angle)}\n .angleSetpointAtZeroDeadband=${this.setpointAtZeroDeadband}\n .setpointOverride=${this.setpointOverride}\n .animateSetpoint=${this.animateSetpoint}\n .tickmarks=${shownTickmarks}\n .tickmarksInside=${this.tickmarksInside}\n .tickmarkStyle=${this.tickmarkStyle}\n .watchCircleType=${WatchCircleType.double}\n .barAreas=${barAreas}\n .state=${this.state}\n .priority=${this.priority}\n .advices=${advices}\n ></obc-watch>\n <svg viewBox=\"${overlayViewBox}\">${this.renderNeedle()}</svg>\n </div>\n `;\n }\n\n static override styles = css`\n * {\n box-sizing: border-box;\n }\n\n .container {\n position: relative;\n width: 100%;\n height: 100%;\n }\n\n .container > * {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n }\n `;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-rudder': ObcRudder;\n }\n}\n"],"names":["ObcRudderVariant"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { LitElement } from 'lit';
1
+ import { LitElement, PropertyValues } from 'lit';
2
2
  import { Tickmark, TickmarkStyle } from '../watch/tickmark.js';
3
3
  import { AdviceType, AngleAdviceRaw } from '../watch/advice.js';
4
4
  import { Priority } from '../types.js';
@@ -102,6 +102,20 @@ export declare class ObcSpeedGauge extends ObcSpeedGauge_base {
102
102
  unit: string;
103
103
  /** Number of fraction digits shown in the readout. Default `1`. */
104
104
  fractionDigits: number;
105
+ /**
106
+ * Outer-ring diameter in CSS pixels. When set, the instrument renders at a
107
+ * fixed intrinsic size derived from the ring, arc shape and label reserve —
108
+ * so instruments sharing the same value have identical ring circumference
109
+ * regardless of label width or arc extent (like obc-donut-chart's
110
+ * fixedHeight). When unset (default), the instrument fills its container.
111
+ */
112
+ faceDiameter: number | undefined;
113
+ private _frame;
114
+ /** Whether the host size styles were set by applyPinnedHostSize. */
115
+ private _hostSizePinned;
116
+ private _resizeController;
117
+ firstUpdated(changed: PropertyValues): void;
118
+ updated(changed: PropertyValues): void;
105
119
  getAngle(v: number): number;
106
120
  get minAngle(): number;
107
121
  maxAngle: number;
@@ -1 +1 @@
1
- {"version":3,"file":"speed-gauge.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/speed-gauge/speed-gauge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAA0B,MAAM,KAAK,CAAC;AAExD,OAAO,EAAC,QAAQ,EAAE,aAAa,EAAe,MAAM,sBAAsB,CAAC;AAE3E,OAAO,EAAC,UAAU,EAAE,cAAc,EAAc,MAAM,oBAAoB,CAAC;AAE3E,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AAKrC,oBAAY,uBAAuB;IACjC,IAAI,SAAS;IACb,GAAG,QAAQ;CACZ;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CACjB;;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AACH,qBACa,aAAc,SAAQ,kBAAyB;IAChC,KAAK,SAAK;IACV,QAAQ,SAAO;IACf,QAAQ,SAAK;IACZ,UAAU,EAAE,OAAO,CAAS;IACvD,mDAAmD;IACxB,eAAe,EAAE,OAAO,CAAS;IAC5D;;;OAGG;IACuB,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAM;IAC1C,QAAQ,EAAE,QAAQ,CAAoB;IACtC,UAAU,EAAE,uBAAuB,CAC9B;IACY,YAAY,EAAE,WAAW,EAAE,CAAM;IAClD,aAAa,EAAE,aAAa,CAC9B;IACxB;;;OAGG;IACwB,UAAU,EAAE,OAAO,CAAS;IACvD,oCAAoC;IACV,KAAK,SAAS;IACxC,kCAAkC;IACR,IAAI,SAAQ;IACtC,mEAAmE;IACzC,cAAc,SAAK;IAE7C,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAI3B,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,QAAQ,SAAY;IAEX,MAAM;IA+Df,IAAI,MAAM,yCAkBT;IAED,IAAI,SAAS,IAAI,QAAQ,EAAE,CA+C1B;IAED,IAAI,QAAQ,IAAI,cAAc,EAAE,CAqB/B;IAED,OAAgB,MAAM,0BAmCpB;CACH;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,iBAAiB,EAAE,aAAa,CAAC;KAClC;CACF"}
1
+ {"version":3,"file":"speed-gauge.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/speed-gauge/speed-gauge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,cAAc,EAA0B,MAAM,KAAK,CAAC;AAWxE,OAAO,EAAC,QAAQ,EAAE,aAAa,EAAe,MAAM,sBAAsB,CAAC;AAE3E,OAAO,EAAC,UAAU,EAAE,cAAc,EAAc,MAAM,oBAAoB,CAAC;AAE3E,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AAKrC,oBAAY,uBAAuB;IACjC,IAAI,SAAS;IACb,GAAG,QAAQ;CACZ;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CACjB;;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AACH,qBACa,aAAc,SAAQ,kBAAyB;IAChC,KAAK,SAAK;IACV,QAAQ,SAAO;IACf,QAAQ,SAAK;IACZ,UAAU,EAAE,OAAO,CAAS;IACvD,mDAAmD;IACxB,eAAe,EAAE,OAAO,CAAS;IAC5D;;;OAGG;IACuB,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAM;IAC1C,QAAQ,EAAE,QAAQ,CAAoB;IACtC,UAAU,EAAE,uBAAuB,CAC9B;IACY,YAAY,EAAE,WAAW,EAAE,CAAM;IAClD,aAAa,EAAE,aAAa,CAC9B;IACxB;;;OAGG;IACwB,UAAU,EAAE,OAAO,CAAS;IACvD,oCAAoC;IACV,KAAK,SAAS;IACxC,kCAAkC;IACR,IAAI,SAAQ;IACtC,mEAAmE;IACzC,cAAc,SAAK;IAC7C;;;;;;OAMG;IAEH,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IAEjC,OAAO,CAAC,MAAM,CAA0B;IAExC,oEAAoE;IACpE,OAAO,CAAC,eAAe,CAAS;IAEhC,OAAO,CAAC,iBAAiB,CAAkC;IAElD,YAAY,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAK3C,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAS/C,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAI3B,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,QAAQ,SAAY;IAEX,MAAM;IA6Ef,IAAI,MAAM,yCAkBT;IAED,IAAI,SAAS,IAAI,QAAQ,EAAE,CA+C1B;IAED,IAAI,QAAQ,IAAI,cAAc,EAAE,CAqB/B;IAED,OAAgB,MAAM,0BAmCpB;CACH;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,iBAAiB,EAAE,aAAa,CAAC;KAClC;CACF"}