@oicl/openbridge-webcomponents-full-bundle 2.0.0-next.101 → 2.0.0-next.103
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/openbridge-webcomponents.bundle.js +580 -143
- package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
- package/custom-elements.json +629 -407
- package/dist/bars-graphs/donut-chart/donut-chart.d.ts +18 -16
- package/dist/bars-graphs/donut-chart/donut-chart.d.ts.map +1 -1
- package/dist/bars-graphs/donut-chart/donut-chart.js.map +1 -1
- package/dist/bars-graphs/pie-chart/pie-chart.d.ts +14 -12
- package/dist/bars-graphs/pie-chart/pie-chart.d.ts.map +1 -1
- package/dist/bars-graphs/pie-chart/pie-chart.js.map +1 -1
- package/dist/bars-graphs/polar-chart/polar-chart.d.ts +19 -16
- package/dist/bars-graphs/polar-chart/polar-chart.d.ts.map +1 -1
- package/dist/bars-graphs/polar-chart/polar-chart.js.map +1 -1
- package/dist/bars-graphs/radial-bar-chart/radial-bar-chart.d.ts +8 -8
- package/dist/bars-graphs/radial-bar-chart/radial-bar-chart.d.ts.map +1 -1
- package/dist/bars-graphs/radial-bar-chart/radial-bar-chart.js.map +1 -1
- package/dist/building-blocks/chart-line/chart-line-base.d.ts +8 -25
- package/dist/building-blocks/chart-line/chart-line-base.d.ts.map +1 -1
- package/dist/building-blocks/chart-line/chart-line-base.js.map +1 -1
- package/dist/building-blocks/instrument-radial/instrument-radial.d.ts +22 -2
- package/dist/building-blocks/instrument-radial/instrument-radial.d.ts.map +1 -1
- package/dist/building-blocks/instrument-radial/instrument-radial.js +61 -37
- package/dist/building-blocks/instrument-radial/instrument-radial.js.map +1 -1
- package/dist/integration-systems/integration-bar/integration-bar.d.ts +20 -24
- package/dist/integration-systems/integration-bar/integration-bar.d.ts.map +1 -1
- package/dist/integration-systems/integration-bar/integration-bar.js.map +1 -1
- package/dist/integration-systems/integration-button/integration-button.d.ts +15 -13
- package/dist/integration-systems/integration-button/integration-button.d.ts.map +1 -1
- package/dist/integration-systems/integration-button/integration-button.js.map +1 -1
- package/dist/navigation-instruments/azimuth-thruster/azimuth-thruster.d.ts +14 -0
- package/dist/navigation-instruments/azimuth-thruster/azimuth-thruster.d.ts.map +1 -1
- package/dist/navigation-instruments/azimuth-thruster/azimuth-thruster.js +30 -11
- package/dist/navigation-instruments/azimuth-thruster/azimuth-thruster.js.map +1 -1
- package/dist/navigation-instruments/compass/compass.d.ts +68 -31
- package/dist/navigation-instruments/compass/compass.d.ts.map +1 -1
- package/dist/navigation-instruments/compass/compass.js +36 -16
- package/dist/navigation-instruments/compass/compass.js.map +1 -1
- package/dist/navigation-instruments/compass-flat/compass-flat.d.ts +8 -9
- package/dist/navigation-instruments/compass-flat/compass-flat.d.ts.map +1 -1
- package/dist/navigation-instruments/compass-flat/compass-flat.js.map +1 -1
- package/dist/navigation-instruments/compass-sector/compass-sector.d.ts.map +1 -1
- package/dist/navigation-instruments/compass-sector/compass-sector.js.map +1 -1
- package/dist/navigation-instruments/gauge-radial/gauge-radial.css.js +34 -2
- package/dist/navigation-instruments/gauge-radial/gauge-radial.css.js.map +1 -1
- package/dist/navigation-instruments/gauge-radial/gauge-radial.d.ts +15 -0
- package/dist/navigation-instruments/gauge-radial/gauge-radial.d.ts.map +1 -1
- package/dist/navigation-instruments/gauge-radial/gauge-radial.js +35 -1
- package/dist/navigation-instruments/gauge-radial/gauge-radial.js.map +1 -1
- package/dist/navigation-instruments/gauge-trend/gauge-trend.d.ts +0 -5
- package/dist/navigation-instruments/gauge-trend/gauge-trend.d.ts.map +1 -1
- package/dist/navigation-instruments/gauge-trend/gauge-trend.js.map +1 -1
- package/dist/navigation-instruments/graph-mini/graph-mini.d.ts +1 -1
- package/dist/navigation-instruments/graph-mini/graph-mini.d.ts.map +1 -1
- package/dist/navigation-instruments/graph-mini/graph-mini.js.map +1 -1
- package/dist/navigation-instruments/heading/heading.d.ts +19 -1
- package/dist/navigation-instruments/heading/heading.d.ts.map +1 -1
- package/dist/navigation-instruments/heading/heading.js +34 -16
- package/dist/navigation-instruments/heading/heading.js.map +1 -1
- package/dist/navigation-instruments/indicator-graph/indicator-graph.d.ts +1 -1
- package/dist/navigation-instruments/indicator-graph/indicator-graph.d.ts.map +1 -1
- package/dist/navigation-instruments/indicator-graph/indicator-graph.js.map +1 -1
- package/dist/navigation-instruments/rudder/rudder.d.ts +15 -2
- package/dist/navigation-instruments/rudder/rudder.d.ts.map +1 -1
- package/dist/navigation-instruments/rudder/rudder.js +36 -26
- package/dist/navigation-instruments/rudder/rudder.js.map +1 -1
- package/dist/navigation-instruments/speed-gauge/speed-gauge.d.ts +15 -1
- package/dist/navigation-instruments/speed-gauge/speed-gauge.d.ts.map +1 -1
- package/dist/navigation-instruments/speed-gauge/speed-gauge.js +31 -3
- package/dist/navigation-instruments/speed-gauge/speed-gauge.js.map +1 -1
- package/dist/navigation-instruments/watch/watch.d.ts +45 -17
- package/dist/navigation-instruments/watch/watch.d.ts.map +1 -1
- package/dist/navigation-instruments/watch/watch.js +53 -38
- package/dist/navigation-instruments/watch/watch.js.map +1 -1
- package/dist/svghelpers/radial-frame.d.ts +122 -0
- package/dist/svghelpers/radial-frame.d.ts.map +1 -0
- package/dist/svghelpers/radial-frame.js +259 -0
- package/dist/svghelpers/radial-frame.js.map +1 -0
- package/package.json +1 -1
- package/script/check-slot-event-docs.ts +35 -0
- package/src/bars-graphs/donut-chart/donut-chart.ts +18 -16
- package/src/bars-graphs/pie-chart/pie-chart.ts +14 -12
- package/src/bars-graphs/polar-chart/polar-chart.ts +19 -16
- package/src/bars-graphs/radial-bar-chart/radial-bar-chart.ts +8 -8
- package/src/building-blocks/chart-line/chart-line-base.ts +8 -25
- package/src/building-blocks/instrument-radial/instrument-radial.stories.ts +187 -6
- package/src/building-blocks/instrument-radial/instrument-radial.ts +98 -47
- package/src/integration-systems/integration-bar/integration-bar.ts +20 -24
- package/src/integration-systems/integration-button/integration-button.ts +15 -13
- package/src/navigation-instruments/azimuth-thruster/azimuth-thruster.stories.ts +78 -1
- package/src/navigation-instruments/azimuth-thruster/azimuth-thruster.ts +55 -11
- package/src/navigation-instruments/compass/compass.stories.ts +88 -1
- package/src/navigation-instruments/compass/compass.ts +99 -46
- package/src/navigation-instruments/compass-flat/compass-flat.ts +8 -9
- package/src/navigation-instruments/compass-sector/compass-sector.ts +7 -0
- package/src/navigation-instruments/gauge-radial/gauge-radial.css +32 -2
- package/src/navigation-instruments/gauge-radial/gauge-radial.stories.ts +265 -1
- package/src/navigation-instruments/gauge-radial/gauge-radial.ts +59 -1
- package/src/navigation-instruments/gauge-trend/gauge-trend.ts +0 -5
- package/src/navigation-instruments/graph-mini/graph-mini.ts +1 -1
- package/src/navigation-instruments/heading/heading.stories.ts +92 -1
- package/src/navigation-instruments/heading/heading.ts +50 -16
- package/src/navigation-instruments/indicator-graph/indicator-graph.ts +1 -1
- package/src/navigation-instruments/rudder/rudder.stories.ts +83 -1
- package/src/navigation-instruments/rudder/rudder.ts +61 -34
- package/src/navigation-instruments/speed-gauge/speed-gauge.stories.ts +94 -1
- package/src/navigation-instruments/speed-gauge/speed-gauge.ts +57 -4
- package/src/navigation-instruments/watch/watch.stories.ts +140 -1
- package/src/navigation-instruments/watch/watch.ts +100 -60
- package/src/storybook-util.ts +59 -0
- package/src/svghelpers/radial-frame.spec.ts +307 -0
- package/src/svghelpers/radial-frame.ts +508 -0
|
@@ -35,36 +35,38 @@ export enum IntegrationButtonType {
|
|
|
35
35
|
*
|
|
36
36
|
* @fires click - Fired when the internal button is activated.
|
|
37
37
|
*
|
|
38
|
-
* @property {boolean} hasTrailingIcon - Shows the `trailing-icon` slot.
|
|
39
|
-
* @property {boolean} hasTrailingIcon2 - Shows the `trailing-icon2` slot.
|
|
40
|
-
* @property {boolean} hasLeadingIcon - Shows the `leading-icon` slot.
|
|
41
|
-
* @property {boolean} hasstatus - Shows the `status` slot.
|
|
42
|
-
* @property {IntegrationButtonReadout[]} readouts - List of readout items shown in the rich type.
|
|
43
|
-
* @property {boolean} disabled - Disables the internal button.
|
|
44
|
-
* @property {boolean} activated - Applies active state styling while a selection is pending.
|
|
45
|
-
* @property {boolean} selected - Applies selected state styling.
|
|
46
|
-
* @property {boolean} dividerBottom - Shows a bottom divider under the button.
|
|
47
|
-
* @property {boolean} dividerRight - Shows a right divider to separate from adjacent buttons.
|
|
48
|
-
* @property {IntegrationButtonVariant} variant - Visual variant (`normal` or `flat`).
|
|
49
|
-
* @property {IntegrationButtonType} type - Layout type (`hug`, `regular`, or `rich`).
|
|
50
38
|
* @experimental
|
|
51
39
|
*/
|
|
52
40
|
@customElement('obc-integration-button')
|
|
53
41
|
export class ObcIntegrationButton extends LitElement {
|
|
42
|
+
/** Shows the `trailing-icon` slot. */
|
|
54
43
|
@property({type: Boolean}) hasTrailingIcon = false;
|
|
55
|
-
/**
|
|
44
|
+
/**
|
|
45
|
+
* Shows the `trailing-icon2` slot.
|
|
46
|
+
* @availableWhen hasTrailingIcon==true
|
|
47
|
+
*/
|
|
56
48
|
@property({type: Boolean}) hasTrailingIcon2 = false;
|
|
49
|
+
/** Shows the `leading-icon` slot. */
|
|
57
50
|
@property({type: Boolean}) hasLeadingIcon = false;
|
|
51
|
+
/** Shows the `status` slot. */
|
|
58
52
|
@property({type: Boolean}) hasStatus = false;
|
|
53
|
+
/** List of readout items shown in the rich type. */
|
|
59
54
|
@property({type: Array, attribute: false})
|
|
60
55
|
readouts: IntegrationButtonReadout[] = [];
|
|
56
|
+
/** Disables the internal button. */
|
|
61
57
|
@property({type: Boolean}) disabled = false;
|
|
58
|
+
/** Applies active state styling while a selection is pending. */
|
|
62
59
|
@property({type: Boolean}) activated = false;
|
|
60
|
+
/** Applies selected state styling. */
|
|
63
61
|
@property({type: Boolean}) selected = false;
|
|
62
|
+
/** Shows a bottom divider under the button. */
|
|
64
63
|
@property({type: Boolean}) dividerBottom = false;
|
|
64
|
+
/** Shows a right divider to separate from adjacent buttons. */
|
|
65
65
|
@property({type: Boolean}) dividerRight = false;
|
|
66
|
+
/** Visual variant (`normal` or `flat`). */
|
|
66
67
|
@property({type: String}) variant: IntegrationButtonVariant =
|
|
67
68
|
IntegrationButtonVariant.normal;
|
|
69
|
+
/** Layout type (`hug`, `regular`, or `rich`). */
|
|
68
70
|
@property({type: String}) type: IntegrationButtonType =
|
|
69
71
|
IntegrationButtonType.regular;
|
|
70
72
|
|
|
@@ -2,7 +2,13 @@ import type {Meta, StoryObj} from '@storybook/web-components-vite';
|
|
|
2
2
|
import {ObcAzimuthThruster} from './azimuth-thruster.js';
|
|
3
3
|
import './azimuth-thruster.js';
|
|
4
4
|
import {InstrumentState, Priority, Size} from '../types.js';
|
|
5
|
-
import {
|
|
5
|
+
import {html} from 'lit';
|
|
6
|
+
import {
|
|
7
|
+
playgroundColumn,
|
|
8
|
+
resizableStoryBox,
|
|
9
|
+
storyHint,
|
|
10
|
+
widthDecorator,
|
|
11
|
+
} from '../../storybook-util.js';
|
|
6
12
|
import {AdviceType} from '../watch/advice.js';
|
|
7
13
|
import {TickmarkStyle} from '../watch/tickmark.js';
|
|
8
14
|
import {PropellerType} from '../thruster/propeller.js';
|
|
@@ -12,6 +18,11 @@ const meta: Meta<typeof ObcAzimuthThruster> = {
|
|
|
12
18
|
tags: ['autodocs', '6.0'],
|
|
13
19
|
component: 'obc-azimuth-thruster',
|
|
14
20
|
argTypes: {
|
|
21
|
+
faceDiameter: {
|
|
22
|
+
control: {type: 'range', min: 100, max: 600, step: 10},
|
|
23
|
+
description:
|
|
24
|
+
'Pins the outer-ring diameter in px (fixed intrinsic size, equal circumference across instruments). Clear to return to fill-the-container sizing.',
|
|
25
|
+
},
|
|
15
26
|
thrust: {control: {type: 'range', min: -100, max: 100, step: 1}},
|
|
16
27
|
thrustSetpoint: {control: {type: 'range', min: -100, max: 100, step: 1}},
|
|
17
28
|
angle: {control: {type: 'range', min: -180, max: 180, step: 1}},
|
|
@@ -256,3 +267,69 @@ export const OffWithAngleSetpointOverride: Story = {
|
|
|
256
267
|
priority: Priority.enhanced,
|
|
257
268
|
},
|
|
258
269
|
};
|
|
270
|
+
|
|
271
|
+
type SizingPlaygroundArgs = Partial<ObcAzimuthThruster> & {
|
|
272
|
+
lockFaceDiameter?: boolean;
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Interactive sizing playground: drag the dashed box's bottom-right corner to
|
|
277
|
+
* resize it. The first thruster is pinned to a fixed intrinsic size by the
|
|
278
|
+
* `faceDiameter` control, while the second adapts to the remaining flex
|
|
279
|
+
* space, reserving room for its degree labels adaptively (issue #1021).
|
|
280
|
+
* Enable `lockFaceDiameter` to pin both to the same circumference. Related:
|
|
281
|
+
* *Sizing Playground* stories under Building Blocks/Watch, Building
|
|
282
|
+
* Blocks/Instrument Radial and Instruments/Gauge Radial.
|
|
283
|
+
*/
|
|
284
|
+
export const SizingPlayground: StoryObj<SizingPlaygroundArgs> = {
|
|
285
|
+
name: 'Sizing Playground — FaceDiameter + Resizable (Manual)',
|
|
286
|
+
tags: ['skip-test'],
|
|
287
|
+
parameters: {widthDecorator: false},
|
|
288
|
+
args: {
|
|
289
|
+
faceDiameter: 240,
|
|
290
|
+
lockFaceDiameter: false,
|
|
291
|
+
},
|
|
292
|
+
argTypes: {
|
|
293
|
+
lockFaceDiameter: {
|
|
294
|
+
control: 'boolean',
|
|
295
|
+
description:
|
|
296
|
+
'Apply faceDiameter to every instance (equal circumference) instead of only the first.',
|
|
297
|
+
},
|
|
298
|
+
},
|
|
299
|
+
render: (args) => {
|
|
300
|
+
const instances = [
|
|
301
|
+
{label: 'thruster A', angle: 45, thrust: 60},
|
|
302
|
+
{label: 'thruster B', angle: -120, thrust: 35},
|
|
303
|
+
];
|
|
304
|
+
const fd = (index: number) =>
|
|
305
|
+
index === 0 || args.lockFaceDiameter ? args.faceDiameter : undefined;
|
|
306
|
+
const caption = (index: number, label: string) =>
|
|
307
|
+
fd(index) !== undefined
|
|
308
|
+
? `${label} — pinned ${fd(index)}px`
|
|
309
|
+
: `${label} — adaptive (flex)`;
|
|
310
|
+
return html`
|
|
311
|
+
${storyHint(
|
|
312
|
+
'Drag the bottom-right corner of the dashed box to resize it. The first thruster is pinned by the faceDiameter control; the second adapts to the remaining flex space. Enable lockFaceDiameter to pin both to the same circumference.'
|
|
313
|
+
)}
|
|
314
|
+
${resizableStoryBox(
|
|
315
|
+
html`
|
|
316
|
+
${instances.map((g, index) =>
|
|
317
|
+
playgroundColumn(
|
|
318
|
+
caption(index, g.label),
|
|
319
|
+
html`
|
|
320
|
+
<obc-azimuth-thruster
|
|
321
|
+
.angle=${g.angle}
|
|
322
|
+
.thrust=${g.thrust}
|
|
323
|
+
.showLabels=${true}
|
|
324
|
+
.faceDiameter=${fd(index)}
|
|
325
|
+
></obc-azimuth-thruster>
|
|
326
|
+
`,
|
|
327
|
+
{pinned: fd(index) !== undefined}
|
|
328
|
+
)
|
|
329
|
+
)}
|
|
330
|
+
`,
|
|
331
|
+
{width: 680, height: 400}
|
|
332
|
+
)}
|
|
333
|
+
`;
|
|
334
|
+
},
|
|
335
|
+
};
|
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
import {html, LitElement, unsafeCSS} from 'lit';
|
|
2
2
|
import {property} from 'lit/decorators.js';
|
|
3
3
|
import type {PropertyValues} from 'lit';
|
|
4
|
+
import {ResizeController} from '@lit-labs/observers/resize-controller.js';
|
|
5
|
+
import {
|
|
6
|
+
applyPinnedHostSize,
|
|
7
|
+
computeRadialFrame,
|
|
8
|
+
estimateLabelWidthPx,
|
|
9
|
+
measureContainerPx,
|
|
10
|
+
observeInnerBox,
|
|
11
|
+
type RadialFrame,
|
|
12
|
+
} from '../../svghelpers/radial-frame.js';
|
|
4
13
|
import {InstrumentState, Priority} from '../types.js';
|
|
5
14
|
import {SetpointBundle} from '../../svghelpers/setpoint-bundle.js';
|
|
6
15
|
import {thruster} from '../thruster/thruster.js';
|
|
7
16
|
import '../watch/watch.js';
|
|
8
17
|
import componentStyle from './azimuth-thruster.css?inline';
|
|
9
|
-
import {ifDefined} from 'lit/directives/if-defined.js';
|
|
10
18
|
import {AdviceState, AngleAdvice, AngleAdviceRaw} from '../watch/advice.js';
|
|
11
19
|
import {Tickmark, TickmarkStyle, TickmarkType} from '../watch/tickmark.js';
|
|
12
20
|
import {LinearAdvice} from '../thruster/advice.js';
|
|
@@ -134,6 +142,36 @@ export class ObcAzimuthThruster extends LitElement {
|
|
|
134
142
|
@property({type: String}) tickmarkStyle: TickmarkStyle =
|
|
135
143
|
TickmarkStyle.regular;
|
|
136
144
|
@property({type: Boolean}) starboardPortIndicator: boolean = false;
|
|
145
|
+
/**
|
|
146
|
+
* Outer-ring diameter in CSS pixels. When set, the instrument renders at a
|
|
147
|
+
* fixed intrinsic size derived from the ring, arc shape and label reserve —
|
|
148
|
+
* so instruments sharing the same value have identical ring circumference
|
|
149
|
+
* regardless of label width or arc extent (like obc-donut-chart's
|
|
150
|
+
* fixedHeight). When unset (default), the instrument fills its container.
|
|
151
|
+
*/
|
|
152
|
+
@property({type: Number, attribute: 'face-diameter'})
|
|
153
|
+
faceDiameter: number | undefined;
|
|
154
|
+
|
|
155
|
+
private _frame: RadialFrame | undefined;
|
|
156
|
+
|
|
157
|
+
/** Whether the host size styles were set by applyPinnedHostSize. */
|
|
158
|
+
private _hostSizePinned = false;
|
|
159
|
+
|
|
160
|
+
private _resizeController = new ResizeController(this, {});
|
|
161
|
+
|
|
162
|
+
override firstUpdated(changed: PropertyValues): void {
|
|
163
|
+
super.firstUpdated(changed);
|
|
164
|
+
observeInnerBox(this._resizeController, this.renderRoot);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
override updated(changed: PropertyValues): void {
|
|
168
|
+
super.updated(changed);
|
|
169
|
+
this._hostSizePinned = applyPinnedHostSize(
|
|
170
|
+
this,
|
|
171
|
+
this._frame,
|
|
172
|
+
this._hostSizePinned
|
|
173
|
+
);
|
|
174
|
+
}
|
|
137
175
|
|
|
138
176
|
private get angleAdviceRaw(): AngleAdviceRaw[] {
|
|
139
177
|
return this.angleAdvices.map((advice) => {
|
|
@@ -236,20 +274,27 @@ export class ObcAzimuthThruster extends LitElement {
|
|
|
236
274
|
|
|
237
275
|
const tickmarks = this.getTickmarks();
|
|
238
276
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
277
|
+
const frame = computeRadialFrame({
|
|
278
|
+
basePadding: this.hasLabelSpacer ? 24 : 16,
|
|
279
|
+
labelWidthPx:
|
|
280
|
+
this.hasLabelSpacer && !this.tickmarksInside
|
|
281
|
+
? estimateLabelWidthPx(tickmarks.map((t) => t.text))
|
|
282
|
+
: 0,
|
|
283
|
+
containerPx: measureContainerPx(this),
|
|
284
|
+
faceDiameter: this.faceDiameter,
|
|
285
|
+
});
|
|
286
|
+
this._frame = frame;
|
|
287
|
+
const shownTickmarks = frame.labelsHidden
|
|
288
|
+
? tickmarks.map((t) => ({...t, text: undefined}))
|
|
289
|
+
: tickmarks;
|
|
290
|
+
const viewBox = frame.viewBox;
|
|
247
291
|
|
|
248
292
|
return html`
|
|
249
293
|
<div class="container">
|
|
250
294
|
<obc-watch
|
|
251
295
|
.touching=${this.touching}
|
|
252
|
-
.
|
|
296
|
+
.arcFrame=${frame}
|
|
297
|
+
.tickmarks=${shownTickmarks}
|
|
253
298
|
.state=${this.state}
|
|
254
299
|
.priority=${this.priority}
|
|
255
300
|
.angleSetpoint=${this.angleSetpoint}
|
|
@@ -260,7 +305,6 @@ export class ObcAzimuthThruster extends LitElement {
|
|
|
260
305
|
.animateSetpoint=${this.animateSetpoint}
|
|
261
306
|
.tickmarksInside=${this.tickmarksInside}
|
|
262
307
|
.tickmarkStyle=${this.tickmarkStyle}
|
|
263
|
-
padding=${ifDefined(!this.hasLabelSpacer ? 16 : undefined)}
|
|
264
308
|
.advices=${this.angleAdviceRaw}
|
|
265
309
|
.starboardPortIndicator=${this.starboardPortIndicator}
|
|
266
310
|
></obc-watch>
|
|
@@ -6,7 +6,13 @@ import {
|
|
|
6
6
|
RotType,
|
|
7
7
|
} from './compass.js';
|
|
8
8
|
import './compass.js';
|
|
9
|
-
import {
|
|
9
|
+
import {html} from 'lit';
|
|
10
|
+
import {
|
|
11
|
+
playgroundColumn,
|
|
12
|
+
resizableStoryBox,
|
|
13
|
+
storyHint,
|
|
14
|
+
widthDecorator,
|
|
15
|
+
} from '../../storybook-util.js';
|
|
10
16
|
import {AdviceType} from '../watch/advice.js';
|
|
11
17
|
import {VesselImage} from '../watch/watch.js';
|
|
12
18
|
import {topVessels} from '../watch/vessels/storybook-helper.js';
|
|
@@ -48,6 +54,11 @@ const meta: Meta<typeof ObcCompass> = {
|
|
|
48
54
|
},
|
|
49
55
|
argTypes: {
|
|
50
56
|
width: {control: {type: 'range', min: 32, max: 1028, step: 1}},
|
|
57
|
+
faceDiameter: {
|
|
58
|
+
control: {type: 'range', min: 100, max: 600, step: 10},
|
|
59
|
+
description:
|
|
60
|
+
'Pins the outer-ring diameter in px (fixed intrinsic size, equal circumference across instruments). Clear to return to fill-the-container sizing.',
|
|
61
|
+
},
|
|
51
62
|
heading: {control: {type: 'range', min: 0, max: 360, step: 1}},
|
|
52
63
|
courseOverGround: {control: {type: 'range', min: 0, max: 360, step: 1}},
|
|
53
64
|
headingSetpoint: {control: {type: 'range', min: 0, max: 360, step: 1}},
|
|
@@ -171,3 +182,79 @@ export const WithRateOfTurnDegreesPerMinute: Story = {
|
|
|
171
182
|
priorityElements: [CompassPriorityElement.hdg, CompassPriorityElement.rot],
|
|
172
183
|
},
|
|
173
184
|
};
|
|
185
|
+
|
|
186
|
+
export const SmallContainer: Story = {
|
|
187
|
+
name: 'Small Container (250px, Labels + Decor Reserve)',
|
|
188
|
+
args: {
|
|
189
|
+
width: 250,
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
type SizingPlaygroundArgs = Partial<ObcCompass> & {
|
|
194
|
+
lockFaceDiameter?: boolean;
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Interactive sizing playground: drag the dashed box's bottom-right corner to
|
|
199
|
+
* resize it. The first compass is pinned to a fixed intrinsic size by the
|
|
200
|
+
* `faceDiameter` control, while the second adapts to the remaining flex
|
|
201
|
+
* space, reserving room for the NSWE labels, north arrow and wind symbols
|
|
202
|
+
* adaptively (issue #1021). Enable `lockFaceDiameter` to pin both to the same
|
|
203
|
+
* circumference. Related: *Sizing Playground* stories under Building
|
|
204
|
+
* Blocks/Watch, Building Blocks/Instrument Radial and Instruments/Gauge
|
|
205
|
+
* Radial.
|
|
206
|
+
*/
|
|
207
|
+
export const SizingPlayground: StoryObj<SizingPlaygroundArgs> = {
|
|
208
|
+
name: 'Sizing Playground — FaceDiameter + Resizable (Manual)',
|
|
209
|
+
tags: ['skip-test'],
|
|
210
|
+
parameters: {widthDecorator: false},
|
|
211
|
+
args: {
|
|
212
|
+
faceDiameter: 240,
|
|
213
|
+
lockFaceDiameter: false,
|
|
214
|
+
},
|
|
215
|
+
argTypes: {
|
|
216
|
+
lockFaceDiameter: {
|
|
217
|
+
control: 'boolean',
|
|
218
|
+
description:
|
|
219
|
+
'Apply faceDiameter to every instance (equal circumference) instead of only the first.',
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
render: (args) => {
|
|
223
|
+
const instances = [
|
|
224
|
+
{label: 'compass A', heading: 311},
|
|
225
|
+
{label: 'compass B', heading: 45},
|
|
226
|
+
];
|
|
227
|
+
const fd = (index: number) =>
|
|
228
|
+
index === 0 || args.lockFaceDiameter ? args.faceDiameter : undefined;
|
|
229
|
+
const caption = (index: number, label: string) =>
|
|
230
|
+
fd(index) !== undefined
|
|
231
|
+
? `${label} — pinned ${fd(index)}px`
|
|
232
|
+
: `${label} — adaptive (flex)`;
|
|
233
|
+
return html`
|
|
234
|
+
${storyHint(
|
|
235
|
+
'Drag the bottom-right corner of the dashed box to resize it. The first compass is pinned by the faceDiameter control; the second adapts to the remaining flex space. Enable lockFaceDiameter to pin both to the same circumference.'
|
|
236
|
+
)}
|
|
237
|
+
${resizableStoryBox(
|
|
238
|
+
html`
|
|
239
|
+
${instances.map((g, index) =>
|
|
240
|
+
playgroundColumn(
|
|
241
|
+
caption(index, g.label),
|
|
242
|
+
html`
|
|
243
|
+
<obc-compass
|
|
244
|
+
.heading=${g.heading}
|
|
245
|
+
.courseOverGround=${g.heading + 27}
|
|
246
|
+
.currentWindSpeedKnots=${20}
|
|
247
|
+
.windFromDirection=${45}
|
|
248
|
+
.showLabels=${true}
|
|
249
|
+
.faceDiameter=${fd(index)}
|
|
250
|
+
></obc-compass>
|
|
251
|
+
`,
|
|
252
|
+
{pinned: fd(index) !== undefined}
|
|
253
|
+
)
|
|
254
|
+
)}
|
|
255
|
+
`,
|
|
256
|
+
{width: 680, height: 400}
|
|
257
|
+
)}
|
|
258
|
+
`;
|
|
259
|
+
},
|
|
260
|
+
};
|
|
@@ -5,6 +5,14 @@ import {Tickmark, TickmarkType} from '../watch/tickmark.js';
|
|
|
5
5
|
import {arrow, ArrowStyle} from './arrow.js';
|
|
6
6
|
import {AdviceState, AngleAdvice, AngleAdviceRaw} from '../watch/advice.js';
|
|
7
7
|
import {ResizeController} from '@lit-labs/observers/resize-controller.js';
|
|
8
|
+
import {
|
|
9
|
+
applyPinnedHostSize,
|
|
10
|
+
computeRadialFrame,
|
|
11
|
+
measureContainerPx,
|
|
12
|
+
NORTH_ARROW_WIDTH_PX,
|
|
13
|
+
NSWE_LABEL_WIDTH_PX,
|
|
14
|
+
type RadialFrame,
|
|
15
|
+
} from '../../svghelpers/radial-frame.js';
|
|
8
16
|
import {
|
|
9
17
|
VesselImage,
|
|
10
18
|
VesselImageSize,
|
|
@@ -59,9 +67,9 @@ export enum CompassPriorityElement {
|
|
|
59
67
|
* Supports spinning dots (`rotType="dots"`) — the dot animation is
|
|
60
68
|
* amplified by `rotDotAnimationFactor` so small physical values still
|
|
61
69
|
* read at a glance — and a banana-shaped arc bar (`rotType="bar"`)
|
|
62
|
-
* showing the
|
|
63
|
-
*
|
|
64
|
-
* circle via `rotPosition`.
|
|
70
|
+
* showing the rate of turn as an arc anchored at the current heading.
|
|
71
|
+
* Bar extent is driven by the physical value only (gain is not applied).
|
|
72
|
+
* Position on the outer scale ring or inner circle via `rotPosition`.
|
|
65
73
|
* - **Environmental overlays**: Wind speed/direction and current
|
|
66
74
|
* speed/direction indicators on the watch face.
|
|
67
75
|
* - **Vessel image**: Configurable vessel silhouette centered on the
|
|
@@ -94,25 +102,6 @@ export enum CompassPriorityElement {
|
|
|
94
102
|
* ></obc-compass>
|
|
95
103
|
* ```
|
|
96
104
|
*
|
|
97
|
-
* @property {number} heading - The current heading of the vessel in degrees.
|
|
98
|
-
* @property {number} courseOverGround - The current course over ground in degrees.
|
|
99
|
-
* @property {number | null} headingSetpoint - The set point for the heading in degrees.
|
|
100
|
-
* @property {boolean} atHeadingSetpoint - Indicates if the vessel is at the heading set point.
|
|
101
|
-
* @property {boolean} autoAtHeadingSetpoint - Enables automatic at heading set point calculation.
|
|
102
|
-
* @property {number} autoAtHeadingSetpointDeadband - The deadband for the heading set point in degrees.
|
|
103
|
-
* @property {boolean} touching - Indicates if the compass is being touched.
|
|
104
|
-
* @property {Array<AngleAdvice>} headingAdvices - An array of angle advices for the compass.
|
|
105
|
-
* @property {number | null} currentWindSpeedKnots - The wind speed in knots.
|
|
106
|
-
* @property {number | null} windFromDirection - The direction the wind is coming from in degrees.
|
|
107
|
-
* @property {number | null} currentSpeed - The current speed, number of arrows.
|
|
108
|
-
* @property {number | null} currentFromDirection - The direction the current is coming from in degrees.
|
|
109
|
-
* @property {VesselImage} vesselImage - The image of the vessel.
|
|
110
|
-
* @property {number|undefined} rateOfTurnDegreesPerMinute - Measured rate of turn in degrees per minute (the AIS / ITU-R M.1371 convention). Sign controls direction (positive = starboard / clockwise). Drives both the bar extent and the dot animation.
|
|
111
|
-
* @property {number} rotDotAnimationFactor - Visual amplification for the dot animation only. Default `18` (≈1 rpm at 20°/min).
|
|
112
|
-
* @property {number} rotationsPerMinute - **Deprecated.** Use `rateOfTurnDegreesPerMinute` instead. Kept as a backward-compatible fallback when `rateOfTurnDegreesPerMinute` is `undefined`.
|
|
113
|
-
* @property {RotType} rotType - ROT display mode: `'dots'` (spinning dots, default) or `'bar'` (arc bar from HDG to COG).
|
|
114
|
-
* @property {RotPosition} rotPosition - ROT track position: `'innerCircle'` (default) or `'scale'` (on the outer ring).
|
|
115
|
-
* @property {Priority} priority - Color priority: `Priority.enhanced` uses the blue/enhanced color palette, `Priority.regular` (default) uses the standard palette.
|
|
116
105
|
*
|
|
117
106
|
* @ignition-base-height: 512px
|
|
118
107
|
* @ignition-base-width: 512px
|
|
@@ -120,36 +109,65 @@ export enum CompassPriorityElement {
|
|
|
120
109
|
*/
|
|
121
110
|
@customElement('obc-compass')
|
|
122
111
|
export class ObcCompass extends LitElement {
|
|
112
|
+
/** The current heading of the vessel in degrees. */
|
|
123
113
|
@property({type: Number}) heading = 0;
|
|
114
|
+
/** The current course over ground in degrees. */
|
|
124
115
|
@property({type: Number}) courseOverGround = 0;
|
|
125
116
|
|
|
117
|
+
/** The set point for the heading in degrees. */
|
|
126
118
|
@property({type: Number}) headingSetpoint: number | null = null;
|
|
127
119
|
/** @availableWhen headingSetpoint!=null */
|
|
128
120
|
@property({type: Number}) newHeadingSetpoint: number | undefined;
|
|
129
|
-
/**
|
|
121
|
+
/**
|
|
122
|
+
* Indicates if the vessel is at the heading set point.
|
|
123
|
+
* @availableWhen headingSetpoint!=null && autoAtHeadingSetpoint==false
|
|
124
|
+
*/
|
|
130
125
|
@property({type: Boolean}) atHeadingSetpoint: boolean = false;
|
|
131
126
|
/** @availableWhen headingSetpoint!=null */
|
|
132
127
|
@property({type: Number}) headingSetpointAtZeroDeadband: number = 0.5;
|
|
133
128
|
/** @availableWhen headingSetpoint!=null */
|
|
134
129
|
@property({type: Boolean}) headingSetpointOverride: boolean = false;
|
|
135
|
-
/**
|
|
130
|
+
/**
|
|
131
|
+
* Enables automatic at heading set point calculation.
|
|
132
|
+
* @availableWhen headingSetpoint!=null
|
|
133
|
+
*/
|
|
136
134
|
@property({type: Boolean, attribute: false}) autoAtHeadingSetpoint: boolean =
|
|
137
135
|
true;
|
|
138
|
-
/**
|
|
136
|
+
/**
|
|
137
|
+
* The deadband for the heading set point in degrees.
|
|
138
|
+
* @availableWhen headingSetpoint!=null && autoAtHeadingSetpoint==true
|
|
139
|
+
*/
|
|
139
140
|
@property({type: Number}) autoAtHeadingSetpointDeadband: number = 2;
|
|
140
141
|
/** @availableWhen headingSetpoint!=null */
|
|
141
142
|
@property({type: Boolean}) animateSetpoint: boolean = false;
|
|
142
|
-
/**
|
|
143
|
+
/**
|
|
144
|
+
* Indicates if the compass is being touched.
|
|
145
|
+
* @availableWhen headingSetpoint!=null
|
|
146
|
+
*/
|
|
143
147
|
@property({type: Boolean}) touching: boolean = false;
|
|
148
|
+
/** An array of angle advices for the compass. */
|
|
144
149
|
@property({type: Array, attribute: false}) headingAdvices: AngleAdvice[] = [];
|
|
145
|
-
/**
|
|
150
|
+
/**
|
|
151
|
+
* The wind speed in knots.
|
|
152
|
+
* @availableWhen windFromDirection!=null
|
|
153
|
+
*/
|
|
146
154
|
@property({type: Number}) currentWindSpeedKnots: number | null = null;
|
|
147
|
-
/**
|
|
155
|
+
/**
|
|
156
|
+
* The direction the wind is coming from in degrees.
|
|
157
|
+
* @availableWhen currentWindSpeedKnots!=null
|
|
158
|
+
*/
|
|
148
159
|
@property({type: Number}) windFromDirection: number | null = null;
|
|
149
|
-
/**
|
|
160
|
+
/**
|
|
161
|
+
* The current speed, number of arrows.
|
|
162
|
+
* @availableWhen currentFromDirection!=null
|
|
163
|
+
*/
|
|
150
164
|
@property({type: Number}) currentSpeed: number | null = null;
|
|
151
|
-
/**
|
|
165
|
+
/**
|
|
166
|
+
* The direction the current is coming from in degrees.
|
|
167
|
+
* @availableWhen currentSpeed!=null
|
|
168
|
+
*/
|
|
152
169
|
@property({type: Number}) currentFromDirection: number | null = null;
|
|
170
|
+
/** The image of the vessel. */
|
|
153
171
|
@property({type: String}) vesselImage: VesselImage = VesselImage.genericTop;
|
|
154
172
|
/**
|
|
155
173
|
* Measured rate of turn in degrees per minute (positive = starboard).
|
|
@@ -166,12 +184,18 @@ export class ObcCompass extends LitElement {
|
|
|
166
184
|
*/
|
|
167
185
|
@property({type: Number}) rotDotAnimationFactor: number = 18;
|
|
168
186
|
/**
|
|
187
|
+
* Legacy rate-of-turn input, in rotations per minute. When
|
|
188
|
+
* `rateOfTurnDegreesPerMinute` is `undefined`, this value is used
|
|
189
|
+
* (unconverted) as the fallback ROT, driving both the spinning dot ring
|
|
190
|
+
* and the bar extent.
|
|
169
191
|
* @deprecated Use `rateOfTurnDegreesPerMinute` (and optionally
|
|
170
192
|
* `rotDotAnimationFactor`) instead. Takes effect only when
|
|
171
193
|
* `rateOfTurnDegreesPerMinute` is `undefined`.
|
|
172
194
|
*/
|
|
173
195
|
@property({type: Number}) rotationsPerMinute: number = 1;
|
|
196
|
+
/** ROT display mode: `'dots'` (spinning dots, default) or `'bar'` (a rate-of-turn arc anchored at the current heading, its length proportional to the rate of turn). */
|
|
174
197
|
@property({type: String}) rotType: RotType = RotType.dots;
|
|
198
|
+
/** ROT track position: `'innerCircle'` (default) or `'scale'` (on the outer ring). */
|
|
175
199
|
@property({type: String}) rotPosition: RotPosition = RotPosition.innerCircle;
|
|
176
200
|
/**
|
|
177
201
|
* Bar-extent reference value in **degrees per minute**. The bar fills the
|
|
@@ -192,6 +216,7 @@ export class ObcCompass extends LitElement {
|
|
|
192
216
|
@property({type: String}) direction: CompassDirection =
|
|
193
217
|
CompassDirection.NorthUp;
|
|
194
218
|
@property({type: String}) state: InstrumentState = InstrumentState.active;
|
|
219
|
+
/** Color priority: `Priority.enhanced` uses the blue/enhanced color palette, `Priority.regular` (default) uses the standard palette. */
|
|
195
220
|
@property({type: String}) priority: Priority = Priority.regular;
|
|
196
221
|
/** @availableWhen priority==enhanced */
|
|
197
222
|
@property({type: Array, attribute: false})
|
|
@@ -200,6 +225,15 @@ export class ObcCompass extends LitElement {
|
|
|
200
225
|
@property({type: Boolean}) showLabels: boolean = false;
|
|
201
226
|
/** When true, labels and north arrow are placed inside the outer ring. */
|
|
202
227
|
@property({type: Boolean}) tickmarksInside: boolean = false;
|
|
228
|
+
/**
|
|
229
|
+
* Outer-ring diameter in CSS pixels. When set, the instrument renders at a
|
|
230
|
+
* fixed intrinsic size derived from the ring, arc shape and label reserve —
|
|
231
|
+
* so instruments sharing the same value have identical ring circumference
|
|
232
|
+
* regardless of label width or arc extent (like obc-donut-chart's
|
|
233
|
+
* fixedHeight). When unset (default), the instrument fills its container.
|
|
234
|
+
*/
|
|
235
|
+
@property({type: Number, attribute: 'face-diameter'})
|
|
236
|
+
faceDiameter: number | undefined;
|
|
203
237
|
|
|
204
238
|
private _headingSp = new SetpointBundle({
|
|
205
239
|
angularWraparound: true,
|
|
@@ -240,18 +274,32 @@ export class ObcCompass extends LitElement {
|
|
|
240
274
|
return this.rateOfTurnDegreesPerMinute ?? this.rotationsPerMinute;
|
|
241
275
|
}
|
|
242
276
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
277
|
+
/**
|
|
278
|
+
* Pixel cost of the outside decor: the always-rendered north-arrow glyph
|
|
279
|
+
* plus, only while shown, the NSWE labels (both keep a constant on-screen
|
|
280
|
+
* size via `1/scale` terms). Feeds the frame's width-aware reserve,
|
|
281
|
+
* replacing the former empirical `72 + delta(clientSize)` padding.
|
|
282
|
+
* Wind/current symbols at their default radius are covered by the base
|
|
283
|
+
* padding of 72.
|
|
284
|
+
*/
|
|
285
|
+
private getOutsideDecorPx(): number {
|
|
286
|
+
if (this.tickmarksInside) {
|
|
287
|
+
return 0;
|
|
252
288
|
}
|
|
289
|
+
return NORTH_ARROW_WIDTH_PX + (this.showLabels ? NSWE_LABEL_WIDTH_PX : 0);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/** Whether the host size styles were set by applyPinnedHostSize. */
|
|
293
|
+
private _hostSizePinned = false;
|
|
294
|
+
private _frame: RadialFrame | undefined;
|
|
253
295
|
|
|
254
|
-
|
|
296
|
+
override updated(changed: PropertyValues): void {
|
|
297
|
+
super.updated(changed);
|
|
298
|
+
this._hostSizePinned = applyPinnedHostSize(
|
|
299
|
+
this,
|
|
300
|
+
this._frame,
|
|
301
|
+
this._hostSizePinned
|
|
302
|
+
);
|
|
255
303
|
}
|
|
256
304
|
|
|
257
305
|
private get angleAdviceRaw(): AngleAdviceRaw[] {
|
|
@@ -298,23 +346,28 @@ export class ObcCompass extends LitElement {
|
|
|
298
346
|
{angle: 270, type: TickmarkType.main},
|
|
299
347
|
];
|
|
300
348
|
|
|
301
|
-
const
|
|
302
|
-
|
|
303
|
-
|
|
349
|
+
const frame = computeRadialFrame({
|
|
350
|
+
basePadding: 72,
|
|
351
|
+
labelWidthPx: this.getOutsideDecorPx(),
|
|
352
|
+
containerPx: measureContainerPx(this),
|
|
353
|
+
faceDiameter: this.faceDiameter,
|
|
354
|
+
});
|
|
355
|
+
this._frame = frame;
|
|
356
|
+
const viewBox = frame.viewBox;
|
|
304
357
|
|
|
305
358
|
return html`
|
|
306
359
|
<div class="container">
|
|
307
360
|
<obc-watch
|
|
308
361
|
.touching=${this.touching}
|
|
309
|
-
.
|
|
362
|
+
.arcFrame=${frame}
|
|
310
363
|
.advices=${this.angleAdviceRaw}
|
|
311
364
|
.tickmarks=${tickmarks}
|
|
312
365
|
.state=${this.state}
|
|
313
366
|
.watchCircleType=${WatchCircleType.triple}
|
|
314
|
-
.showLabels=${this.showLabels}
|
|
367
|
+
.showLabels=${this.showLabels && !frame.labelsHidden}
|
|
315
368
|
.tickmarksInside=${this.tickmarksInside}
|
|
316
369
|
.crosshairEnabled=${true}
|
|
317
|
-
.northArrow=${
|
|
370
|
+
.northArrow=${!frame.labelsHidden}
|
|
318
371
|
.angleSetpoint=${this.headingSetpoint ?? undefined}
|
|
319
372
|
.newAngleSetpoint=${this.newHeadingSetpoint}
|
|
320
373
|
.atAngleSetpoint=${this._headingSp.computeAtSetpoint(this.heading)}
|
|
@@ -58,14 +58,6 @@ export interface Label {
|
|
|
58
58
|
* - **Color priority**: Per-element priority for HDG, COG, and ROT via
|
|
59
59
|
* `priorityElements`.
|
|
60
60
|
*
|
|
61
|
-
* @property {number} heading - Current heading in degrees.
|
|
62
|
-
* @property {number} courseOverGround - Current COG in degrees.
|
|
63
|
-
* @property {RotType|undefined} rotType - ROT display mode: `'dots'`, `'bar'`, or `undefined` (hidden).
|
|
64
|
-
* @property {number|undefined} rateOfTurnDegreesPerMinute - Measured rate of turn in degrees per minute (positive = starboard). Drives the bar extent and (after `× rotDotAnimationFactor`) the dot animation.
|
|
65
|
-
* @property {number} rotDotAnimationFactor - Visual amplification for the dot animation only. Default `18` (≈1 rpm at 20°/min).
|
|
66
|
-
* @property {number} rotationsPerMinute - **Deprecated.** Use `rateOfTurnDegreesPerMinute` instead.
|
|
67
|
-
* @property {number} rotMaxValue - Bar-extent reference value in **degrees per minute**. Default `60` per ES-TRIN 2025/1 Art. 3.02.
|
|
68
|
-
* @property {number} rotArcExtent - Degrees of bar arc per max-value ROT (default 60).
|
|
69
61
|
*
|
|
70
62
|
* @ignition-base-height: 170px
|
|
71
63
|
* @ignition-base-width: 512px
|
|
@@ -74,7 +66,9 @@ export interface Label {
|
|
|
74
66
|
@customElement('obc-compass-flat')
|
|
75
67
|
export class ObcCompassFlat extends LitElement {
|
|
76
68
|
@property({type: Boolean}) FOVIndicator: boolean = false;
|
|
69
|
+
/** Current heading in degrees. */
|
|
77
70
|
@property({type: Number}) heading = 0;
|
|
71
|
+
/** Current COG in degrees. */
|
|
78
72
|
@property({type: Number}) courseOverGround = 0;
|
|
79
73
|
@property({type: Number}) tickInterval = 5;
|
|
80
74
|
@property({type: Number}) FOV = 45;
|
|
@@ -85,6 +79,7 @@ export class ObcCompassFlat extends LitElement {
|
|
|
85
79
|
priorityElements: CompassFlatPriorityElement[] = [
|
|
86
80
|
CompassFlatPriorityElement.hdg,
|
|
87
81
|
];
|
|
82
|
+
/** ROT display mode: `'dots'`, `'bar'`, or `undefined` (hidden). */
|
|
88
83
|
@property({type: String}) rotType: RotType | undefined;
|
|
89
84
|
/**
|
|
90
85
|
* Measured rate of turn in degrees per minute (positive = starboard).
|
|
@@ -98,6 +93,7 @@ export class ObcCompassFlat extends LitElement {
|
|
|
98
93
|
*/
|
|
99
94
|
@property({type: Number}) rotDotAnimationFactor: number = 18;
|
|
100
95
|
/**
|
|
96
|
+
* **Deprecated.** Use `rateOfTurnDegreesPerMinute` instead.
|
|
101
97
|
* @deprecated Use `rateOfTurnDegreesPerMinute` instead.
|
|
102
98
|
* @availableWhen rotType!=undefined
|
|
103
99
|
*/
|
|
@@ -108,7 +104,10 @@ export class ObcCompassFlat extends LitElement {
|
|
|
108
104
|
* @availableWhen rotType!=undefined
|
|
109
105
|
*/
|
|
110
106
|
@property({type: Number}) rotMaxValue: number = 60;
|
|
111
|
-
/**
|
|
107
|
+
/**
|
|
108
|
+
* Degrees of bar arc per max-value ROT (default 60).
|
|
109
|
+
* @availableWhen rotType!=undefined
|
|
110
|
+
*/
|
|
112
111
|
@property({type: Number}) rotArcExtent: number = 60;
|
|
113
112
|
/** @availableWhen rotType!=undefined */
|
|
114
113
|
@property({type: Boolean}) rotPortStarboard: boolean = false;
|
|
@@ -31,6 +31,13 @@ export enum CompassSectorPriorityElement {
|
|
|
31
31
|
rot = 'rot',
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
// Fixed frame padding for both the zoomed and un-zoomed paths. This component
|
|
35
|
+
// deliberately keeps its bespoke FOV-compression geometry and does NOT use
|
|
36
|
+
// svghelpers/radial-frame.ts: the viewBox is cached per FOV (a
|
|
37
|
+
// container-size-dependent label reserve would invalidate that), and the
|
|
38
|
+
// 72-unit padding covers the 3-char degree labels at typical sizes.
|
|
39
|
+
// TODO(#1021): adopt computeRadialFrame if degree labels ever clip when the
|
|
40
|
+
// component is shrunk far below its design size.
|
|
34
41
|
const PADDING = 72;
|
|
35
42
|
const WATCH_TYPE = WatchCircleType.triple;
|
|
36
43
|
const INNER_RADIUS = innerRingRadiusFor(WATCH_TYPE);
|