@oicl/openbridge-webcomponents 2.0.0-next.56 → 2.0.0-next.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/openbridge-webcomponents.bundle.js +987 -362
- package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
- package/custom-elements.json +576 -10
- package/dist/building-blocks/instrument-radial/instrument-radial.d.ts +10 -0
- package/dist/building-blocks/instrument-radial/instrument-radial.d.ts.map +1 -1
- package/dist/building-blocks/instrument-radial/instrument-radial.js +86 -21
- package/dist/building-blocks/instrument-radial/instrument-radial.js.map +1 -1
- package/dist/navigation-instruments/compass-sector/compass-sector.css.js +12 -0
- package/dist/navigation-instruments/compass-sector/compass-sector.css.js.map +1 -1
- package/dist/navigation-instruments/compass-sector/compass-sector.d.ts +23 -0
- package/dist/navigation-instruments/compass-sector/compass-sector.d.ts.map +1 -1
- package/dist/navigation-instruments/compass-sector/compass-sector.js +47 -0
- package/dist/navigation-instruments/compass-sector/compass-sector.js.map +1 -1
- package/dist/navigation-instruments/gauge-radial/gauge-radial.css.js +99 -0
- package/dist/navigation-instruments/gauge-radial/gauge-radial.css.js.map +1 -0
- package/dist/navigation-instruments/gauge-radial/gauge-radial.d.ts +42 -7
- package/dist/navigation-instruments/gauge-radial/gauge-radial.d.ts.map +1 -1
- package/dist/navigation-instruments/gauge-radial/gauge-radial.js +178 -31
- package/dist/navigation-instruments/gauge-radial/gauge-radial.js.map +1 -1
- package/dist/navigation-instruments/pitch/pitch.d.ts +37 -0
- package/dist/navigation-instruments/pitch/pitch.d.ts.map +1 -1
- package/dist/navigation-instruments/pitch/pitch.js +130 -62
- package/dist/navigation-instruments/pitch/pitch.js.map +1 -1
- package/dist/navigation-instruments/pitch-roll/pitch-roll.d.ts +7 -0
- package/dist/navigation-instruments/pitch-roll/pitch-roll.d.ts.map +1 -1
- package/dist/navigation-instruments/pitch-roll/pitch-roll.js +58 -2
- package/dist/navigation-instruments/pitch-roll/pitch-roll.js.map +1 -1
- package/dist/navigation-instruments/readout/readout.css.js +4 -0
- package/dist/navigation-instruments/readout/readout.css.js.map +1 -1
- package/dist/navigation-instruments/roll/roll.d.ts +37 -0
- package/dist/navigation-instruments/roll/roll.d.ts.map +1 -1
- package/dist/navigation-instruments/roll/roll.js +119 -63
- package/dist/navigation-instruments/roll/roll.js.map +1 -1
- package/dist/navigation-instruments/rot-sector/rot-sector.d.ts +15 -0
- package/dist/navigation-instruments/rot-sector/rot-sector.d.ts.map +1 -1
- package/dist/navigation-instruments/rot-sector/rot-sector.js +53 -1
- package/dist/navigation-instruments/rot-sector/rot-sector.js.map +1 -1
- package/dist/navigation-instruments/watch/tickmark.d.ts +2 -1
- package/dist/navigation-instruments/watch/tickmark.d.ts.map +1 -1
- package/dist/navigation-instruments/watch/tickmark.js +24 -4
- package/dist/navigation-instruments/watch/tickmark.js.map +1 -1
- package/dist/navigation-instruments/watch/watch.d.ts +23 -1
- package/dist/navigation-instruments/watch/watch.d.ts.map +1 -1
- package/dist/navigation-instruments/watch/watch.js +48 -20
- package/dist/navigation-instruments/watch/watch.js.map +1 -1
- 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} from 'lit';\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';\n\nexport enum ObcGaugeRadialType {\n filled = 'filled',\n bar = 'bar',\n needle = 'needle',\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 * - **Full-range mapping**: The configured `minValue..maxValue` always spans\n * the full 270° sweep. Symmetric ranges still place `0` at 12 o'clock.\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.\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 *\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 * 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 */\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 @property({type: Array, attribute: false}) advices: GaugeRadialAdvice[] = [];\n\n getAngle(v: number): number {\n const span = this.maxValue - this.minValue;\n if (!Number.isFinite(span) || span <= 0) {\n return -135;\n }\n\n return ((v - this.minValue) / span) * 270 - 135;\n }\n\n override render() {\n return html`\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.advices}\n >\n </obc-instrument-radial>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-gauge-radial': ObcGaugeRadial;\n }\n}\n"],"names":["ObcGaugeRadialType"],"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} 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 '../readout/readout.js';\nimport {\n ReadoutStackVerticalAlignment,\n ReadoutVariant,\n} 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 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 *\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 `showReadout` 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 */\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 @property({type: Boolean}) showReadout = 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`/`labelOnly` pick parts. */\n private renderReadout({\n className,\n variant,\n alignment = ReadoutStackVerticalAlignment.vertical,\n withMeta = true,\n labelOnly = false,\n }: {\n className: string;\n variant: ReadoutVariant;\n alignment?: ReadoutStackVerticalAlignment;\n withMeta?: boolean;\n labelOnly?: boolean;\n }): TemplateResult {\n // `labelOnly` already means \"no value\", so derive it instead of passing both.\n const withValue = !labelOnly;\n return html`\n <obc-readout\n class=${className}\n direction=\"vertical\"\n ?labelOnly=${labelOnly}\n .variant=${variant}\n .alignment=${alignment}\n .valuePriority=${withValue ? this.priority : undefined}\n .value=${withValue ? this.value : undefined}\n .fractionDigits=${this.fractionDigits}\n .label=${withMeta ? this.label : ''}\n .unit=${withMeta ? this.unit : ''}\n ></obc-readout>\n `;\n }\n\n private renderReadouts() {\n if (!this.showReadout) {\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 variant: ReadoutVariant.enhanced,\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 variant: ReadoutVariant.stack,\n alignment: ReadoutStackVerticalAlignment.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 variant: ReadoutVariant.enhanced,\n withMeta: false,\n })}\n ${this.label || this.unit\n ? this.renderReadout({\n className: 'gauge-readout-meta',\n variant: ReadoutVariant.stack,\n alignment: ReadoutStackVerticalAlignment.center,\n labelOnly: true,\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 })}\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"],"mappings":"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"}
|
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
import { LitElement } from 'lit';
|
|
2
2
|
import { VesselImage } from '../watch/watch.js';
|
|
3
|
+
import { Priority } from '../types.js';
|
|
3
4
|
import '../watch/watch.js';
|
|
5
|
+
import '../readout/readout.js';
|
|
6
|
+
export declare enum ObcPitchType {
|
|
7
|
+
/** Single arc scale on the right (default). */
|
|
8
|
+
singleScale = "single-scale",
|
|
9
|
+
/** Right scale duplicated to the opposite (left) arc as well. */
|
|
10
|
+
dualScale = "dual-scale"
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* `<obc-pitch>` — Pitch (trim) indicator with a side arc scale.
|
|
14
|
+
*
|
|
15
|
+
* Shows `pitch` against a watch arc centred on the right, with an average-pitch
|
|
16
|
+
* band and a rotating indicator. Supports an optional opposite-side scale
|
|
17
|
+
* (`dual-scale`), a centre readout (`hasReadout`), and a `regular`/`enhanced`
|
|
18
|
+
* palette.
|
|
19
|
+
*
|
|
20
|
+
* @element obc-pitch
|
|
21
|
+
*/
|
|
4
22
|
export declare class ObcPitch extends LitElement {
|
|
5
23
|
pitch: number;
|
|
6
24
|
minAvgPitch: number;
|
|
@@ -9,6 +27,22 @@ export declare class ObcPitch extends LitElement {
|
|
|
9
27
|
maxPitchAdvice: number | undefined;
|
|
10
28
|
triggerPitchAdvice: boolean;
|
|
11
29
|
zoomToFitArc: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* When `true`, the centre shows an `<obc-readout>` with the pitch value
|
|
32
|
+
* (label `Pitch`, unit `DEG`) instead of the horizon line, rotating indicator
|
|
33
|
+
* and vessel. Default `false`.
|
|
34
|
+
*/
|
|
35
|
+
hasReadout: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* `single-scale` shows one arc on the right (default); `dual-scale` also
|
|
38
|
+
* shows the scale on the opposite (left) arc (the indicator's opposite end).
|
|
39
|
+
*/
|
|
40
|
+
type: ObcPitchType;
|
|
41
|
+
/**
|
|
42
|
+
* Colour palette for the scale fill / indicator and the readout value:
|
|
43
|
+
* `regular` (default) or `enhanced`.
|
|
44
|
+
*/
|
|
45
|
+
priority: Priority;
|
|
12
46
|
/**
|
|
13
47
|
* Half-extent of the watch arc in degrees. The arc spans `90° ± arcAngle`
|
|
14
48
|
* and pitch values are placed at their true position within it. Default
|
|
@@ -22,7 +56,10 @@ export declare class ObcPitch extends LitElement {
|
|
|
22
56
|
*/
|
|
23
57
|
arcAngle: number;
|
|
24
58
|
private _arcFrame;
|
|
59
|
+
private get scaleFillColor();
|
|
60
|
+
private get indicatorColor();
|
|
25
61
|
render(): import('lit-html').TemplateResult<1>;
|
|
62
|
+
private renderScale;
|
|
26
63
|
private get advices();
|
|
27
64
|
static styles: import('lit').CSSResult;
|
|
28
65
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pitch.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/pitch/pitch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAA0B,MAAM,KAAK,CAAC;AAExD,OAAO,mBAAmB,CAAC;AAC3B,OAAO,EACL,WAAW,
|
|
1
|
+
{"version":3,"file":"pitch.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/pitch/pitch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAA0B,MAAM,KAAK,CAAC;AAExD,OAAO,mBAAmB,CAAC;AAC3B,OAAO,EACL,WAAW,EAOZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,uBAAuB,CAAC;AAE/B,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AAerC,oBAAY,YAAY;IACtB,+CAA+C;IAC/C,WAAW,iBAAiB;IAC5B,iEAAiE;IACjE,SAAS,eAAe;CACzB;AAED;;;;;;;;;GASG;AACH,qBACa,QAAS,SAAQ,UAAU;IACZ,KAAK,SAAK;IACV,WAAW,SAAK;IAChB,WAAW,SAAK;IAChB,eAAe,EAAE,WAAW,CAAuB;IACnD,cAAc,EAAE,MAAM,GAAG,SAAS,CAAa;IAC9C,kBAAkB,UAAS;IAC3B,YAAY,EAAE,OAAO,CAAS;IACzD;;;;OAIG;IACwB,UAAU,EAAE,OAAO,CAAS;IACvD;;;OAGG;IACuB,IAAI,EAAE,YAAY,CAA4B;IACxE;;;OAGG;IACuB,QAAQ,EAAE,QAAQ,CAAoB;IAChE;;;;;;;;;;OAUG;IACuB,QAAQ,EAAE,MAAM,CAAM;IAEhD,OAAO,CAAC,SAAS,CAAgC;IAEjD,OAAO,KAAK,cAAc,GAIzB;IAED,OAAO,KAAK,cAAc,GAIzB;IAEQ,MAAM;IA4Hf,OAAO,CAAC,WAAW;IAuCnB,OAAO,KAAK,OAAO,GA4BlB;IAED,OAAgB,MAAM,0BA4BpB;CACH;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,WAAW,EAAE,QAAQ,CAAC;KACvB;CACF"}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { css, LitElement, nothing, svg, html } from "lit";
|
|
2
2
|
import { property } from "lit/decorators.js";
|
|
3
3
|
import { innerRingRadiusFor, WatchCircleType, OUTER_RING_RADIUS } from "../watch/watch.js";
|
|
4
|
+
import { ReadoutVariant, ReadoutDirection } from "../readout/readout.js";
|
|
5
|
+
import { Priority } from "../types.js";
|
|
4
6
|
import { TickmarkType } from "../watch/tickmark.js";
|
|
5
7
|
import { AdviceState, AdviceType } from "../watch/advice.js";
|
|
6
8
|
import { customElement } from "../../decorator.js";
|
|
7
9
|
import { normalizeArcAngle, computeZoomToFitArcFrame, shiftArcFrameToOuterEdge } from "../../svghelpers/arc-frame.js";
|
|
8
|
-
import { VesselImage,
|
|
10
|
+
import { VesselImage, vesselImages, VesselImageSize } from "../watch/vessel.js";
|
|
9
11
|
var __defProp = Object.defineProperty;
|
|
10
12
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
11
13
|
var __decorateClass = (decorators, target, key, kind) => {
|
|
@@ -18,6 +20,11 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
18
20
|
};
|
|
19
21
|
const watchRadius = OUTER_RING_RADIUS;
|
|
20
22
|
const CENTRE_HALF = 200;
|
|
23
|
+
var ObcPitchType = /* @__PURE__ */ ((ObcPitchType2) => {
|
|
24
|
+
ObcPitchType2["singleScale"] = "single-scale";
|
|
25
|
+
ObcPitchType2["dualScale"] = "dual-scale";
|
|
26
|
+
return ObcPitchType2;
|
|
27
|
+
})(ObcPitchType || {});
|
|
21
28
|
let ObcPitch = class extends LitElement {
|
|
22
29
|
constructor() {
|
|
23
30
|
super(...arguments);
|
|
@@ -28,8 +35,17 @@ let ObcPitch = class extends LitElement {
|
|
|
28
35
|
this.maxPitchAdvice = void 0;
|
|
29
36
|
this.triggerPitchAdvice = false;
|
|
30
37
|
this.zoomToFitArc = false;
|
|
38
|
+
this.hasReadout = false;
|
|
39
|
+
this.type = "single-scale";
|
|
40
|
+
this.priority = Priority.regular;
|
|
31
41
|
this.arcAngle = 45;
|
|
32
42
|
}
|
|
43
|
+
get scaleFillColor() {
|
|
44
|
+
return this.priority === Priority.enhanced ? "var(--instrument-enhanced-tertiary-color)" : "var(--instrument-regular-tertiary-color)";
|
|
45
|
+
}
|
|
46
|
+
get indicatorColor() {
|
|
47
|
+
return this.priority === Priority.enhanced ? "var(--instrument-enhanced-secondary-color)" : "var(--instrument-regular-secondary-color)";
|
|
48
|
+
}
|
|
33
49
|
render() {
|
|
34
50
|
const arcAngle = normalizeArcAngle(this.arcAngle, 45);
|
|
35
51
|
const x = watchRadius * Math.cos(arcAngle * Math.PI / 180);
|
|
@@ -67,96 +83,128 @@ let ObcPitch = class extends LitElement {
|
|
|
67
83
|
return html`
|
|
68
84
|
<div class="container">
|
|
69
85
|
<svg viewBox="${centreViewBox}">
|
|
70
|
-
${svg`
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
86
|
+
${this.hasReadout ? nothing : svg`
|
|
87
|
+
<line
|
|
88
|
+
x1="-${watchRadius}"
|
|
89
|
+
y1="0"
|
|
90
|
+
x2="${watchRadius}"
|
|
91
|
+
y2="0"
|
|
92
|
+
stroke="var(--instrument-frame-tertiary-color)"
|
|
93
|
+
/>
|
|
94
|
+
<line
|
|
95
|
+
x1="0"
|
|
96
|
+
y1="0"
|
|
97
|
+
x2="${watchRadius - 10}"
|
|
98
|
+
y2="0"
|
|
99
|
+
stroke="${this.indicatorColor}"
|
|
100
|
+
transform="${needleTransform}"
|
|
101
|
+
/>
|
|
102
|
+
<g
|
|
103
|
+
style="transform: rotate(${this.pitch}deg) scale(${vesselScale}) translate(-80px, -80px);"
|
|
104
|
+
>
|
|
105
|
+
${this.zoomToFitArc ? vesselImages[this.vesselImageSide] : nothing}
|
|
106
|
+
</g>
|
|
107
|
+
`}
|
|
108
|
+
${this.zoomToFitArc ? nothing : this.type === "dual-scale" ? svg`
|
|
109
|
+
<path
|
|
110
|
+
d="M ${x} ${-y} A ${watchRadius} ${watchRadius} 0 0 0 ${-x} ${-y}"
|
|
111
|
+
fill="none"
|
|
112
|
+
stroke="var(--instrument-frame-tertiary-color)"
|
|
113
|
+
/>
|
|
114
|
+
<path
|
|
115
|
+
d="M ${x} ${y} A ${watchRadius} ${watchRadius} 0 0 1 ${-x} ${y}"
|
|
116
|
+
fill="none"
|
|
117
|
+
stroke="var(--instrument-frame-tertiary-color)"
|
|
118
|
+
/>
|
|
119
|
+
` : svg`
|
|
120
|
+
<path
|
|
121
|
+
d="M ${x} ${y} A ${watchRadius} ${watchRadius} 0 1 1 ${x} ${-y}"
|
|
122
|
+
fill="none"
|
|
123
|
+
stroke="var(--instrument-frame-tertiary-color)"
|
|
124
|
+
/>
|
|
125
|
+
`}
|
|
99
126
|
</svg>
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
127
|
+
${this.renderScale(areas, false)}
|
|
128
|
+
${this.type === "dual-scale" ? this.renderScale(areas, true) : nothing}
|
|
129
|
+
${this.hasReadout ? html`<div class="readout">
|
|
130
|
+
<obc-readout
|
|
131
|
+
.variant=${ReadoutVariant.enhanced}
|
|
132
|
+
.direction=${ReadoutDirection.vertical}
|
|
133
|
+
.hasSetpoint=${false}
|
|
134
|
+
.hasAdvice=${false}
|
|
135
|
+
.value=${this.pitch}
|
|
136
|
+
.fractionDigits=${0}
|
|
137
|
+
.valuePriority=${this.priority}
|
|
138
|
+
label="Pitch"
|
|
139
|
+
unit="DEG"
|
|
140
|
+
></obc-readout>
|
|
141
|
+
</div>` : nothing}
|
|
142
|
+
</div>
|
|
143
|
+
`;
|
|
144
|
+
}
|
|
145
|
+
// `opposite` rotates a second watch 180° onto the opposite (left) arc for
|
|
146
|
+
// dual-scale — a rotation (opposite end of the indicator), not a mirror. A
|
|
147
|
+
// separate watch keeps the zoomed `arcFrame` correct.
|
|
148
|
+
renderScale(areas, opposite) {
|
|
149
|
+
return html`
|
|
150
|
+
<obc-watch
|
|
151
|
+
class=${opposite ? "scale-opposite" : nothing}
|
|
152
|
+
.priority=${this.priority}
|
|
153
|
+
.watchCircleType=${WatchCircleType.double}
|
|
154
|
+
.zoomToFitArc=${this.zoomToFitArc}
|
|
155
|
+
.arcFrame=${this._arcFrame}
|
|
156
|
+
tickmarksInside
|
|
157
|
+
.areas=${areas}
|
|
158
|
+
.barAreas=${[
|
|
106
159
|
{
|
|
107
160
|
startAngle: 90 + this.minAvgPitch,
|
|
108
161
|
endAngle: 90 + this.maxAvgPitch,
|
|
109
|
-
fillColor:
|
|
162
|
+
fillColor: this.scaleFillColor
|
|
110
163
|
}
|
|
111
164
|
]}
|
|
112
|
-
|
|
165
|
+
.needles=${[
|
|
113
166
|
{
|
|
114
167
|
angle: 90 + this.pitch,
|
|
115
|
-
fillColor:
|
|
168
|
+
fillColor: this.indicatorColor,
|
|
116
169
|
strokeColor: "var(--border-silhouette-color)"
|
|
117
170
|
}
|
|
118
171
|
]}
|
|
119
|
-
|
|
172
|
+
.vessels=${opposite || this.zoomToFitArc || this.hasReadout ? [] : [
|
|
120
173
|
{
|
|
121
174
|
size: VesselImageSize.large,
|
|
122
175
|
vesselImage: this.vesselImageSide,
|
|
123
176
|
transform: `rotate(${this.pitch}deg)`
|
|
124
177
|
}
|
|
125
178
|
]}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
type: TickmarkType.main
|
|
130
|
-
}
|
|
131
|
-
]}
|
|
132
|
-
.advices=${this.advices}
|
|
133
|
-
></obc-watch>
|
|
134
|
-
</div>
|
|
179
|
+
.tickmarks=${[{ angle: 90, type: TickmarkType.main }]}
|
|
180
|
+
.advices=${this.advices}
|
|
181
|
+
></obc-watch>
|
|
135
182
|
`;
|
|
136
183
|
}
|
|
137
184
|
get advices() {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
185
|
+
if (this.maxPitchAdvice === void 0) {
|
|
186
|
+
return [];
|
|
187
|
+
}
|
|
188
|
+
const arcAngle = normalizeArcAngle(this.arcAngle, 45);
|
|
189
|
+
const outer = Math.min(arcAngle, 30);
|
|
190
|
+
const inner = Math.min(this.maxPitchAdvice, outer);
|
|
191
|
+
const state = this.triggerPitchAdvice ? AdviceState.triggered : AdviceState.regular;
|
|
192
|
+
return [
|
|
193
|
+
{
|
|
145
194
|
minAngle: 90 - outer,
|
|
146
195
|
maxAngle: 90 - inner,
|
|
147
196
|
type: AdviceType.caution,
|
|
148
197
|
state,
|
|
149
198
|
hideMinTickmark: true
|
|
150
|
-
}
|
|
151
|
-
|
|
199
|
+
},
|
|
200
|
+
{
|
|
152
201
|
minAngle: 90 + inner,
|
|
153
202
|
maxAngle: 90 + outer,
|
|
154
203
|
type: AdviceType.caution,
|
|
155
204
|
state,
|
|
156
205
|
hideMaxTickmark: true
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
return advices;
|
|
206
|
+
}
|
|
207
|
+
];
|
|
160
208
|
}
|
|
161
209
|
};
|
|
162
210
|
ObcPitch.styles = css`
|
|
@@ -177,6 +225,16 @@ ObcPitch.styles = css`
|
|
|
177
225
|
width: 100%;
|
|
178
226
|
height: 100%;
|
|
179
227
|
}
|
|
228
|
+
|
|
229
|
+
.readout {
|
|
230
|
+
display: flex;
|
|
231
|
+
align-items: center;
|
|
232
|
+
justify-content: center;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
.scale-opposite {
|
|
236
|
+
transform: rotate(180deg);
|
|
237
|
+
}
|
|
180
238
|
`;
|
|
181
239
|
__decorateClass([
|
|
182
240
|
property({ type: Number })
|
|
@@ -199,6 +257,15 @@ __decorateClass([
|
|
|
199
257
|
__decorateClass([
|
|
200
258
|
property({ type: Boolean })
|
|
201
259
|
], ObcPitch.prototype, "zoomToFitArc", 2);
|
|
260
|
+
__decorateClass([
|
|
261
|
+
property({ type: Boolean })
|
|
262
|
+
], ObcPitch.prototype, "hasReadout", 2);
|
|
263
|
+
__decorateClass([
|
|
264
|
+
property({ type: String })
|
|
265
|
+
], ObcPitch.prototype, "type", 2);
|
|
266
|
+
__decorateClass([
|
|
267
|
+
property({ type: String })
|
|
268
|
+
], ObcPitch.prototype, "priority", 2);
|
|
202
269
|
__decorateClass([
|
|
203
270
|
property({ type: Number })
|
|
204
271
|
], ObcPitch.prototype, "arcAngle", 2);
|
|
@@ -206,6 +273,7 @@ ObcPitch = __decorateClass([
|
|
|
206
273
|
customElement("obc-pitch")
|
|
207
274
|
], ObcPitch);
|
|
208
275
|
export {
|
|
209
|
-
ObcPitch
|
|
276
|
+
ObcPitch,
|
|
277
|
+
ObcPitchType
|
|
210
278
|
};
|
|
211
279
|
//# sourceMappingURL=pitch.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pitch.js","sources":["../../../src/navigation-instruments/pitch/pitch.ts"],"sourcesContent":["import {LitElement, css, html, nothing, svg} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport '../watch/watch.js';\nimport {\n VesselImage,\n VesselImageSize,\n WatchCircleType,\n OUTER_RING_RADIUS,\n innerRingRadiusFor,\n vesselImages,\n} from '../watch/watch.js';\nimport {TickmarkType} from '../watch/tickmark.js';\nimport {AdviceState, AdviceType, AngleAdviceRaw} from '../watch/advice.js';\nimport {customElement} from '../../decorator.js';\nimport {\n computeZoomToFitArcFrame,\n normalizeArcAngle,\n shiftArcFrameToOuterEdge,\n type ZoomToFitArcFrame,\n} from '../../svghelpers/arc-frame.js';\n\nconst watchRadius = OUTER_RING_RADIUS;\n/** Half-side of the centre overlay viewBox in SVG units. */\nconst CENTRE_HALF = 200;\n\n@customElement('obc-pitch')\nexport class ObcPitch extends LitElement {\n @property({type: Number}) pitch = 0;\n @property({type: Number}) minAvgPitch = 0;\n @property({type: Number}) maxAvgPitch = 0;\n @property({type: String}) vesselImageSide: VesselImage = VesselImage.psvSide;\n @property({type: Number}) maxPitchAdvice: number | undefined = undefined;\n @property({type: Boolean}) triggerPitchAdvice = false;\n @property({type: Boolean}) zoomToFitArc: boolean = false;\n /**\n * Half-extent of the watch arc in degrees. The arc spans `90° ± arcAngle`\n * and pitch values are placed at their true position within it. Default\n * `45` reproduces the historical 90°-wide arc.\n *\n * Smaller values render a narrower arc. Combined with `zoomToFitArc`, the\n * narrower arc is enlarged (its radius grows) on its own layer, while the\n * vessel image and the rotating indicator line stay at their natural size\n * and position on a separate central layer. The two layers are\n * intentionally visually disconnected.\n */\n @property({type: Number}) arcAngle: number = 45;\n\n private _arcFrame: ZoomToFitArcFrame | undefined;\n\n override render() {\n const arcAngle = normalizeArcAngle(this.arcAngle, 45);\n // Outer thin-ring complement endpoints. The arc band is centred at\n // watch angle 90° (right side) and spans 90° ± arcAngle, so its edges\n // sit at SVG coords (R·cos(arcAngle), ±R·sin(arcAngle)).\n const x = watchRadius * Math.cos((arcAngle * Math.PI) / 180);\n const y = watchRadius * Math.sin((arcAngle * Math.PI) / 180);\n\n const areas = [\n {\n startAngle: 90 - arcAngle,\n endAngle: 90 + arcAngle,\n roundOutsideCut: true,\n roundInsideCut: true,\n },\n ];\n\n if (this.zoomToFitArc) {\n const ext = 48;\n const targetSize = (176 + ext) * 2;\n // Pure arc-only fit (compass-sector style). The viewBox is centred on\n // the enlarged arc bbox, so the origin (centre of the instrument) is\n // typically OUTSIDE this viewBox. The vessel and central elements\n // therefore need their own normal-scale layer.\n const baseFrame = computeZoomToFitArcFrame({\n areas,\n outerRadius: OUTER_RING_RADIUS,\n innerRadius: innerRingRadiusFor(WatchCircleType.double),\n extension: ext,\n targetSize,\n });\n // Push the enlarged arc to the side so its outer edge aligns with the\n // central layer's outer ring. Direction is derived from the arc bbox\n // centre so left/right/top/bottom is handled automatically.\n this._arcFrame = shiftArcFrameToOuterEdge(\n baseFrame,\n OUTER_RING_RADIUS + baseFrame.radiusOffset,\n OUTER_RING_RADIUS,\n CENTRE_HALF\n );\n } else {\n this._arcFrame = undefined;\n }\n\n const needleTransform = `rotate(${this.pitch} 0 0)`;\n const centreViewBox = `-${CENTRE_HALF} -${CENTRE_HALF} ${CENTRE_HALF * 2} ${CENTRE_HALF * 2}`;\n const vesselScale = 224 / 160;\n\n return html`\n <div class=\"container\">\n <svg viewBox=\"${centreViewBox}\">\n ${svg`\n <line\n x1=\"-${watchRadius}\"\n y1=\"0\"\n x2=\"${watchRadius}\"\n y2=\"0\"\n stroke=\"var(--instrument-frame-tertiary-color)\"\n />\n <line\n x1=\"0\"\n y1=\"0\"\n x2=\"${watchRadius - 10}\"\n y2=\"0\"\n stroke=\"var(--instrument-enhanced-secondary-color)\"\n transform=\"${needleTransform}\"\n />\n <g\n style=\"transform: rotate(${this.pitch}deg) scale(${vesselScale}) translate(-80px, -80px);\"\n >\n ${vesselImages[this.vesselImageSide]}\n </g>\n ${\n this.zoomToFitArc\n ? nothing\n : svg`\n <path\n d=\"M ${x} ${y} A ${watchRadius} ${watchRadius} 0 1 1 ${x} ${-y}\"\n fill=\"none\"\n stroke=\"var(--instrument-frame-tertiary-color)\"\n />\n `\n }\n `}\n </svg>\n <obc-watch\n .watchCircleType=${WatchCircleType.double}\n .zoomToFitArc=${this.zoomToFitArc}\n .arcFrame=${this._arcFrame}\n .areas=${areas}\n .barAreas=${[\n {\n startAngle: 90 + this.minAvgPitch,\n endAngle: 90 + this.maxAvgPitch,\n fillColor: 'var(--instrument-enhanced-tertiary-color)',\n },\n ]}\n .needles=${[\n {\n angle: 90 + this.pitch,\n fillColor: 'var(--instrument-enhanced-secondary-color)',\n strokeColor: 'var(--border-silhouette-color)',\n },\n ]}\n .vessels=${this.zoomToFitArc\n ? []\n : [\n {\n size: VesselImageSize.large,\n vesselImage: this.vesselImageSide,\n transform: `rotate(${this.pitch}deg)`,\n },\n ]}\n .tickmarks=${[\n {\n angle: 90,\n type: TickmarkType.main,\n },\n ]}\n .advices=${this.advices}\n ></obc-watch>\n </div>\n `;\n }\n\n private get advices(): AngleAdviceRaw[] {\n const advices = [];\n if (this.maxPitchAdvice !== undefined) {\n const arcAngle = normalizeArcAngle(this.arcAngle, 45);\n // Caution band fills the remainder of the arc out to a default 30°\n // caution range (clamped to the arc edge).\n const outer = Math.min(arcAngle, 30);\n const inner = Math.min(this.maxPitchAdvice, outer);\n const state = this.triggerPitchAdvice\n ? AdviceState.triggered\n : AdviceState.regular;\n advices.push({\n minAngle: 90 - outer,\n maxAngle: 90 - inner,\n type: AdviceType.caution,\n state: state,\n hideMinTickmark: true,\n });\n advices.push({\n minAngle: 90 + inner,\n maxAngle: 90 + outer,\n type: AdviceType.caution,\n state: state,\n hideMaxTickmark: true,\n });\n }\n return advices;\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-pitch': ObcPitch;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pitch.js","sources":["../../../src/navigation-instruments/pitch/pitch.ts"],"sourcesContent":["import {LitElement, css, html, nothing, svg} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport '../watch/watch.js';\nimport {\n VesselImage,\n VesselImageSize,\n WatchCircleType,\n OUTER_RING_RADIUS,\n innerRingRadiusFor,\n vesselImages,\n type WatchArea,\n} from '../watch/watch.js';\nimport '../readout/readout.js';\nimport {ReadoutDirection, ReadoutVariant} from '../readout/readout.js';\nimport {Priority} from '../types.js';\nimport {TickmarkType} from '../watch/tickmark.js';\nimport {AdviceState, AdviceType, AngleAdviceRaw} from '../watch/advice.js';\nimport {customElement} from '../../decorator.js';\nimport {\n computeZoomToFitArcFrame,\n normalizeArcAngle,\n shiftArcFrameToOuterEdge,\n type ZoomToFitArcFrame,\n} from '../../svghelpers/arc-frame.js';\n\nconst watchRadius = OUTER_RING_RADIUS;\n/** Half-side of the centre overlay viewBox in SVG units. */\nconst CENTRE_HALF = 200;\n\nexport enum ObcPitchType {\n /** Single arc scale on the right (default). */\n singleScale = 'single-scale',\n /** Right scale duplicated to the opposite (left) arc as well. */\n dualScale = 'dual-scale',\n}\n\n/**\n * `<obc-pitch>` — Pitch (trim) indicator with a side arc scale.\n *\n * Shows `pitch` against a watch arc centred on the right, with an average-pitch\n * band and a rotating indicator. Supports an optional opposite-side scale\n * (`dual-scale`), a centre readout (`hasReadout`), and a `regular`/`enhanced`\n * palette.\n *\n * @element obc-pitch\n */\n@customElement('obc-pitch')\nexport class ObcPitch extends LitElement {\n @property({type: Number}) pitch = 0;\n @property({type: Number}) minAvgPitch = 0;\n @property({type: Number}) maxAvgPitch = 0;\n @property({type: String}) vesselImageSide: VesselImage = VesselImage.psvSide;\n @property({type: Number}) maxPitchAdvice: number | undefined = undefined;\n @property({type: Boolean}) triggerPitchAdvice = false;\n @property({type: Boolean}) zoomToFitArc: boolean = false;\n /**\n * When `true`, the centre shows an `<obc-readout>` with the pitch value\n * (label `Pitch`, unit `DEG`) instead of the horizon line, rotating indicator\n * and vessel. Default `false`.\n */\n @property({type: Boolean}) hasReadout: boolean = false;\n /**\n * `single-scale` shows one arc on the right (default); `dual-scale` also\n * shows the scale on the opposite (left) arc (the indicator's opposite end).\n */\n @property({type: String}) type: ObcPitchType = ObcPitchType.singleScale;\n /**\n * Colour palette for the scale fill / indicator and the readout value:\n * `regular` (default) or `enhanced`.\n */\n @property({type: String}) priority: Priority = Priority.regular;\n /**\n * Half-extent of the watch arc in degrees. The arc spans `90° ± arcAngle`\n * and pitch values are placed at their true position within it. Default\n * `45` reproduces the historical 90°-wide arc.\n *\n * Smaller values render a narrower arc. Combined with `zoomToFitArc`, the\n * narrower arc is enlarged (its radius grows) on its own layer, while the\n * vessel image and the rotating indicator line stay at their natural size\n * and position on a separate central layer. The two layers are\n * intentionally visually disconnected.\n */\n @property({type: Number}) arcAngle: number = 45;\n\n private _arcFrame: ZoomToFitArcFrame | undefined;\n\n private get scaleFillColor(): string {\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-tertiary-color)'\n : 'var(--instrument-regular-tertiary-color)';\n }\n\n private get indicatorColor(): string {\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n\n override render() {\n const arcAngle = normalizeArcAngle(this.arcAngle, 45);\n // Outer thin-ring complement endpoints. The arc band is centred at\n // watch angle 90° (right side) and spans 90° ± arcAngle, so its edges\n // sit at SVG coords (R·cos(arcAngle), ±R·sin(arcAngle)).\n const x = watchRadius * Math.cos((arcAngle * Math.PI) / 180);\n const y = watchRadius * Math.sin((arcAngle * Math.PI) / 180);\n\n const areas: WatchArea[] = [\n {\n startAngle: 90 - arcAngle,\n endAngle: 90 + arcAngle,\n roundOutsideCut: true,\n roundInsideCut: true,\n },\n ];\n\n if (this.zoomToFitArc) {\n const ext = 48;\n const targetSize = (176 + ext) * 2;\n // Pure arc-only fit (compass-sector style). The viewBox is centred on\n // the enlarged arc bbox, so the origin (centre of the instrument) is\n // typically OUTSIDE this viewBox. The vessel and central elements\n // therefore need their own normal-scale layer.\n const baseFrame = computeZoomToFitArcFrame({\n areas,\n outerRadius: OUTER_RING_RADIUS,\n innerRadius: innerRingRadiusFor(WatchCircleType.double),\n extension: ext,\n targetSize,\n });\n // Push the enlarged arc to the side so its outer edge aligns with the\n // central layer's outer ring. Direction is derived from the arc bbox\n // centre so left/right/top/bottom is handled automatically.\n this._arcFrame = shiftArcFrameToOuterEdge(\n baseFrame,\n OUTER_RING_RADIUS + baseFrame.radiusOffset,\n OUTER_RING_RADIUS,\n CENTRE_HALF\n );\n } else {\n this._arcFrame = undefined;\n }\n\n const needleTransform = `rotate(${this.pitch} 0 0)`;\n const centreViewBox = `-${CENTRE_HALF} -${CENTRE_HALF} ${CENTRE_HALF * 2} ${CENTRE_HALF * 2}`;\n const vesselScale = 224 / 160;\n\n return html`\n <div class=\"container\">\n <svg viewBox=\"${centreViewBox}\">\n ${this.hasReadout\n ? nothing\n : svg`\n <line\n x1=\"-${watchRadius}\"\n y1=\"0\"\n x2=\"${watchRadius}\"\n y2=\"0\"\n stroke=\"var(--instrument-frame-tertiary-color)\"\n />\n <line\n x1=\"0\"\n y1=\"0\"\n x2=\"${watchRadius - 10}\"\n y2=\"0\"\n stroke=\"${this.indicatorColor}\"\n transform=\"${needleTransform}\"\n />\n <g\n style=\"transform: rotate(${this.pitch}deg) scale(${vesselScale}) translate(-80px, -80px);\"\n >\n ${this.zoomToFitArc ? vesselImages[this.vesselImageSide] : nothing}\n </g>\n `}\n ${this.zoomToFitArc\n ? nothing\n : this.type === ObcPitchType.dualScale\n ? svg`\n <path\n d=\"M ${x} ${-y} A ${watchRadius} ${watchRadius} 0 0 0 ${-x} ${-y}\"\n fill=\"none\"\n stroke=\"var(--instrument-frame-tertiary-color)\"\n />\n <path\n d=\"M ${x} ${y} A ${watchRadius} ${watchRadius} 0 0 1 ${-x} ${y}\"\n fill=\"none\"\n stroke=\"var(--instrument-frame-tertiary-color)\"\n />\n `\n : svg`\n <path\n d=\"M ${x} ${y} A ${watchRadius} ${watchRadius} 0 1 1 ${x} ${-y}\"\n fill=\"none\"\n stroke=\"var(--instrument-frame-tertiary-color)\"\n />\n `}\n </svg>\n ${this.renderScale(areas, false)}\n ${this.type === ObcPitchType.dualScale\n ? this.renderScale(areas, true)\n : nothing}\n ${this.hasReadout\n ? html`<div class=\"readout\">\n <obc-readout\n .variant=${ReadoutVariant.enhanced}\n .direction=${ReadoutDirection.vertical}\n .hasSetpoint=${false}\n .hasAdvice=${false}\n .value=${this.pitch}\n .fractionDigits=${0}\n .valuePriority=${this.priority}\n label=\"Pitch\"\n unit=\"DEG\"\n ></obc-readout>\n </div>`\n : nothing}\n </div>\n `;\n }\n\n // `opposite` rotates a second watch 180° onto the opposite (left) arc for\n // dual-scale — a rotation (opposite end of the indicator), not a mirror. A\n // separate watch keeps the zoomed `arcFrame` correct.\n private renderScale(areas: WatchArea[], opposite: boolean) {\n return html`\n <obc-watch\n class=${opposite ? 'scale-opposite' : nothing}\n .priority=${this.priority}\n .watchCircleType=${WatchCircleType.double}\n .zoomToFitArc=${this.zoomToFitArc}\n .arcFrame=${this._arcFrame}\n tickmarksInside\n .areas=${areas}\n .barAreas=${[\n {\n startAngle: 90 + this.minAvgPitch,\n endAngle: 90 + this.maxAvgPitch,\n fillColor: this.scaleFillColor,\n },\n ]}\n .needles=${[\n {\n angle: 90 + this.pitch,\n fillColor: this.indicatorColor,\n strokeColor: 'var(--border-silhouette-color)',\n },\n ]}\n .vessels=${opposite || this.zoomToFitArc || this.hasReadout\n ? []\n : [\n {\n size: VesselImageSize.large,\n vesselImage: this.vesselImageSide,\n transform: `rotate(${this.pitch}deg)`,\n },\n ]}\n .tickmarks=${[{angle: 90, type: TickmarkType.main}]}\n .advices=${this.advices}\n ></obc-watch>\n `;\n }\n\n private get advices(): AngleAdviceRaw[] {\n if (this.maxPitchAdvice === undefined) {\n return [];\n }\n const arcAngle = normalizeArcAngle(this.arcAngle, 45);\n // Caution band fills the remainder of the arc out to a default 30° caution\n // range (clamped to the arc edge).\n const outer = Math.min(arcAngle, 30);\n const inner = Math.min(this.maxPitchAdvice, outer);\n const state = this.triggerPitchAdvice\n ? AdviceState.triggered\n : AdviceState.regular;\n return [\n {\n minAngle: 90 - outer,\n maxAngle: 90 - inner,\n type: AdviceType.caution,\n state: state,\n hideMinTickmark: true,\n },\n {\n minAngle: 90 + inner,\n maxAngle: 90 + outer,\n type: AdviceType.caution,\n state: state,\n hideMaxTickmark: true,\n },\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 .readout {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .scale-opposite {\n transform: rotate(180deg);\n }\n `;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-pitch': ObcPitch;\n }\n}\n"],"names":["ObcPitchType"],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ import { LitElement } from 'lit';
|
|
|
2
2
|
import { VesselImage } from '../watch/watch.js';
|
|
3
3
|
import { Priority } from '../types.js';
|
|
4
4
|
import '../watch/watch.js';
|
|
5
|
+
import '../readout/readout.js';
|
|
5
6
|
export declare enum PitchRollPriorityElement {
|
|
6
7
|
pitch = "pitch",
|
|
7
8
|
roll = "roll"
|
|
@@ -22,6 +23,11 @@ export declare class ObcPitchRoll extends LitElement {
|
|
|
22
23
|
triggerRollAdvice: boolean;
|
|
23
24
|
priority: Priority;
|
|
24
25
|
priorityElements: PitchRollPriorityElement[];
|
|
26
|
+
/**
|
|
27
|
+
* When `true`, the centre shows two stacked `<obc-readout>`s (pitch above
|
|
28
|
+
* roll) instead of the vessel images. Default `false`.
|
|
29
|
+
*/
|
|
30
|
+
hasReadout: boolean;
|
|
25
31
|
zoomToFitArc: boolean;
|
|
26
32
|
/**
|
|
27
33
|
* Half-extent of each of the four watch arcs in degrees, measured from the
|
|
@@ -50,6 +56,7 @@ export declare class ObcPitchRoll extends LitElement {
|
|
|
50
56
|
private get requestedPitchArcAngle();
|
|
51
57
|
private get requestedRollArcAngle();
|
|
52
58
|
render(): import('lit-html').TemplateResult<1>;
|
|
59
|
+
private renderReadout;
|
|
53
60
|
/**
|
|
54
61
|
* Zoomed-arc layer: four CSS-rotated `<obc-watch>` instances, each
|
|
55
62
|
* containing a single arc rendered at the watch's natural top
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pitch-roll.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/pitch-roll/pitch-roll.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAA0B,MAAM,KAAK,CAAC;AAExD,OAAO,mBAAmB,CAAC;AAC3B,OAAO,EACL,WAAW,EAOZ,MAAM,mBAAmB,CAAC;AAI3B,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"pitch-roll.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/pitch-roll/pitch-roll.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAA0B,MAAM,KAAK,CAAC;AAExD,OAAO,mBAAmB,CAAC;AAC3B,OAAO,EACL,WAAW,EAOZ,MAAM,mBAAmB,CAAC;AAI3B,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AACrC,OAAO,uBAAuB,CAAC;AAQ/B,oBAAY,wBAAwB;IAClC,KAAK,UAAU;IACf,IAAI,SAAS;CACd;AAqBD,qBACa,YAAa,SAAQ,UAAU;IAChB,KAAK,SAAK;IACV,IAAI,SAAK;IACT,WAAW,SAAK;IAChB,WAAW,SAAK;IAChB,UAAU,SAAK;IACf,UAAU,SAAK;IACf,eAAe,EAAE,WAAW,CAAuB;IACnD,eAAe,EAAE,WAAW,CAAuB;IACnD,cAAc,SAAK;IACnB,cAAc,EAAE,MAAM,GAAG,SAAS,CAAa;IAC/C,aAAa,EAAE,MAAM,GAAG,SAAS,CAAa;IAC7C,kBAAkB,UAAS;IAC3B,iBAAiB,UAAS;IAC3B,QAAQ,EAAE,QAAQ,CAAoB;IAEhE,gBAAgB,EAAE,wBAAwB,EAAE,CAG1C;IACF;;;OAGG;IACwB,UAAU,EAAE,OAAO,CAAS;IAC5B,YAAY,EAAE,OAAO,CAAS;IACzD;;;;;;OAMG;IACuB,QAAQ,EAAE,MAAM,CAAM;IAChD;;;;OAIG;IACuB,aAAa,CAAC,EAAE,MAAM,CAAC;IACjD;;;OAGG;IACuB,YAAY,CAAC,EAAE,MAAM,CAAC;IAEhD,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,QAAQ;IAMhB,OAAO,KAAK,wBAAwB,GAKnC;IAED,kEAAkE;IAClE,OAAO,KAAK,sBAAsB,GAEjC;IACD,OAAO,KAAK,qBAAqB,GAEhC;IAEQ,MAAM;IAkFf,OAAO,CAAC,aAAa;IAoBrB;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,OAAO,CAAC,gBAAgB;IA6RxB;;;;;;OAMG;IACH,OAAO,CAAC,UAAU;IA8BlB,6DAA6D;IAC7D,OAAO,CAAC,eAAe;IA2EvB,OAAO,KAAK,OAAO,GA2ElB;IAED,OAAgB,MAAM,0BAqCpB;CACH;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,gBAAgB,EAAE,YAAY,CAAC;KAChC;CACF"}
|
|
@@ -5,6 +5,7 @@ import { TickmarkType } from "../watch/tickmark.js";
|
|
|
5
5
|
import { AdviceState, AdviceType } from "../watch/advice.js";
|
|
6
6
|
import { customElement } from "../../decorator.js";
|
|
7
7
|
import { Priority } from "../types.js";
|
|
8
|
+
import { ReadoutVariant, ReadoutDirection } from "../readout/readout.js";
|
|
8
9
|
import { normalizeArcAngle, computeZoomToFitArcFrame, shiftArcFrameToOuterEdge } from "../../svghelpers/arc-frame.js";
|
|
9
10
|
import { VesselImage, vesselImages, VesselImageSize } from "../watch/vessel.js";
|
|
10
11
|
var __defProp = Object.defineProperty;
|
|
@@ -47,6 +48,7 @@ let ObcPitchRoll = class extends LitElement {
|
|
|
47
48
|
"roll"
|
|
48
49
|
/* roll */
|
|
49
50
|
];
|
|
51
|
+
this.hasReadout = false;
|
|
50
52
|
this.zoomToFitArc = false;
|
|
51
53
|
this.arcAngle = 30;
|
|
52
54
|
}
|
|
@@ -107,7 +109,7 @@ let ObcPitchRoll = class extends LitElement {
|
|
|
107
109
|
return html`
|
|
108
110
|
<div class="container">
|
|
109
111
|
<svg viewBox="${overlayViewBox}">
|
|
110
|
-
${svg`
|
|
112
|
+
${this.hasReadout ? nothing : svg`
|
|
111
113
|
<line
|
|
112
114
|
x1="-150"
|
|
113
115
|
y1="0"
|
|
@@ -128,9 +130,41 @@ let ObcPitchRoll = class extends LitElement {
|
|
|
128
130
|
`}
|
|
129
131
|
</svg>
|
|
130
132
|
${this.zoomToFitArc ? this.renderZoomedArcs(pitchReq, rollReq) : this.renderFullWatch(areas)}
|
|
133
|
+
${this.hasReadout ? html`<div class="readout">
|
|
134
|
+
<div class="readout-group">
|
|
135
|
+
${this.renderReadout(
|
|
136
|
+
this.pitch,
|
|
137
|
+
"Pitch",
|
|
138
|
+
"pitch"
|
|
139
|
+
/* pitch */
|
|
140
|
+
)}
|
|
141
|
+
<div class="readout-divider"></div>
|
|
142
|
+
${this.renderReadout(
|
|
143
|
+
this.roll,
|
|
144
|
+
"Roll",
|
|
145
|
+
"roll"
|
|
146
|
+
/* roll */
|
|
147
|
+
)}
|
|
148
|
+
</div>
|
|
149
|
+
</div>` : nothing}
|
|
131
150
|
</div>
|
|
132
151
|
`;
|
|
133
152
|
}
|
|
153
|
+
renderReadout(value, label, element) {
|
|
154
|
+
return html`
|
|
155
|
+
<obc-readout
|
|
156
|
+
.variant=${ReadoutVariant.enhanced}
|
|
157
|
+
.direction=${ReadoutDirection.vertical}
|
|
158
|
+
.hasSetpoint=${false}
|
|
159
|
+
.hasAdvice=${false}
|
|
160
|
+
.value=${value}
|
|
161
|
+
.fractionDigits=${0}
|
|
162
|
+
.valuePriority=${this.priorityFor(element)}
|
|
163
|
+
label=${label}
|
|
164
|
+
unit="DEG"
|
|
165
|
+
></obc-readout>
|
|
166
|
+
`;
|
|
167
|
+
}
|
|
134
168
|
/**
|
|
135
169
|
* Zoomed-arc layer: four CSS-rotated `<obc-watch>` instances, each
|
|
136
170
|
* containing a single arc rendered at the watch's natural top
|
|
@@ -460,7 +494,7 @@ let ObcPitchRoll = class extends LitElement {
|
|
|
460
494
|
strokeColor: "var(--border-silhouette-color)"
|
|
461
495
|
}
|
|
462
496
|
]}
|
|
463
|
-
.vessels=${[
|
|
497
|
+
.vessels=${this.hasReadout ? [] : [
|
|
464
498
|
{
|
|
465
499
|
size: VesselImageSize.large,
|
|
466
500
|
vesselImage: this.vesselImageSide,
|
|
@@ -573,6 +607,25 @@ ObcPitchRoll.styles = css`
|
|
|
573
607
|
width: 100%;
|
|
574
608
|
height: 100%;
|
|
575
609
|
}
|
|
610
|
+
|
|
611
|
+
.readout {
|
|
612
|
+
display: flex;
|
|
613
|
+
align-items: center;
|
|
614
|
+
justify-content: center;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
.readout-group {
|
|
618
|
+
display: flex;
|
|
619
|
+
flex-direction: column;
|
|
620
|
+
align-items: center;
|
|
621
|
+
width: fit-content;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
.readout-divider {
|
|
625
|
+
align-self: stretch;
|
|
626
|
+
height: 1px;
|
|
627
|
+
background: var(--border-divider-color);
|
|
628
|
+
}
|
|
576
629
|
`;
|
|
577
630
|
__decorateClass([
|
|
578
631
|
property({ type: Number })
|
|
@@ -619,6 +672,9 @@ __decorateClass([
|
|
|
619
672
|
__decorateClass([
|
|
620
673
|
property({ type: Array, attribute: false })
|
|
621
674
|
], ObcPitchRoll.prototype, "priorityElements", 2);
|
|
675
|
+
__decorateClass([
|
|
676
|
+
property({ type: Boolean })
|
|
677
|
+
], ObcPitchRoll.prototype, "hasReadout", 2);
|
|
622
678
|
__decorateClass([
|
|
623
679
|
property({ type: Boolean })
|
|
624
680
|
], ObcPitchRoll.prototype, "zoomToFitArc", 2);
|