@oicl/openbridge-webcomponents-full-bundle 2.0.0-next.45 → 2.0.0-next.49
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/.storybook/ComponentPreview.tsx +26 -0
- package/.storybook/PreviewTemplate.tsx +99 -0
- package/.storybook/action-handler.ts +81 -0
- package/.storybook/channels.ts +44 -0
- package/.storybook/main.ts +313 -0
- package/.storybook/manager.ts +71 -0
- package/.storybook/openbridgeTheme.ts +197 -0
- package/.storybook/preview-head.html +15 -0
- package/.storybook/preview.tsx +129 -0
- package/.storybook/vitest.setup.ts +23 -0
- package/bundle/openbridge-webcomponents.bundle.js +14869 -14889
- package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
- package/custom-elements.json +81 -82
- package/dist/components/badge/badge.css.js +15 -15
- package/dist/components/icon-button/icon-button.d.ts +4 -0
- package/dist/components/icon-button/icon-button.d.ts.map +1 -1
- package/dist/components/icon-button/icon-button.js.map +1 -1
- package/dist/navigation-instruments/compass/compass.d.ts +3 -3
- package/dist/navigation-instruments/compass/compass.d.ts.map +1 -1
- package/dist/navigation-instruments/compass/compass.js +3 -3
- package/dist/navigation-instruments/compass/compass.js.map +1 -1
- package/dist/navigation-instruments/compass-indicator/compass-indicator.d.ts +12 -0
- package/dist/navigation-instruments/compass-indicator/compass-indicator.d.ts.map +1 -1
- package/dist/navigation-instruments/compass-indicator/compass-indicator.js +9 -1
- package/dist/navigation-instruments/compass-indicator/compass-indicator.js.map +1 -1
- package/dist/navigation-instruments/velocity-projection-plot/velocity-projection-plot.d.ts +4 -4
- package/dist/navigation-instruments/velocity-projection-plot/velocity-projection-plot.d.ts.map +1 -1
- package/dist/navigation-instruments/velocity-projection-plot/velocity-projection-plot.js +15 -14
- package/dist/navigation-instruments/velocity-projection-plot/velocity-projection-plot.js.map +1 -1
- package/dist/navigation-instruments/watch/environment.d.ts +39 -1
- package/dist/navigation-instruments/watch/environment.d.ts.map +1 -1
- package/dist/navigation-instruments/watch/environment.js +71 -88
- package/dist/navigation-instruments/watch/environment.js.map +1 -1
- package/dist/navigation-instruments/watch/watch.d.ts +1 -1
- package/dist/navigation-instruments/watch/watch.d.ts.map +1 -1
- package/dist/navigation-instruments/watch/watch.js +4 -4
- package/dist/navigation-instruments/watch/watch.js.map +1 -1
- package/dist/navigation-instruments/wind/wind.d.ts +1 -1
- package/dist/navigation-instruments/wind/wind.d.ts.map +1 -1
- package/dist/navigation-instruments/wind/wind.js +3 -3
- package/dist/navigation-instruments/wind/wind.js.map +1 -1
- package/dist/navigation-instruments/wind-indicator/wind-indicator.d.ts +63 -9
- package/dist/navigation-instruments/wind-indicator/wind-indicator.d.ts.map +1 -1
- package/dist/navigation-instruments/wind-indicator/wind-indicator.js +57 -1995
- package/dist/navigation-instruments/wind-indicator/wind-indicator.js.map +1 -1
- package/dist/navigation-instruments/wind-propulsion/wind-propulsion.d.ts +1 -1
- package/dist/navigation-instruments/wind-propulsion/wind-propulsion.d.ts.map +1 -1
- package/dist/navigation-instruments/wind-propulsion/wind-propulsion.js +4 -4
- package/dist/navigation-instruments/wind-propulsion/wind-propulsion.js.map +1 -1
- package/eslint.config.mjs +589 -0
- package/fix-imports.mjs +185 -0
- package/fix-js-extensions.mjs +44 -0
- package/lit-localize.json +15 -0
- package/new-component.ts +148 -0
- package/package.json +56 -3
- package/postcss.config.mjs +195 -0
- package/script/check-css-mixins.ts +191 -0
- package/script/check-css-variables.ts +280 -0
- package/script/convert-icons.ts +202 -0
- package/script/convert-vessel-svg-to-ts.ts +110 -0
- package/script/docgen/README.md +95 -0
- package/script/docgen/docs-gen.ts +225 -0
- package/script/docgen/prompt-system.txt +187 -0
- package/script/download-alert-icons.ts +193 -0
- package/script/download-icons.ts +314 -0
- package/script/figmavariables.json +139 -0
- package/script/generate-bundle-entry.ts +77 -0
- package/script/prepare-full-bundle.ts +105 -0
- package/script/sort-custom-element-manifest.ts +67 -0
- package/src/components/badge/badge.css +15 -15
- package/src/components/badge/badge.stories.ts +2 -0
- package/src/components/icon-button/icon-button.ts +4 -0
- package/src/navigation-instruments/compass/compass.stories.ts +5 -2
- package/src/navigation-instruments/compass/compass.ts +4 -4
- package/src/navigation-instruments/compass-indicator/compass-indicator.stories.ts +34 -1
- package/src/navigation-instruments/compass-indicator/compass-indicator.ts +19 -1
- package/src/navigation-instruments/velocity-projection-plot/velocity-projection-plot.stories.ts +13 -13
- package/src/navigation-instruments/velocity-projection-plot/velocity-projection-plot.ts +15 -11
- package/src/navigation-instruments/watch/environment.ts +120 -87
- package/src/navigation-instruments/watch/watch.stories.ts +2 -2
- package/src/navigation-instruments/watch/watch.ts +3 -3
- package/src/navigation-instruments/wind/wind.stories.ts +4 -3
- package/src/navigation-instruments/wind/wind.ts +2 -2
- package/src/navigation-instruments/wind-indicator/wind-indicator.stories.ts +22 -12
- package/src/navigation-instruments/wind-indicator/wind-indicator.ts +91 -46
- package/src/navigation-instruments/wind-propulsion/wind-propulsion.stories.ts +3 -3
- package/src/navigation-instruments/wind-propulsion/wind-propulsion.ts +3 -3
- package/tsconfig.json +38 -0
- package/vite.config.ts +107 -0
- package/vitest.browser.config.ts +14 -0
- package/vitest.config.ts +51 -0
- package/xliff/es-419.xlf +111 -0
- package/xliff/fi-FI.xlf +139 -0
- package/dist/NotoSans.ttf +0 -0
- package/dist/oicl.svg +0 -4
|
@@ -1,18 +1,131 @@
|
|
|
1
1
|
import {svg, SVGTemplateResult} from 'lit';
|
|
2
2
|
import {styleMap} from 'lit/directives/style-map.js';
|
|
3
|
+
import '../../icons/icon-wind-true-1.js';
|
|
4
|
+
import '../../icons/icon-wind-true-2.js';
|
|
5
|
+
import '../../icons/icon-wind-true-3.js';
|
|
6
|
+
import '../../icons/icon-wind-true-4.js';
|
|
7
|
+
import '../../icons/icon-wind-true-5.js';
|
|
8
|
+
import '../../icons/icon-wind-true-6.js';
|
|
9
|
+
import '../../icons/icon-wind-true-7.js';
|
|
10
|
+
import '../../icons/icon-wind-true-8.js';
|
|
11
|
+
import '../../icons/icon-wind-true-9.js';
|
|
12
|
+
import '../../icons/icon-wind-true-10.js';
|
|
13
|
+
import '../../icons/icon-wind-true-11.js';
|
|
14
|
+
import '../../icons/icon-wind-true-12.js';
|
|
15
|
+
import '../../icons/icon-wind-true-13.js';
|
|
16
|
+
import '../../icons/icon-wind-true-14.js';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Number of wind barb icons available (`<obi-wind-true-1>` …
|
|
20
|
+
* `<obi-wind-true-14>`).
|
|
21
|
+
*
|
|
22
|
+
* The set follows the standard meteorological wind-barb convention:
|
|
23
|
+
* icon 1 is calm, icon 2 is shaft-only (1 kn bucket), icons 3–11 add
|
|
24
|
+
* one half-barb per 5 kn (5, 10, 15, …, 45 kn), icon 12 is one pennant
|
|
25
|
+
* (50 kn), icons 13–14 add full barbs above the pennant (60 / 70 kn).
|
|
26
|
+
*/
|
|
27
|
+
const WIND_ICON_COUNT = 14;
|
|
28
|
+
|
|
29
|
+
/** Render scale applied to the 24×24 icon so it matches the historic 48×48 visual footprint on the watch dial. */
|
|
30
|
+
const WIND_ICON_SCALE = 2;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Tip coordinates of the `obi-wind-true-*` icons in their native 24×24 child
|
|
34
|
+
* space. The arrowhead tip is at approximately (12, 22.4453) — this is the
|
|
35
|
+
* anchor point that lands on the watch's periphery radius so the barb tail
|
|
36
|
+
* extends outward only (matching the legacy inline-glyph behavior).
|
|
37
|
+
*/
|
|
38
|
+
const WIND_ICON_TIP_X = 12;
|
|
39
|
+
const WIND_ICON_TIP_Y = 22.4453;
|
|
40
|
+
|
|
41
|
+
const windIconCache = new Map<string, SVGTemplateResult>();
|
|
42
|
+
|
|
43
|
+
function getWindIconSvg(index: number): SVGTemplateResult | null {
|
|
44
|
+
const tagName = `obi-wind-true-${index}`;
|
|
45
|
+
const cached = windIconCache.get(tagName);
|
|
46
|
+
if (cached) {
|
|
47
|
+
return cached;
|
|
48
|
+
}
|
|
49
|
+
const ctor = customElements.get(tagName) as
|
|
50
|
+
| (new () => {icon?: SVGTemplateResult; iconCss?: SVGTemplateResult})
|
|
51
|
+
| undefined;
|
|
52
|
+
if (!ctor) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
const instance = new ctor();
|
|
56
|
+
const tpl: SVGTemplateResult | undefined = instance.icon ?? instance.iconCss;
|
|
57
|
+
if (!tpl) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
windIconCache.set(tagName, tpl);
|
|
61
|
+
return tpl;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Maps a wind speed in **knots** to a wind-barb icon index in `[1, 14]`.
|
|
66
|
+
*
|
|
67
|
+
* Implements the designer-confirmed "Option C" mapping: speeds round to
|
|
68
|
+
* the nearest 5-knot bucket (with two sub-pennant buckets for calm and
|
|
69
|
+
* near-calm conditions):
|
|
70
|
+
*
|
|
71
|
+
* | Knots range | Icon | Glyph |
|
|
72
|
+
* | ----------- | ---- | -------------------- |
|
|
73
|
+
* | `[0, 0.5)` | 1 | calm |
|
|
74
|
+
* | `[0.5, 2.5)`| 2 | shaft only |
|
|
75
|
+
* | `[2.5, 7.5)`| 3 | shaft + ½ barb |
|
|
76
|
+
* | `[7.5, 12.5)`| 4 | shaft + 1 full barb |
|
|
77
|
+
* | …5-kn steps…| … | … |
|
|
78
|
+
* | `[42.5, 47.5)`| 11 | shaft + 4 full + ½ |
|
|
79
|
+
* | `[47.5, 55)`| 12 | pennant (50 kn) |
|
|
80
|
+
* | `[55, 65)` | 13 | pennant + 1 full barb |
|
|
81
|
+
* | `[65, ∞)` | 14 | pennant + 2 full barbs |
|
|
82
|
+
*
|
|
83
|
+
* The 55 / 65 / 100-knot buckets currently collapse to the nearest
|
|
84
|
+
* available icon; dedicated glyphs are tracked for a follow-up icon
|
|
85
|
+
* refresh. Non-finite / null / undefined inputs fall back to icon 1.
|
|
86
|
+
*/
|
|
87
|
+
export function windKnotsToIconIndex(knots: number | null | undefined): number {
|
|
88
|
+
if (knots == null || !Number.isFinite(knots) || knots < 0.5) {
|
|
89
|
+
return 1;
|
|
90
|
+
}
|
|
91
|
+
if (knots < 2.5) {
|
|
92
|
+
return 2;
|
|
93
|
+
}
|
|
94
|
+
if (knots < 47.5) {
|
|
95
|
+
return Math.round(knots / 5) + 2;
|
|
96
|
+
}
|
|
97
|
+
if (knots < 55) {
|
|
98
|
+
return 12;
|
|
99
|
+
}
|
|
100
|
+
if (knots < 65) {
|
|
101
|
+
return 13;
|
|
102
|
+
}
|
|
103
|
+
return WIND_ICON_COUNT;
|
|
104
|
+
}
|
|
3
105
|
|
|
4
106
|
export function renderWind(options: {
|
|
5
|
-
|
|
107
|
+
windKnots: number;
|
|
6
108
|
fromDirectionDeg: number;
|
|
7
109
|
radius: number;
|
|
8
110
|
color?: string;
|
|
9
111
|
}): SVGTemplateResult {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
112
|
+
const {windKnots, fromDirectionDeg, radius, color} = options;
|
|
113
|
+
const index = windKnotsToIconIndex(windKnots);
|
|
114
|
+
const icon = getWindIconSvg(index);
|
|
115
|
+
if (!icon) {
|
|
116
|
+
return svg``;
|
|
117
|
+
}
|
|
118
|
+
const dirRad = (fromDirectionDeg * Math.PI) / 180;
|
|
119
|
+
const x = Math.sin(dirRad) * radius;
|
|
120
|
+
const y = -Math.cos(dirRad) * radius;
|
|
121
|
+
const tipX = WIND_ICON_TIP_X * WIND_ICON_SCALE;
|
|
122
|
+
const tipY = WIND_ICON_TIP_Y * WIND_ICON_SCALE;
|
|
123
|
+
const styles = {
|
|
124
|
+
color: color ?? 'var(--instrument-regular-secondary-color)',
|
|
125
|
+
};
|
|
126
|
+
return svg`<g style=${styleMap(styles)} transform="translate(${x} ${y}) rotate(${fromDirectionDeg}) translate(${-tipX} ${-tipY}) scale(${WIND_ICON_SCALE})">
|
|
127
|
+
${icon}
|
|
128
|
+
</g>`;
|
|
16
129
|
}
|
|
17
130
|
|
|
18
131
|
export function renderCurrent(options: {
|
|
@@ -73,84 +186,4 @@ export const environmentSvgs: Record<string, SVGTemplateResult> = {
|
|
|
73
186
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M7 10.5858L12.2071 5.37866L17.4142 10.5858L16 12L12.2071 8.20709L8.41421 12L7 10.5858Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
74
187
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M7 16.5858L12.2071 11.3787L17.4142 16.5858L16 18L12.2071 14.2071L8.41421 18L7 16.5858Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
75
188
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M7 22.5858L12.2071 17.3787L17.4142 22.5858L16 24L12.2071 20.2071L8.41421 24L7 22.5858Z" fill="var(--instrument-regular-secondary-color)"/>`,
|
|
76
|
-
'wind-1.svg': svg`<path d="M12 2C6.47715 2 2 6.47715 2 12H3.90476C3.90476 7.52912 7.52912 3.90476 12 3.90476V2Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
77
|
-
<path d="M22 12C22 6.47715 17.5228 2 12 2V3.90476C16.4709 3.90476 20.0952 7.52912 20.0952 12H22Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
78
|
-
<path d="M12 22C17.5228 22 22 17.5228 22 12H20.0952C20.0952 16.4709 16.4709 20.0952 12 20.0952V22Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
79
|
-
<path d="M2 12C2 17.5228 6.47715 22 12 22V20.0952C7.52912 20.0952 3.90476 16.4709 3.90476 12H2Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
80
|
-
<path d="M12 2C6.47715 2 2 6.47715 2 12H3.90476C3.90476 7.52912 7.52912 3.90476 12 3.90476V2Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
81
|
-
<path d="M22 12C22 6.47715 17.5228 2 12 2V3.90476C16.4709 3.90476 20.0952 7.52912 20.0952 12H22Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
82
|
-
<path d="M12 22C17.5228 22 22 17.5228 22 12H20.0952C20.0952 16.4709 16.4709 20.0952 12 20.0952V22Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
83
|
-
<path d="M2 12C2 17.5228 6.47715 22 12 22V20.0952C7.52912 20.0952 3.90476 16.4709 3.90476 12H2Z" fill="var(--instrument-regular-secondary-color)"/>`,
|
|
84
|
-
'wind-2.svg': svg`<path d="M11 24H13L13 7H15L12 0L9 7H11L11 24Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
85
|
-
<path d="M11 24H13L13 7H15L12 0L9 7H11L11 24Z" fill="var(--instrument-regular-secondary-color)"/>`,
|
|
86
|
-
'wind-3.svg': svg`<path d="M11 24L13 24L13 7L15 7L12 -1.74846e-07L9 7L11 7L11 24Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
87
|
-
<path d="M8 21L8 19L11 19L11 21L8 21Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
88
|
-
<path d="M11 24L13 24L13 7L15 7L12 -1.74846e-07L9 7L11 7L11 24Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
89
|
-
<path d="M8 21L8 19L11 19L11 21L8 21Z" fill="var(--instrument-regular-secondary-color)"/>`,
|
|
90
|
-
'wind-4.svg': svg`<path d="M11 24L13 24L13 7L15 7L12 -2.62268e-07L9 7L11 7L11 24Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
91
|
-
<path d="M6 24L6 22L11 22L11 24L6 24Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
92
|
-
<path d="M11 24L13 24L13 7L15 7L12 -2.62268e-07L9 7L11 7L11 24Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
93
|
-
<path d="M6 24L6 22L11 22L11 24L6 24Z" fill="var(--instrument-regular-secondary-color)"/>`,
|
|
94
|
-
'wind-5.svg': svg`<path d="M11 24H13L13 7H15L12 0L9 7H11L11 24Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
95
|
-
<path d="M5 24L5 22H12V24H5Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
96
|
-
<path d="M8 21L8 19H12V21H8Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
97
|
-
<path d="M11 24H13L13 7H15L12 0L9 7H11L11 24Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
98
|
-
<path d="M5 24L5 22H12V24H5Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
99
|
-
<path d="M8 21L8 19H12V21H8Z" fill="var(--instrument-regular-secondary-color)"/>`,
|
|
100
|
-
'wind-6.svg': svg`<path d="M11 24H13L13 7L15 7L12 0L9 7H11L11 24Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
101
|
-
<path d="M5 24L5 22H12V24H5Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
102
|
-
<path d="M5 21L5 19H12V21H5Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
103
|
-
<path d="M11 24H13L13 7L15 7L12 0L9 7H11L11 24Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
104
|
-
<path d="M5 24L5 22H12V24H5Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
105
|
-
<path d="M5 21L5 19H12V21H5Z" fill="var(--instrument-regular-secondary-color)"/>`,
|
|
106
|
-
'wind-7.svg': svg`<path d="M11 24H13L13 7H15L12 0L9 7H11L11 24Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
107
|
-
<path d="M5 24L5 22H12V24H5Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
108
|
-
<path d="M5 21L5 19H12V21H5Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
109
|
-
<path d="M8 18L8 16H12V18H8Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
110
|
-
<path d="M11 24H13L13 7H15L12 0L9 7H11L11 24Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
111
|
-
<path d="M5 24L5 22H12V24H5Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
112
|
-
<path d="M5 21L5 19H12V21H5Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
113
|
-
<path d="M8 18L8 16H12V18H8Z" fill="var(--instrument-regular-secondary-color)"/>`,
|
|
114
|
-
'wind-8.svg': svg`<path d="M11 24H13L13 7H15L12 0L9 7H11L11 24Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
115
|
-
<path d="M5 24L5 22H12V24H5Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
116
|
-
<path d="M5 21L5 19H12V21H5Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
117
|
-
<path d="M5 18L5 16H12V18H5Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
118
|
-
<path d="M11 24H13L13 7H15L12 0L9 7H11L11 24Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
119
|
-
<path d="M5 24L5 22H12V24H5Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
120
|
-
<path d="M5 21L5 19H12V21H5Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
121
|
-
<path d="M5 18L5 16H12V18H5Z" fill="var(--instrument-regular-secondary-color)"/>`,
|
|
122
|
-
'wind-9.svg': svg`<path d="M11 24H13L13 7H15L12 0L9 7H11L11 24Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
123
|
-
<path d="M5 24L5 22H12V24H5Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
124
|
-
<path d="M5 21L5 19H12V21H5Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
125
|
-
<path d="M5 18L5 16H12V18H5Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
126
|
-
<path d="M8 15L8 13H12V15H5Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
127
|
-
<path d="M11 24H13L13 7H15L12 0L9 7H11L11 24Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
128
|
-
<path d="M5 24L5 22H12V24H5Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
129
|
-
<path d="M5 21L5 19H12V21H5Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
130
|
-
<path d="M5 18L5 16H12V18H5Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
131
|
-
<path d="M8 15L8 13H12V15H5Z" fill="var(--instrument-regular-secondary-color)"/>`,
|
|
132
|
-
'wind-10.svg': svg`<path d="M11 24H13L13 7H15L12 0L9 7H11L11 24Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
133
|
-
<path d="M5 24L5 22H12V24H5Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
134
|
-
<path d="M5 21L5 19H12V21H5Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
135
|
-
<path d="M5 18L5 16H12V18H5Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
136
|
-
<path d="M5 15L5 13H12V15H5Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
137
|
-
<path d="M8 12L8 10H12V12H8Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
138
|
-
<path d="M11 24H13L13 7H15L12 0L9 7H11L11 24Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
139
|
-
<path d="M5 24L5 22H12V24H5Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
140
|
-
<path d="M5 21L5 19H12V21H5Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
141
|
-
<path d="M5 18L5 16H12V18H5Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
142
|
-
<path d="M5 15L5 13H12V15H5Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
143
|
-
<path d="M8 12L8 10H12V12H8Z" fill="var(--instrument-regular-secondary-color)"/>`,
|
|
144
|
-
'wind-11.svg': svg`<path d="M5 22L13 24L13 7H15L12 0L9 7H11L11 20L5 22Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
145
|
-
<path d="M5 22L13 24L13 7H15L12 0L9 7H11L11 20L5 22Z" fill="var(--instrument-regular-secondary-color)"/>`,
|
|
146
|
-
'wind-12.svg': svg`<path d="M5 22L13 24L13 7H15L12 0L9 7H11L11 19L5 22Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
147
|
-
<path d="M5 18L5 16H12V18H5Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
148
|
-
<path d="M5 22L13 24L13 7H15L12 0L9 7H11L11 19L5 22Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
149
|
-
<path d="M5 18L5 16H12V18H5Z" fill="var(--instrument-regular-secondary-color)"/>`,
|
|
150
|
-
'wind-13.svg': svg`<path d="M5 22L13 24L13 7H15L12 0L9 7H11L11 19L5 22Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
151
|
-
<path d="M5 18L5 16H12V18H5Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
152
|
-
<path d="M5 15L5 13H12V15H5Z" stroke="var(--border-silhouette-color)" stroke-width="2"/>
|
|
153
|
-
<path d="M5 22L13 24L13 7H15L12 0L9 7H11L11 19L5 22Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
154
|
-
<path d="M5 18L5 16H12V18H5Z" fill="var(--instrument-regular-secondary-color)"/>
|
|
155
|
-
<path d="M5 15L5 13H12V15H5Z" fill="var(--instrument-regular-secondary-color)"/>`,
|
|
156
189
|
};
|
|
@@ -71,7 +71,7 @@ Source of truth: \`packages/openbridge-webcomponents/src/navigation-instruments/
|
|
|
71
71
|
areas: {control: {type: 'object'}},
|
|
72
72
|
padding: {control: {type: 'range', min: 0, max: 100, step: 1}},
|
|
73
73
|
vessels: {control: {type: 'object'}},
|
|
74
|
-
|
|
74
|
+
windKnots: {control: {type: 'range', min: 0, max: 70, step: 1}},
|
|
75
75
|
windFromDirectionDeg: {control: {type: 'range', min: 0, max: 360, step: 1}},
|
|
76
76
|
windSymbolRadius: {control: {type: 'range', min: 0, max: 360, step: 1}},
|
|
77
77
|
current: {control: {type: 'range', min: 0, max: 4, step: 1}},
|
|
@@ -194,7 +194,7 @@ export const WithStarboardPortIndicator: Story = {
|
|
|
194
194
|
|
|
195
195
|
export const WithWind: Story = {
|
|
196
196
|
args: {
|
|
197
|
-
|
|
197
|
+
windKnots: 50,
|
|
198
198
|
windFromDirectionDeg: 116,
|
|
199
199
|
padding: 70,
|
|
200
200
|
windSymbolRadius: 190,
|
|
@@ -222,7 +222,7 @@ export class ObcWatch extends LitElement {
|
|
|
222
222
|
@property({type: Boolean}) crosshairEnabled: boolean = false;
|
|
223
223
|
@property({type: Boolean}) showLabels: boolean = false;
|
|
224
224
|
@property({type: Array, attribute: false}) vessels: WatchVessel[] = [];
|
|
225
|
-
@property({type: Number})
|
|
225
|
+
@property({type: Number}) windKnots: number | null = null;
|
|
226
226
|
@property({type: Number}) windFromDirectionDeg: number | null = null;
|
|
227
227
|
@property({type: Number}) windSymbolRadius: number | null = null;
|
|
228
228
|
@property({type: String}) windColor: string | undefined;
|
|
@@ -766,9 +766,9 @@ export class ObcWatch extends LitElement {
|
|
|
766
766
|
})
|
|
767
767
|
: nothing;
|
|
768
768
|
const wind =
|
|
769
|
-
this.
|
|
769
|
+
this.windKnots != null && this.windFromDirectionDeg != null
|
|
770
770
|
? svg`<g transform="scale(${this.scaleWindIcon})">${renderWind({
|
|
771
|
-
|
|
771
|
+
windKnots: this.windKnots,
|
|
772
772
|
fromDirectionDeg: this.windFromDirectionDeg,
|
|
773
773
|
radius: this.windSymbolRadius ?? 192,
|
|
774
774
|
color: this.windColor,
|
|
@@ -76,7 +76,7 @@ const meta: Meta<typeof ObcWind> = {
|
|
|
76
76
|
width: 400,
|
|
77
77
|
vesselHeadingDeg: 60,
|
|
78
78
|
currentWindFromDirection: 100,
|
|
79
|
-
|
|
79
|
+
currentWindSpeedKnots: 25,
|
|
80
80
|
windHistogramData: windHistogramData,
|
|
81
81
|
},
|
|
82
82
|
argTypes: {
|
|
@@ -85,8 +85,9 @@ const meta: Meta<typeof ObcWind> = {
|
|
|
85
85
|
currentWindFromDirection: {
|
|
86
86
|
control: {type: 'range', min: 0, max: 360, step: 1},
|
|
87
87
|
},
|
|
88
|
-
|
|
89
|
-
control: {type: 'range', min: 0, max:
|
|
88
|
+
currentWindSpeedKnots: {
|
|
89
|
+
control: {type: 'range', min: 0, max: 75, step: 1},
|
|
90
|
+
description: 'Wind speed in knots.',
|
|
90
91
|
},
|
|
91
92
|
windHistogramData: {control: 'object'},
|
|
92
93
|
vesselImage: {
|
|
@@ -33,7 +33,7 @@ const WIND_HISTOGRAM_MIN_RADIUS = 50;
|
|
|
33
33
|
@customElement('obc-wind')
|
|
34
34
|
export class ObcWind extends LitElement {
|
|
35
35
|
@property({type: Number}) currentWindFromDirection: number = 0;
|
|
36
|
-
@property({type: Number})
|
|
36
|
+
@property({type: Number}) currentWindSpeedKnots: number = 25;
|
|
37
37
|
@property({type: Array, attribute: false})
|
|
38
38
|
windHistogramData: WindHistogramData[] = [];
|
|
39
39
|
@property({type: String}) vesselImage: VesselImage = VesselImage.genericTop;
|
|
@@ -146,7 +146,7 @@ export class ObcWind extends LitElement {
|
|
|
146
146
|
${this.renderWindHistogram(variant)}
|
|
147
147
|
<obc-watch
|
|
148
148
|
.watchCircleType=${watchCircleType}
|
|
149
|
-
.
|
|
149
|
+
.windKnots=${this.currentWindSpeedKnots}
|
|
150
150
|
.windFromDirectionDeg=${this.currentWindFromDirection}
|
|
151
151
|
.windSymbolRadius=${windSymbolRadius}
|
|
152
152
|
.scaleWindIcon=${scaleWindIcon}
|
|
@@ -11,15 +11,18 @@ type WindIndicatorArgs = {
|
|
|
11
11
|
type: WindIndicatorType;
|
|
12
12
|
direction: WindIndicatorDirection;
|
|
13
13
|
priority: WindIndicatorPriority;
|
|
14
|
-
|
|
14
|
+
currentWindSpeedKnots: number;
|
|
15
15
|
rotationAngle: number;
|
|
16
|
-
|
|
16
|
+
currentWindFromDirection: number;
|
|
17
17
|
angle?: number;
|
|
18
18
|
'wind-from-angle'?: number;
|
|
19
|
+
'current-wind-from-direction'?: number;
|
|
19
20
|
'rotation-angle'?: number;
|
|
20
|
-
|
|
21
|
+
'current-wind-speed-knots'?: number;
|
|
22
|
+
iconIndex?: number;
|
|
21
23
|
accentColor?: string;
|
|
22
24
|
windIconCache?: unknown;
|
|
25
|
+
windFromAngle?: number;
|
|
23
26
|
};
|
|
24
27
|
|
|
25
28
|
const meta: Meta<WindIndicatorArgs> = {
|
|
@@ -37,14 +40,14 @@ const meta: Meta<WindIndicatorArgs> = {
|
|
|
37
40
|
.type=${args.type}
|
|
38
41
|
.direction=${args.direction}
|
|
39
42
|
.priority=${args.priority}
|
|
40
|
-
.
|
|
43
|
+
.currentWindSpeedKnots=${args.currentWindSpeedKnots}
|
|
41
44
|
.rotationAngle=${args.rotationAngle}
|
|
42
|
-
.
|
|
45
|
+
.currentWindFromDirection=${args.currentWindFromDirection}
|
|
43
46
|
></obc-wind-indicator>
|
|
44
47
|
`,
|
|
45
48
|
args: {
|
|
46
|
-
|
|
47
|
-
|
|
49
|
+
currentWindFromDirection: 0,
|
|
50
|
+
currentWindSpeedKnots: 35,
|
|
48
51
|
type: WindIndicatorType.arrow,
|
|
49
52
|
direction: WindIndicatorDirection.true,
|
|
50
53
|
priority: WindIndicatorPriority.regular,
|
|
@@ -59,8 +62,8 @@ const meta: Meta<WindIndicatorArgs> = {
|
|
|
59
62
|
control: {type: 'select'},
|
|
60
63
|
options: Object.values(WindIndicatorDirection),
|
|
61
64
|
},
|
|
62
|
-
|
|
63
|
-
name: 'Wind From
|
|
65
|
+
currentWindFromDirection: {
|
|
66
|
+
name: 'Current Wind From Direction',
|
|
64
67
|
description: 'Wind-from angle in degrees. 0/360 = wind from north.',
|
|
65
68
|
control: {type: 'range', min: 0, max: 360, step: 1},
|
|
66
69
|
},
|
|
@@ -74,12 +77,19 @@ const meta: Meta<WindIndicatorArgs> = {
|
|
|
74
77
|
control: {type: 'select'},
|
|
75
78
|
options: Object.values(WindIndicatorPriority),
|
|
76
79
|
},
|
|
77
|
-
|
|
80
|
+
currentWindSpeedKnots: {
|
|
81
|
+
description:
|
|
82
|
+
'Wind speed in knots. Mapped to barb icons in 5-kn steps (standard meteorological wind-barb convention).',
|
|
83
|
+
control: {type: 'range', min: 0, max: 75, step: 1},
|
|
84
|
+
},
|
|
78
85
|
|
|
79
86
|
angle: {table: {disable: true}, control: false},
|
|
87
|
+
windFromAngle: {table: {disable: true}, control: false},
|
|
80
88
|
'wind-from-angle': {table: {disable: true}, control: false},
|
|
89
|
+
'current-wind-from-direction': {table: {disable: true}, control: false},
|
|
81
90
|
'rotation-angle': {table: {disable: true}, control: false},
|
|
82
|
-
|
|
91
|
+
'current-wind-speed-knots': {table: {disable: true}, control: false},
|
|
92
|
+
iconIndex: {table: {disable: true}, control: false},
|
|
83
93
|
accentColor: {table: {disable: true}, control: false},
|
|
84
94
|
windIconCache: {table: {disable: true}, control: false},
|
|
85
95
|
},
|
|
@@ -121,6 +131,6 @@ export const Labeled: Story = {
|
|
|
121
131
|
type: WindIndicatorType.labeled,
|
|
122
132
|
direction: WindIndicatorDirection.true,
|
|
123
133
|
priority: WindIndicatorPriority.regular,
|
|
124
|
-
|
|
134
|
+
currentWindSpeedKnots: 60,
|
|
125
135
|
},
|
|
126
136
|
};
|
|
@@ -2,7 +2,35 @@ import {LitElement, css, html, svg, type SVGTemplateResult} from 'lit';
|
|
|
2
2
|
import {property} from 'lit/decorators.js';
|
|
3
3
|
import {customElement} from '../../decorator.js';
|
|
4
4
|
import {styleMap} from 'lit/directives/style-map.js';
|
|
5
|
-
import '../../icons/
|
|
5
|
+
import '../../icons/icon-wind-true-1.js';
|
|
6
|
+
import '../../icons/icon-wind-true-2.js';
|
|
7
|
+
import '../../icons/icon-wind-true-3.js';
|
|
8
|
+
import '../../icons/icon-wind-true-4.js';
|
|
9
|
+
import '../../icons/icon-wind-true-5.js';
|
|
10
|
+
import '../../icons/icon-wind-true-6.js';
|
|
11
|
+
import '../../icons/icon-wind-true-7.js';
|
|
12
|
+
import '../../icons/icon-wind-true-8.js';
|
|
13
|
+
import '../../icons/icon-wind-true-9.js';
|
|
14
|
+
import '../../icons/icon-wind-true-10.js';
|
|
15
|
+
import '../../icons/icon-wind-true-11.js';
|
|
16
|
+
import '../../icons/icon-wind-true-12.js';
|
|
17
|
+
import '../../icons/icon-wind-true-13.js';
|
|
18
|
+
import '../../icons/icon-wind-true-14.js';
|
|
19
|
+
import '../../icons/icon-wind-shaft-1.js';
|
|
20
|
+
import '../../icons/icon-wind-shaft-2.js';
|
|
21
|
+
import '../../icons/icon-wind-shaft-3.js';
|
|
22
|
+
import '../../icons/icon-wind-shaft-4.js';
|
|
23
|
+
import '../../icons/icon-wind-shaft-5.js';
|
|
24
|
+
import '../../icons/icon-wind-shaft-6.js';
|
|
25
|
+
import '../../icons/icon-wind-shaft-7.js';
|
|
26
|
+
import '../../icons/icon-wind-shaft-8.js';
|
|
27
|
+
import '../../icons/icon-wind-shaft-9.js';
|
|
28
|
+
import '../../icons/icon-wind-shaft-10.js';
|
|
29
|
+
import '../../icons/icon-wind-shaft-11.js';
|
|
30
|
+
import '../../icons/icon-wind-shaft-12.js';
|
|
31
|
+
import '../../icons/icon-wind-shaft-13.js';
|
|
32
|
+
import '../../icons/icon-wind-shaft-14.js';
|
|
33
|
+
import {windKnotsToIconIndex} from '../watch/environment.js';
|
|
6
34
|
|
|
7
35
|
export enum WindIndicatorType {
|
|
8
36
|
arrow = 'arrow',
|
|
@@ -43,13 +71,6 @@ const SHAFT_TRUE_CIRCLE_TPL = svg`
|
|
|
43
71
|
/>
|
|
44
72
|
`;
|
|
45
73
|
|
|
46
|
-
const SHAFT_TRUE_WIND_BARB_TPL = svg`
|
|
47
|
-
<path
|
|
48
|
-
d="M39.613 20.3747C39.7971 20.6935 39.6878 21.1013 39.3689 21.2853C39.0501 21.4694 38.6424 21.3602 38.4583 21.0413L36.4583 17.5772L35.3036 18.2439L37.3036 21.708C37.4876 22.0269 37.3784 22.4346 37.0595 22.6187C36.7407 22.8028 36.3329 22.6935 36.1489 22.3747L34.1489 18.9106L32.9942 19.5772L33.9942 21.3093C34.1782 21.6281 34.069 22.0359 33.7501 22.22C33.4313 22.4041 33.0235 22.2948 32.8395 21.9759L31.8395 20.2439L24.3339 24.5772L23.6672 23.4225L36.3114 16.1224C36.6621 15.9201 37.1103 16.0402 37.3128 16.3907L39.613 20.3747Z"
|
|
49
|
-
fill="currentColor"
|
|
50
|
-
/>
|
|
51
|
-
`;
|
|
52
|
-
|
|
53
74
|
const SHAFT_TRUE_WIND_BARB_D_BY_LEVEL: string[] = [
|
|
54
75
|
'M33.0954 23.7527C35.1680 22.5560 35.8782 19.9058 34.6816 17.8332C33.4850 15.7606 30.8347 15.0504 28.7621 16.2471C26.6895 17.4437 25.9794 20.0939 27.1760 22.1665L26.3099 22.6665C24.8372 20.1156 25.7112 16.8538 28.2621 15.3810C30.8130 13.9083 34.0748 14.7823 35.5476 17.3332C37.0204 19.8841 36.1463 23.1459 33.5954 24.6187C31.0445 26.0914 27.7827 25.2174 26.3099 22.6665L27.1760 22.1665C28.3726 24.2392 31.0228 24.9493 33.0954 23.7527L33.0954 23.7527',
|
|
55
76
|
'M37.2797 16.3332C37.4638 16.6521 37.3545 17.0598 37.0356 17.2439L24.3339 24.5772L23.6672 23.4225L36.3690 16.0892C36.6878 15.9051 37.0956 16.0143 37.2797 16.3332L37.2797 16.3332',
|
|
@@ -64,6 +85,7 @@ const SHAFT_TRUE_WIND_BARB_D_BY_LEVEL: string[] = [
|
|
|
64
85
|
'M39.6130 20.3747C39.7971 20.6936 39.6878 21.1013 39.3690 21.2854C39.0501 21.4695 38.6424 21.3602 38.4583 21.0413L36.4583 17.5772L35.3036 18.2439L37.3036 21.7080C37.4877 22.0269 37.3784 22.4346 37.0595 22.6187C36.7407 22.8028 36.3330 22.6935 36.1489 22.3747L34.1489 18.9106L32.9942 19.5772L34.9941 23.0413C35.1782 23.3602 35.0690 23.7679 34.7501 23.9520C34.4313 24.1361 34.0235 24.0269 33.8394 23.7080L31.8395 20.2439L30.6847 20.9105L32.6847 24.3747C32.8688 24.6935 32.7596 25.1012 32.4407 25.2853C32.1218 25.4694 31.7141 25.3602 31.5300 25.0413L29.5300 21.5772L28.3753 22.2439L29.3753 23.9759C29.5594 24.2948 29.4502 24.7025 29.1313 24.8866C28.8124 25.0707 28.4047 24.9615 28.2206 24.6426L27.2206 22.9105L24.3339 24.5772L23.6672 23.4225L36.3115 16.1224C36.6621 15.9201 37.1103 16.0402 37.3129 16.3907L39.6130 20.3747L39.6130 20.3747',
|
|
65
86
|
'M37.3380 16.4822L37.3672 16.5654L38.7821 21.5122C38.9920 22.2462 38.0802 22.7726 37.5496 22.2238L34.2758 18.8373L24.3339 24.5772L23.6672 23.4224L36.2952 16.1318C36.6825 15.9082 37.1705 16.0816 37.3380 16.4822L37.3380 16.4822',
|
|
66
87
|
'M37.3380 16.4822L37.3672 16.5654L38.7821 21.5122C38.9920 22.2462 38.0802 22.7726 37.5496 22.2238L34.2758 18.8373L32.9942 19.5772L34.9942 23.0413C35.1783 23.3602 35.0690 23.7679 34.7502 23.9520C34.4313 24.1361 34.0236 24.0268 33.8395 23.7080L31.8395 20.2438L24.3339 24.5772L23.6672 23.4224L36.2952 16.1318C36.6825 15.9082 37.1705 16.0816 37.3380 16.4822L37.3380 16.4822',
|
|
88
|
+
'M37.3380 16.4822L37.3672 16.5654L38.7821 21.5122C38.9920 22.2462 38.0802 22.7726 37.5496 22.2238L34.2758 18.8373L32.9942 19.5772L34.9942 23.0413C35.1783 23.3602 35.0690 23.7679 34.7502 23.9520C34.4313 24.1361 34.0236 24.0268 33.8395 23.7080L31.8395 20.2438L30.6847 20.9105L32.6847 24.3747C32.8688 24.6935 32.7596 25.1012 32.4407 25.2853C32.1218 25.4694 31.7141 25.3602 31.5300 25.0413L29.5300 21.5772L24.3339 24.5772L23.6672 23.4224L36.2952 16.1318C36.6825 15.9082 37.1705 16.0816 37.3380 16.4822L37.3380 16.4822',
|
|
67
89
|
];
|
|
68
90
|
|
|
69
91
|
const SHAFT_RELATIVE_EXPORT_OFFSET_X = -9.9395;
|
|
@@ -169,16 +191,23 @@ const LABELED_ARROW_TPL = svg`
|
|
|
169
191
|
/**
|
|
170
192
|
* `<obc-wind-indicator>` – A compact wind indicator with a fixed frame and a rotating wind marker.
|
|
171
193
|
*
|
|
172
|
-
* Visualizes a
|
|
194
|
+
* Visualizes a wind speed in knots using a compact wind-barb icon plus
|
|
195
|
+
* optional mode layers.
|
|
173
196
|
*
|
|
174
197
|
* ## Features
|
|
175
198
|
*
|
|
176
199
|
* - **Variants:** `type` (`arrow` | `shaft` | `labeled`), `direction` (`true` | `relative`), `priority` (`regular` | `enhanced`).
|
|
177
|
-
* - **
|
|
200
|
+
* - **Speed input:** `currentWindSpeedKnots` is the wind speed in knots.
|
|
201
|
+
* The barb icon follows the standard meteorological convention (one
|
|
202
|
+
* half-barb per 5 kn). 0–65 kn covers all 14 icons; higher values clamp
|
|
203
|
+
* to the heaviest icon.
|
|
178
204
|
*
|
|
179
205
|
* ## Usage Guidelines
|
|
180
206
|
*
|
|
181
207
|
* Use when you need a small wind cue next to other compact indicators.
|
|
208
|
+
* Pass the wind speed in knots through `currentWindSpeedKnots`, matching
|
|
209
|
+
* the convention used by `<obc-wind>`, `<obc-wind-propulsion>` and
|
|
210
|
+
* `<obc-compass>`.
|
|
182
211
|
*/
|
|
183
212
|
@customElement('obc-wind-indicator')
|
|
184
213
|
export class ObcWindIndicator extends LitElement {
|
|
@@ -190,12 +219,24 @@ export class ObcWindIndicator extends LitElement {
|
|
|
190
219
|
@property({type: String}) priority: WindIndicatorPriority =
|
|
191
220
|
WindIndicatorPriority.regular;
|
|
192
221
|
|
|
193
|
-
|
|
222
|
+
/**
|
|
223
|
+
* Wind speed in **knots**, used to pick the wind-barb icon.
|
|
224
|
+
*
|
|
225
|
+
* Maps to the icon set using the designer-confirmed "Option C"
|
|
226
|
+
* ranges: `[0, 0.5)` kn renders calm, `[0.5, 2.5)` kn renders a
|
|
227
|
+
* shaft only, then 5-kn nearest-neighbour buckets up to 45 kn
|
|
228
|
+
* (half-barb steps), `[47.5, 55)` kn renders the 50-kn pennant, and
|
|
229
|
+
* `[55, 65)` / `[65, ∞)` kn add one and two full barbs above the
|
|
230
|
+
* pennant respectively. Non-finite or negative values fall back to
|
|
231
|
+
* calm.
|
|
232
|
+
*/
|
|
233
|
+
@property({type: Number, attribute: 'current-wind-speed-knots'})
|
|
234
|
+
currentWindSpeedKnots = 0;
|
|
194
235
|
|
|
195
236
|
/**
|
|
196
237
|
* Rotation of the reference frame (course/heading) in degrees.
|
|
197
238
|
*
|
|
198
|
-
*
|
|
239
|
+
* This could be the heading or the course of the vessel.
|
|
199
240
|
* `0` means north-up.
|
|
200
241
|
*/
|
|
201
242
|
@property({type: Number, attribute: 'rotation-angle'}) rotationAngle = 0;
|
|
@@ -207,17 +248,29 @@ export class ObcWindIndicator extends LitElement {
|
|
|
207
248
|
* - `0` / `360`: wind from north → marker points south (down)
|
|
208
249
|
* - `180`: wind from south → marker points north (up)
|
|
209
250
|
*/
|
|
210
|
-
@property({type: Number, attribute: 'wind-from-
|
|
251
|
+
@property({type: Number, attribute: 'current-wind-from-direction'})
|
|
252
|
+
currentWindFromDirection = 0;
|
|
211
253
|
|
|
212
254
|
/**
|
|
213
|
-
* @deprecated Use `
|
|
255
|
+
* @deprecated Use `currentWindFromDirection` instead.
|
|
256
|
+
*/
|
|
257
|
+
@property({type: Number})
|
|
258
|
+
get windFromAngle() {
|
|
259
|
+
return this.currentWindFromDirection;
|
|
260
|
+
}
|
|
261
|
+
set windFromAngle(value: number) {
|
|
262
|
+
this.currentWindFromDirection = value;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* @deprecated Use `currentWindFromDirection` instead.
|
|
214
267
|
*/
|
|
215
268
|
@property({type: Number})
|
|
216
269
|
get angle() {
|
|
217
|
-
return this.
|
|
270
|
+
return this.currentWindFromDirection;
|
|
218
271
|
}
|
|
219
272
|
set angle(value: number) {
|
|
220
|
-
this.
|
|
273
|
+
this.currentWindFromDirection = value;
|
|
221
274
|
}
|
|
222
275
|
|
|
223
276
|
static override styles = css`
|
|
@@ -252,15 +305,13 @@ export class ObcWindIndicator extends LitElement {
|
|
|
252
305
|
}
|
|
253
306
|
`;
|
|
254
307
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
private get clampedLevel(): number {
|
|
263
|
-
return this.clampLevel(this.level);
|
|
308
|
+
/**
|
|
309
|
+
* Icon index in the range `1..14`, derived from `currentWindSpeedKnots`
|
|
310
|
+
* via the shared `windKnotsToIconIndex` helper (standard meteorological
|
|
311
|
+
* wind-barb convention; one half-barb per 5 kn).
|
|
312
|
+
*/
|
|
313
|
+
private get iconIndex(): number {
|
|
314
|
+
return windKnotsToIconIndex(this.currentWindSpeedKnots);
|
|
264
315
|
}
|
|
265
316
|
|
|
266
317
|
private get accentColor(): string {
|
|
@@ -271,11 +322,11 @@ export class ObcWindIndicator extends LitElement {
|
|
|
271
322
|
|
|
272
323
|
private getWindBaseAngle(): number {
|
|
273
324
|
if (this.type === WindIndicatorType.labeled) {
|
|
274
|
-
return this.
|
|
325
|
+
return this.currentWindFromDirection;
|
|
275
326
|
}
|
|
276
327
|
return this.direction === WindIndicatorDirection.relative
|
|
277
|
-
? this.
|
|
278
|
-
: this.
|
|
328
|
+
? this.currentWindFromDirection + this.rotationAngle
|
|
329
|
+
: this.currentWindFromDirection;
|
|
279
330
|
}
|
|
280
331
|
|
|
281
332
|
private getWindRotation(offsetDeg = 0): number {
|
|
@@ -309,12 +360,8 @@ export class ObcWindIndicator extends LitElement {
|
|
|
309
360
|
return tpl;
|
|
310
361
|
}
|
|
311
362
|
|
|
312
|
-
private getWindIconTagName(
|
|
313
|
-
|
|
314
|
-
_direction: string,
|
|
315
|
-
level: number
|
|
316
|
-
): string {
|
|
317
|
-
const index = Math.max(0, Math.min(12, Math.round(level))) + 1;
|
|
363
|
+
private getWindIconTagName(type: string, _direction: string): string {
|
|
364
|
+
const index = this.iconIndex;
|
|
318
365
|
|
|
319
366
|
if (type === WindIndicatorType.shaft) {
|
|
320
367
|
return `obi-wind-shaft-${index}`;
|
|
@@ -325,10 +372,9 @@ export class ObcWindIndicator extends LitElement {
|
|
|
325
372
|
|
|
326
373
|
private getWindIcon(
|
|
327
374
|
type: string,
|
|
328
|
-
direction: string
|
|
329
|
-
level: number
|
|
375
|
+
direction: string
|
|
330
376
|
): SVGTemplateResult | null {
|
|
331
|
-
const tagName = this.getWindIconTagName(type, direction
|
|
377
|
+
const tagName = this.getWindIconTagName(type, direction);
|
|
332
378
|
return this.getWindIconSvg(tagName);
|
|
333
379
|
}
|
|
334
380
|
|
|
@@ -412,8 +458,7 @@ export class ObcWindIndicator extends LitElement {
|
|
|
412
458
|
const windStyles = {color: this.accentColor};
|
|
413
459
|
const windIcon = this.getWindIcon(
|
|
414
460
|
WindIndicatorType.shaft,
|
|
415
|
-
this.direction
|
|
416
|
-
this.clampedLevel
|
|
461
|
+
this.direction
|
|
417
462
|
);
|
|
418
463
|
|
|
419
464
|
const windMarker = svg`
|
|
@@ -473,17 +518,13 @@ export class ObcWindIndicator extends LitElement {
|
|
|
473
518
|
transform="rotate(${this.getWindRotation(SHAFT_TRUE_ARROW_OFFSET_DEG)} ${CX} ${CY})"
|
|
474
519
|
data-name="hdg"
|
|
475
520
|
>
|
|
476
|
-
${
|
|
477
|
-
this.clampedLevel === 7
|
|
478
|
-
? SHAFT_TRUE_WIND_BARB_TPL
|
|
479
|
-
: svg`<path d=${SHAFT_TRUE_WIND_BARB_D_BY_LEVEL[this.clampedLevel]} fill="currentColor" />`
|
|
480
|
-
}
|
|
521
|
+
${svg`<path d=${SHAFT_TRUE_WIND_BARB_D_BY_LEVEL[this.iconIndex - 1]} fill="currentColor" />`}
|
|
481
522
|
${SHAFT_TRUE_CIRCLE_TPL}
|
|
482
523
|
</g>
|
|
483
524
|
`;
|
|
484
525
|
}
|
|
485
526
|
|
|
486
|
-
const icon = this.getWindIcon(this.type, this.direction
|
|
527
|
+
const icon = this.getWindIcon(this.type, this.direction);
|
|
487
528
|
if (!icon) {
|
|
488
529
|
return null;
|
|
489
530
|
}
|
|
@@ -505,6 +546,10 @@ export class ObcWindIndicator extends LitElement {
|
|
|
505
546
|
return null;
|
|
506
547
|
}
|
|
507
548
|
|
|
549
|
+
const value = Number.isFinite(this.currentWindSpeedKnots)
|
|
550
|
+
? Math.max(0, Math.round(this.currentWindSpeedKnots))
|
|
551
|
+
: 0;
|
|
552
|
+
|
|
508
553
|
return svg`
|
|
509
554
|
<text
|
|
510
555
|
x="${CX}"
|
|
@@ -516,7 +561,7 @@ export class ObcWindIndicator extends LitElement {
|
|
|
516
561
|
font-weight="var(--global-typography-ui-label-active-font-weight)"
|
|
517
562
|
line-height="var(--global-typography-ui-label-active-line-height)"
|
|
518
563
|
>
|
|
519
|
-
${
|
|
564
|
+
${value}
|
|
520
565
|
</text>
|
|
521
566
|
`;
|
|
522
567
|
}
|