@oicl/openbridge-webcomponents 0.0.15-dev-20240915195432 → 0.0.15-dev-20240916185711
Sign up to get free protection for your applications and to get access to all the features.
- package/__snapshots__/navigation-instruments-azimuth-thruster--in-command-at-setpoint-disable-auto-setpoint.png +0 -0
- package/__snapshots__/navigation-instruments-azimuth-thruster--in-command-at-setpoint.png +0 -0
- package/__snapshots__/navigation-instruments-azimuth-thruster--in-command.png +0 -0
- package/__snapshots__/navigation-instruments-azimuth-thruster--pod.png +0 -0
- package/__snapshots__/navigation-instruments-azimuth-thruster--single-direction-with-propeller.png +0 -0
- package/__snapshots__/navigation-instruments-azimuth-thruster--single-direction.png +0 -0
- package/__snapshots__/navigation-instruments-azimuth-thruster-labeled--large.png +0 -0
- package/__snapshots__/navigation-instruments-main-engine--active.png +0 -0
- package/__snapshots__/navigation-instruments-main-engine--in-command.png +0 -0
- package/__snapshots__/navigation-instruments-main-engine--off.png +0 -0
- package/__snapshots__/navigation-instruments-thruster--tunnel.png +0 -0
- package/custom-elements.json +570 -7
- package/dist/navigation-instruments/azimuth-thruster/azimuth-thruster.d.ts.map +1 -1
- package/dist/navigation-instruments/azimuth-thruster/azimuth-thruster.js +2 -1
- package/dist/navigation-instruments/azimuth-thruster/azimuth-thruster.js.map +1 -1
- package/dist/navigation-instruments/main-engine/main-engine.css.js +22 -0
- package/dist/navigation-instruments/main-engine/main-engine.css.js.map +1 -0
- package/dist/navigation-instruments/main-engine/main-engine.d.ts +29 -0
- package/dist/navigation-instruments/main-engine/main-engine.d.ts.map +1 -0
- package/dist/navigation-instruments/main-engine/main-engine.js +196 -0
- package/dist/navigation-instruments/main-engine/main-engine.js.map +1 -0
- package/dist/navigation-instruments/thruster/thruster.d.ts +54 -1
- package/dist/navigation-instruments/thruster/thruster.d.ts.map +1 -1
- package/dist/navigation-instruments/thruster/thruster.js +163 -99
- package/dist/navigation-instruments/thruster/thruster.js.map +1 -1
- package/package.json +1 -1
- package/src/navigation-instruments/azimuth-thruster/azimuth-thruster.ts +1 -0
- package/src/navigation-instruments/main-engine/main-engine.css +17 -0
- package/src/navigation-instruments/main-engine/main-engine.stories.ts +54 -0
- package/src/navigation-instruments/main-engine/main-engine.ts +160 -0
- package/src/navigation-instruments/thruster/thruster.stories.ts +1 -0
- package/src/navigation-instruments/thruster/thruster.ts +205 -113
- package/src/palettes/variables.css +1343 -1343
@@ -1,4 +1,4 @@
|
|
1
|
-
import { css, LitElement, html, svg } from "lit";
|
1
|
+
import { css, LitElement, html, svg, nothing } from "lit";
|
2
2
|
import { property, customElement } from "lit/decorators.js";
|
3
3
|
import { InstrumentState } from "../types.js";
|
4
4
|
import { renderAdvice } from "./advice.js";
|
@@ -49,7 +49,8 @@ let ObcThruster = class extends LitElement {
|
|
49
49
|
singleDirection: this.singleDirection,
|
50
50
|
singleDirectionHalfSize: this.singleDirectionHalfSize,
|
51
51
|
topPropeller: this.topPropeller,
|
52
|
-
bottomPropeller: this.bottomPropeller
|
52
|
+
bottomPropeller: this.bottomPropeller,
|
53
|
+
narrow: !this.tunnel
|
53
54
|
})}
|
54
55
|
</div>`;
|
55
56
|
}
|
@@ -113,7 +114,7 @@ __decorateClass([
|
|
113
114
|
ObcThruster = __decorateClass([
|
114
115
|
customElement("obc-thruster")
|
115
116
|
], ObcThruster);
|
116
|
-
function thrusterTop(height, value, colors,
|
117
|
+
function thrusterTop(height, value, colors, options) {
|
117
118
|
const container = svg`
|
118
119
|
<path transform="translate(0 -2)" d="M -44 0 v -${height - 8} a 8 8 0 0 1 8 -8 h 72 a 8 8 0 0 1 8 8 V 0 Z" fill=${colors.container} stroke="var(--instrument-frame-tertiary-color)" vector-effect="non-scaling-stroke"/>
|
119
120
|
`;
|
@@ -121,7 +122,7 @@ function thrusterTop(height, value, colors, hideTicks) {
|
|
121
122
|
const tickmarks = [];
|
122
123
|
const nTicks = 2;
|
123
124
|
const delta = height / nTicks;
|
124
|
-
if (!hideTicks) {
|
125
|
+
if (!options.hideTicks) {
|
125
126
|
for (let i = 1; i < nTicks; i++) {
|
126
127
|
tickmarks.push(
|
127
128
|
svg`<line x1="-24" x2="-44" y1=${-i * delta - 2} y2=${-i * delta - 2} stroke="var(--instrument-frame-tertiary-color)" stroke-width="1" vector-effect="non-scaling-stroke"/>`
|
@@ -134,49 +135,70 @@ function thrusterTop(height, value, colors, hideTicks) {
|
|
134
135
|
const barHeight = height * value / 100;
|
135
136
|
const barY = -2 - barHeight;
|
136
137
|
const bar = svg`<rect width="40" height=${barHeight} x="-20" y=${barY} fill=${colors.box} stroke=${colors.box} vector-effect="non-scaling-stroke"/>`;
|
137
|
-
|
138
|
+
if (options.hideContainer) {
|
139
|
+
return [track, tickmarks, bar];
|
140
|
+
} else {
|
141
|
+
return [container, track, tickmarks, bar];
|
142
|
+
}
|
138
143
|
}
|
139
|
-
function thrusterTopSingleSided(height, value, colors,
|
140
|
-
const container = svg`
|
144
|
+
function thrusterTopSingleSided(height, value, colors, options, advice) {
|
145
|
+
const container = options.narrow ? svg`
|
141
146
|
<path transform="translate(0 -2)" d="M -32 0 v -${height - 8} a 8 8 0 0 1 8 -8 h 48 a 8 8 0 0 1 8 8 V 0 Z" fill=${colors.container} stroke="var(--instrument-frame-tertiary-color)" vector-effect="non-scaling-stroke"/>
|
147
|
+
` : svg`
|
148
|
+
<path transform="translate(0 -2)" d="M -40 0 v -${height - 8} a 8 8 0 0 1 8 -8 h 56 a 8 8 0 0 1 8 8 V 0 Z" fill=${colors.container} stroke="var(--instrument-frame-tertiary-color)" vector-effect="non-scaling-stroke"/>
|
142
149
|
`;
|
143
|
-
const track = svg`
|
150
|
+
const track = options.narrow ? svg`
|
144
151
|
<path transform="translate(0 -2)" d="M -32 0 v -${height - 8} a 8 8 0 0 1 8 -8 h 32 V 0 Z" fill="var(--instrument-frame-secondary-color)" stroke="var(--instrument-frame-tertiary-color)" vector-effect="non-scaling-stroke"/>
|
152
|
+
` : svg`
|
153
|
+
<path transform="translate(0 -2)" d="M -40 0 v -${height - 8} a 8 8 0 0 1 8 -8 h 40 V 0 Z" fill="var(--instrument-frame-secondary-color)" stroke="var(--instrument-frame-tertiary-color)" vector-effect="non-scaling-stroke"/>
|
145
154
|
`;
|
146
|
-
const tickmarks = hideTicks ? [] : [singleSidedTickmark(height, 50, TickmarkStyle.hinted)];
|
155
|
+
const tickmarks = options.hideTicks ? [] : [singleSidedTickmark(height, 50, TickmarkStyle.hinted)];
|
147
156
|
const barHeight = height * value / 100;
|
157
|
+
const barWidth = options.narrow ? 40 : 48;
|
158
|
+
const barX = options.narrow ? -32 : -40;
|
148
159
|
const barY = -2 - barHeight;
|
149
|
-
const maskId = flipAdicePattern ? "thrusterBarMask1" : "thrusterBarMask2";
|
150
|
-
const
|
160
|
+
const maskId = options.flipAdicePattern ? "thrusterBarMask1" : "thrusterBarMask2";
|
161
|
+
const mask = options.hideContainer ? nothing : svg`
|
151
162
|
<defs>
|
152
163
|
<mask id=${maskId}>
|
153
|
-
<path transform="translate(0 -2)" d="M
|
154
|
-
</defs
|
155
|
-
|
164
|
+
<path transform="translate(0 -2)" d="M ${barX} 0 v -${height - 8} a 8 8 0 0 1 8 -8 h ${barWidth} V 0 Z" fill="white" stroke="white" vector-effect="non-scaling-stroke"/>
|
165
|
+
</defs>`;
|
166
|
+
const maskAttr = options.hideContainer ? "" : `mask="url(#${maskId})"`;
|
167
|
+
const bar = svg`
|
168
|
+
${mask}
|
169
|
+
<rect ${maskAttr} width=${barWidth} height=${barHeight} x=${barX} y=${barY} fill=${colors.box} stroke=${colors.box} vector-effect="non-scaling-stroke"/>`;
|
156
170
|
const advicesSvg = advice.map(
|
157
|
-
(a) => renderAdvice(height, a, flipAdicePattern)
|
171
|
+
(a) => renderAdvice(height, a, options.flipAdicePattern)
|
158
172
|
);
|
159
|
-
|
173
|
+
const all = [tickmarks, bar, advicesSvg];
|
174
|
+
if (!options.hideContainer) {
|
175
|
+
all.splice(0, 0, [container, track]);
|
176
|
+
}
|
177
|
+
if (!options.narrow) {
|
178
|
+
return svg`<g transform="translate(4 0)">${all}</g>`;
|
179
|
+
} else {
|
180
|
+
return all;
|
181
|
+
}
|
160
182
|
}
|
161
|
-
function thrusterBottom(height, value, colors,
|
183
|
+
function thrusterBottom(height, value, colors, options) {
|
162
184
|
const container = svg`
|
163
185
|
<g transform="rotate(180)">
|
164
|
-
${thrusterTop(height, value, colors,
|
186
|
+
${thrusterTop(height, value, colors, options)}
|
165
187
|
</g>
|
166
188
|
`;
|
167
189
|
return container;
|
168
190
|
}
|
169
|
-
function thrusterBottomSingleSided(height, value, colors,
|
191
|
+
function thrusterBottomSingleSided(height, value, colors, options, advice) {
|
170
192
|
const container = svg`
|
171
193
|
<g transform="rotate(180) scale(-1,1)">
|
172
|
-
${thrusterTopSingleSided(height, value, colors, hideTicks,
|
194
|
+
${thrusterTopSingleSided(height, value, colors, { hideTicks: options.hideTicks, flipAdicePattern: options.flipAdicePattern, hideContainer: options.hideContainer, narrow: options.narrow }, advice)}
|
173
195
|
</g>
|
174
196
|
`;
|
175
197
|
return container;
|
176
198
|
}
|
177
199
|
function setpointSvg(height, value, setpointAtZero, colors, options) {
|
178
200
|
const y = -(setpointAtZero ? 0 : Math.sign(value) * (height * Math.abs(value) / 100 + 2));
|
179
|
-
const extra = options.singleSided ? -12 : 0;
|
201
|
+
const extra = (options.singleSided ? -12 : 0) + (options.narrow ? 0 : 4);
|
180
202
|
let path;
|
181
203
|
if (options.inCommand) {
|
182
204
|
path = "M23.5119 8C24.6981 6.35191 23.5696 4 21.5926 4L2.39959 4C0.422598 4 -0.705911 6.35191 0.480283 8L11.9961 24L23.5119 8Z";
|
@@ -203,78 +225,38 @@ function setpointSvg(height, value, setpointAtZero, colors, options) {
|
|
203
225
|
</g>
|
204
226
|
`;
|
205
227
|
}
|
206
|
-
function
|
207
|
-
if (
|
208
|
-
|
228
|
+
function atSetpoint(thrust, setpoint, options) {
|
229
|
+
if (options.touching) {
|
230
|
+
return false;
|
209
231
|
}
|
210
232
|
if (options.autoAtSetpoint && setpoint !== void 0) {
|
211
|
-
|
212
|
-
}
|
213
|
-
if (options.touching) {
|
214
|
-
options.atSetpoint = false;
|
233
|
+
return Math.abs(thrust - setpoint) < options.autoSetpointDeadband;
|
215
234
|
}
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
if (options.atSetpoint) {
|
223
|
-
setPointColor = boxColor;
|
235
|
+
return options.atSetpoint;
|
236
|
+
}
|
237
|
+
function thruster(thrust, setpoint, state, options) {
|
238
|
+
if (options.tunnel) {
|
239
|
+
thrust = -thrust;
|
240
|
+
setpoint = setpoint === void 0 ? void 0 : -setpoint;
|
224
241
|
}
|
225
|
-
if (
|
226
|
-
|
227
|
-
zeroLineColor = "var(--instrument-regular-secondary-color)";
|
228
|
-
setPointColor = "var(--instrument-regular-primary-color)";
|
229
|
-
arrowColor = "var(--instrument-regular-secondary-color)";
|
230
|
-
if (options.atSetpoint) {
|
231
|
-
setPointColor = boxColor;
|
232
|
-
}
|
233
|
-
} else if (state === InstrumentState.loading) {
|
234
|
-
boxColor = "transparent";
|
235
|
-
setPointColor = "var(--instrument-frame-tertiary-color)";
|
236
|
-
zeroLineColor = "var(--instrument-frame-tertiary-color)";
|
237
|
-
arrowColor = "var(--instrument-regular-secondary-color)";
|
238
|
-
thrust = 0;
|
239
|
-
hideTicks = true;
|
240
|
-
if (setpoint !== void 0) {
|
241
|
-
setpoint = 0;
|
242
|
-
}
|
243
|
-
} else if (state === InstrumentState.off) {
|
244
|
-
boxColor = "transparent";
|
245
|
-
setPointColor = "var(--instrument-frame-tertiary-color)";
|
246
|
-
arrowColor = "var(--instrument-frame-tertiary-color)";
|
247
|
-
zeroLineColor = "var(--instrument-frame-tertiary-color)";
|
248
|
-
thrust = 0;
|
249
|
-
hideTicks = true;
|
250
|
-
containerBackgroundColor = "transparent";
|
251
|
-
if (setpoint !== void 0) {
|
252
|
-
setpoint = 0;
|
253
|
-
}
|
242
|
+
if (!options.singleSided && options.advices.length > 0) {
|
243
|
+
throw new Error("Double sided thruster does not support advice");
|
254
244
|
}
|
255
|
-
|
256
|
-
|
245
|
+
options.atSetpoint = atSetpoint(thrust, setpoint, options);
|
246
|
+
const tc = thrusterColors(options, state);
|
247
|
+
let centerLine = svg`
|
248
|
+
<rect x="-44" y="-2" width="88" height="4" stroke-width="1" fill=${tc.zeroLineColor} stroke=${tc.zeroLineColor} vector-effect="non-scaling-stroke"/>
|
257
249
|
`;
|
250
|
+
if (options.singleSided) {
|
251
|
+
const width = options.narrow ? 64 : 72;
|
252
|
+
const x = options.narrow ? -32 : -36;
|
253
|
+
centerLine = svg`<rect x=${x} y="-2" width=${width} height="4" stroke-width="1" fill=${tc.zeroLineColor} stroke=${tc.zeroLineColor} vector-effect="non-scaling-stroke"/>`;
|
254
|
+
}
|
258
255
|
const setpointAtZero = Math.abs(setpoint || 0) < options.setpointAtZeroDeadband;
|
259
|
-
const
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
state2 = AdviceState.triggered;
|
264
|
-
} else if (a.hinted) {
|
265
|
-
state2 = AdviceState.hinted;
|
266
|
-
} else {
|
267
|
-
state2 = AdviceState.regular;
|
268
|
-
}
|
269
|
-
return {
|
270
|
-
min: a.min,
|
271
|
-
max: a.max,
|
272
|
-
type: a.type,
|
273
|
-
state: state2
|
274
|
-
};
|
275
|
-
});
|
276
|
-
const topAdvices = advices.filter((a) => a.min >= 0);
|
277
|
-
const bottomAdvices = advices.filter((a) => a.max <= 0).map((a) => ({ ...a, min: -a.max, max: -a.min }));
|
256
|
+
const { topAdvices, bottomAdvices } = convertThrustAdvices(
|
257
|
+
options.advices,
|
258
|
+
thrust
|
259
|
+
);
|
278
260
|
const thrusterSvg = [];
|
279
261
|
const baseheight = options.topPropeller === PropellerType.none ? 134 : 106;
|
280
262
|
const height = options.singleDirection ? baseheight * 2 : baseheight;
|
@@ -283,8 +265,13 @@ function thruster(thrust, setpoint, state, options) {
|
|
283
265
|
thrusterTopSingleSided(
|
284
266
|
height,
|
285
267
|
Math.max(thrust, 0),
|
286
|
-
{ box: boxColor, container: containerBackgroundColor },
|
287
|
-
|
268
|
+
{ box: tc.boxColor, container: tc.containerBackgroundColor },
|
269
|
+
{
|
270
|
+
hideTicks: tc.hideTicks,
|
271
|
+
flipAdicePattern: false,
|
272
|
+
hideContainer: false,
|
273
|
+
narrow: options.narrow
|
274
|
+
},
|
288
275
|
topAdvices
|
289
276
|
)
|
290
277
|
);
|
@@ -293,8 +280,13 @@ function thruster(thrust, setpoint, state, options) {
|
|
293
280
|
thrusterBottomSingleSided(
|
294
281
|
height,
|
295
282
|
Math.max(-thrust, 0),
|
296
|
-
{ box: boxColor, container: containerBackgroundColor },
|
297
|
-
|
283
|
+
{ box: tc.boxColor, container: tc.containerBackgroundColor },
|
284
|
+
{
|
285
|
+
hideTicks: tc.hideTicks,
|
286
|
+
flipAdicePattern: true,
|
287
|
+
hideContainer: false,
|
288
|
+
narrow: options.narrow
|
289
|
+
},
|
298
290
|
bottomAdvices
|
299
291
|
)
|
300
292
|
);
|
@@ -305,8 +297,8 @@ function thruster(thrust, setpoint, state, options) {
|
|
305
297
|
thrusterTop(
|
306
298
|
height,
|
307
299
|
Math.max(thrust, 0),
|
308
|
-
{ box: boxColor, container: containerBackgroundColor },
|
309
|
-
hideTicks
|
300
|
+
{ box: tc.boxColor, container: tc.containerBackgroundColor },
|
301
|
+
{ hideTicks: tc.hideTicks, hideContainer: false }
|
310
302
|
)
|
311
303
|
);
|
312
304
|
if (!options.singleDirection) {
|
@@ -314,8 +306,8 @@ function thruster(thrust, setpoint, state, options) {
|
|
314
306
|
thrusterBottom(
|
315
307
|
height,
|
316
308
|
Math.max(-thrust, 0),
|
317
|
-
{ box: boxColor, container: containerBackgroundColor },
|
318
|
-
hideTicks
|
309
|
+
{ box: tc.boxColor, container: tc.containerBackgroundColor },
|
310
|
+
{ hideTicks: tc.hideTicks, hideContainer: false }
|
319
311
|
)
|
320
312
|
);
|
321
313
|
}
|
@@ -328,12 +320,13 @@ function thruster(thrust, setpoint, state, options) {
|
|
328
320
|
setpoint,
|
329
321
|
setpointAtZero,
|
330
322
|
{
|
331
|
-
fill: setPointColor,
|
323
|
+
fill: tc.setPointColor,
|
332
324
|
stroke: "var(--border-silhouette-color)"
|
333
325
|
},
|
334
326
|
{
|
335
327
|
inCommand: state === InstrumentState.inCommand,
|
336
|
-
singleSided: options.singleSided
|
328
|
+
singleSided: options.singleSided,
|
329
|
+
narrow: options.narrow
|
337
330
|
}
|
338
331
|
)
|
339
332
|
);
|
@@ -341,7 +334,7 @@ function thruster(thrust, setpoint, state, options) {
|
|
341
334
|
if (options.tunnel) {
|
342
335
|
return svg`
|
343
336
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-160 -64 320 128" x="-160" y="-64">
|
344
|
-
<g transform="rotate(90)">
|
337
|
+
<g transform="rotate(-90)">
|
345
338
|
${thrusterSvg}
|
346
339
|
</g>
|
347
340
|
</svg>`;
|
@@ -352,7 +345,7 @@ function thruster(thrust, setpoint, state, options) {
|
|
352
345
|
viewBox = "-80 -300 160 320";
|
353
346
|
y = -320;
|
354
347
|
}
|
355
|
-
const top = topPropeller(height, arrowColor, options.topPropeller);
|
348
|
+
const top = topPropeller(height, tc.arrowColor, options.topPropeller);
|
356
349
|
const bottom = bottomPropeller(
|
357
350
|
options.singleDirectionHalfSize ? 0.5 : height,
|
358
351
|
options.bottomPropeller
|
@@ -366,8 +359,79 @@ function thruster(thrust, setpoint, state, options) {
|
|
366
359
|
`;
|
367
360
|
}
|
368
361
|
}
|
362
|
+
function convertThrustAdvices(advices, thrust) {
|
363
|
+
const rawAdvices = advices.map((a) => {
|
364
|
+
const triggered = thrust >= a.min && thrust <= a.max;
|
365
|
+
let state;
|
366
|
+
if (triggered) {
|
367
|
+
state = AdviceState.triggered;
|
368
|
+
} else if (a.hinted) {
|
369
|
+
state = AdviceState.hinted;
|
370
|
+
} else {
|
371
|
+
state = AdviceState.regular;
|
372
|
+
}
|
373
|
+
return {
|
374
|
+
min: a.min,
|
375
|
+
max: a.max,
|
376
|
+
type: a.type,
|
377
|
+
state,
|
378
|
+
hinted: a.hinted
|
379
|
+
};
|
380
|
+
});
|
381
|
+
const topAdvices = rawAdvices.filter((a) => a.min >= 0);
|
382
|
+
const bottomAdvices = rawAdvices.filter((a) => a.max <= 0).map((a) => ({ ...a, min: -a.max, max: -a.min }));
|
383
|
+
return { topAdvices, bottomAdvices };
|
384
|
+
}
|
385
|
+
function thrusterColors(options, state) {
|
386
|
+
let boxColor = "var(--instrument-enhanced-secondary-color)";
|
387
|
+
let setPointColor = "var(--instrument-enhanced-primary-color)";
|
388
|
+
let arrowColor = "var(--instrument-regular-secondary-color)";
|
389
|
+
let containerBackgroundColor = "var(--instrument-frame-primary-color)";
|
390
|
+
let zeroLineColor = "var(--instrument-enhanced-secondary-color)";
|
391
|
+
let hideTicks = false;
|
392
|
+
if (options.atSetpoint) {
|
393
|
+
setPointColor = boxColor;
|
394
|
+
}
|
395
|
+
if (state === InstrumentState.active) {
|
396
|
+
boxColor = "var(--instrument-regular-secondary-color)";
|
397
|
+
zeroLineColor = "var(--instrument-regular-secondary-color)";
|
398
|
+
setPointColor = "var(--instrument-regular-primary-color)";
|
399
|
+
arrowColor = "var(--instrument-regular-secondary-color)";
|
400
|
+
if (options.atSetpoint) {
|
401
|
+
setPointColor = boxColor;
|
402
|
+
}
|
403
|
+
} else if (state === InstrumentState.loading) {
|
404
|
+
boxColor = "transparent";
|
405
|
+
setPointColor = "var(--instrument-frame-tertiary-color)";
|
406
|
+
zeroLineColor = "var(--instrument-frame-tertiary-color)";
|
407
|
+
arrowColor = "var(--instrument-regular-secondary-color)";
|
408
|
+
hideTicks = true;
|
409
|
+
} else if (state === InstrumentState.off) {
|
410
|
+
boxColor = "transparent";
|
411
|
+
setPointColor = "var(--instrument-frame-tertiary-color)";
|
412
|
+
arrowColor = "var(--instrument-frame-tertiary-color)";
|
413
|
+
zeroLineColor = "var(--instrument-frame-tertiary-color)";
|
414
|
+
hideTicks = true;
|
415
|
+
containerBackgroundColor = "transparent";
|
416
|
+
}
|
417
|
+
return {
|
418
|
+
zeroLineColor,
|
419
|
+
boxColor,
|
420
|
+
containerBackgroundColor,
|
421
|
+
hideTicks,
|
422
|
+
setPointColor,
|
423
|
+
arrowColor
|
424
|
+
};
|
425
|
+
}
|
369
426
|
export {
|
370
427
|
ObcThruster,
|
371
|
-
|
428
|
+
atSetpoint,
|
429
|
+
convertThrustAdvices,
|
430
|
+
setpointSvg,
|
431
|
+
thruster,
|
432
|
+
thrusterBottom,
|
433
|
+
thrusterColors,
|
434
|
+
thrusterTop,
|
435
|
+
thrusterTopSingleSided
|
372
436
|
};
|
373
437
|
//# sourceMappingURL=thruster.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"thruster.js","sources":["../../../src/navigation-instruments/thruster/thruster.ts"],"sourcesContent":["import {LitElement, svg, html, css} from 'lit';\nimport {customElement, property} from 'lit/decorators.js';\nimport {InstrumentState} from '../types';\nimport {LinearAdvice, LinearAdviceRaw, renderAdvice} from './advice';\nimport {AdviceState} from '../watch/advice';\nimport {TickmarkStyle} from '../watch/tickmark';\nimport {singleSidedTickmark} from './tickmark';\nimport {PropellerType, bottomPropeller, topPropeller} from './propeller';\n\n/**\n * @element obc-thruster\n *\n * @prop {number} thrust - The thrust of the thruster in percent (-100 - +100)\n * @prop {boolean} touching - Highlight the thruster when the lever is being touched\n */\n@customElement('obc-thruster')\nexport class ObcThruster extends LitElement {\n @property({type: Number}) thrust: number = 0;\n @property({type: Number}) setpoint: number | undefined;\n @property({type: Boolean}) touching: boolean = false;\n @property({type: Boolean}) atSetpoint: boolean = false;\n @property({type: Boolean}) disableAutoAtSetpoint: boolean = false;\n @property({type: Number}) autoAtSetpointDeadband: number = 1;\n @property({type: Number}) setpointAtZeroDeadband: number = 0.5;\n @property({type: String}) state: InstrumentState = InstrumentState.inCommand;\n @property({type: Boolean}) tunnel: boolean = false;\n @property({type: Boolean}) singleSided: boolean = false;\n @property({type: Boolean}) singleDirection: boolean = false;\n @property({type: Boolean}) singleDirectionHalfSize: boolean = false;\n @property({type: Array}) advices: LinearAdvice[] = [];\n @property({type: String}) topPropeller: PropellerType = PropellerType.none;\n @property({type: String}) bottomPropeller: PropellerType = PropellerType.none;\n\n override render() {\n return html`<div class=\"container\">\n ${thruster(this.thrust, this.setpoint, this.state, {\n atSetpoint: this.atSetpoint,\n tunnel: this.tunnel,\n setpointAtZeroDeadband: this.setpointAtZeroDeadband,\n autoAtSetpoint: !this.disableAutoAtSetpoint,\n autoSetpointDeadband: this.autoAtSetpointDeadband,\n touching: this.touching,\n singleSided: this.singleSided,\n advices: this.advices,\n singleDirection: this.singleDirection,\n singleDirectionHalfSize: this.singleDirectionHalfSize,\n topPropeller: this.topPropeller,\n bottomPropeller: this.bottomPropeller,\n })}\n </div>`;\n }\n\n static override styles = css`\n .container {\n height: 100%;\n width: 100%;\n }\n\n .container > svg {\n height: 100%;\n width: 100%;\n }\n `;\n}\n\nfunction thrusterTop(\n height: number,\n value: number,\n colors: {box: string; container: string},\n hideTicks: boolean\n) {\n const container = svg`\n <path transform=\"translate(0 -2)\" d=\"M -44 0 v -${height - 8} a 8 8 0 0 1 8 -8 h 72 a 8 8 0 0 1 8 8 V 0 Z\" fill=${colors.container} stroke=\"var(--instrument-frame-tertiary-color)\" vector-effect=\"non-scaling-stroke\"/>\n `;\n const track = svg`<rect width=\"40\" height=${height} x=\"-20\" y=${-2 - height} fill=\"var(--instrument-frame-secondary-color)\" stroke=\"var(--instrument-frame-tertiary-color)\" vector-effect=\"non-scaling-stroke\"/>`;\n\n const tickmarks = [];\n\n const nTicks = 2;\n const delta = height / nTicks;\n if (!hideTicks) {\n for (let i = 1; i < nTicks; i++) {\n tickmarks.push(\n svg`<line x1=\"-24\" x2=\"-44\" y1=${-i * delta - 2} y2=${\n -i * delta - 2\n } stroke=\"var(--instrument-frame-tertiary-color)\" stroke-width=\"1\" vector-effect=\"non-scaling-stroke\"/>`\n );\n tickmarks.push(\n svg`<line x1=\"24\" x2=\"44\" y1=${-i * delta - 2} y2=${\n -i * delta - 2\n } stroke=\"var(--instrument-frame-tertiary-color)\" stroke-width=\"1\" vector-effect=\"non-scaling-stroke\"/>`\n );\n }\n }\n\n const barHeight = (height * value) / 100;\n const barY = -2 - barHeight;\n const bar = svg`<rect width=\"40\" height=${barHeight} x=\"-20\" y=${barY} fill=${colors.box} stroke=${colors.box} vector-effect=\"non-scaling-stroke\"/>`;\n\n return [container, track, tickmarks, bar];\n}\n\nfunction thrusterTopSingleSided(\n height: number,\n value: number,\n colors: {box: string; container: string},\n hideTicks: boolean,\n advice: LinearAdviceRaw[],\n flipAdicePattern: boolean = false\n) {\n const container = svg`\n <path transform=\"translate(0 -2)\" d=\"M -32 0 v -${height - 8} a 8 8 0 0 1 8 -8 h 48 a 8 8 0 0 1 8 8 V 0 Z\" fill=${colors.container} stroke=\"var(--instrument-frame-tertiary-color)\" vector-effect=\"non-scaling-stroke\"/>\n `;\n const track = svg`\n <path transform=\"translate(0 -2)\" d=\"M -32 0 v -${height - 8} a 8 8 0 0 1 8 -8 h 32 V 0 Z\" fill=\"var(--instrument-frame-secondary-color)\" stroke=\"var(--instrument-frame-tertiary-color)\" vector-effect=\"non-scaling-stroke\"/>\n `;\n\n const tickmarks = hideTicks\n ? []\n : [singleSidedTickmark(height, 50, TickmarkStyle.hinted)];\n\n const barHeight = (height * value) / 100;\n const barY = -2 - barHeight;\n const maskId = flipAdicePattern ? 'thrusterBarMask1' : 'thrusterBarMask2';\n const bar = svg`\n <defs>\n <mask id=${maskId}>\n <path transform=\"translate(0 -2)\" d=\"M -32 0 v -${height - 8} a 8 8 0 0 1 8 -8 h 48 a 8 8 0 0 1 8 8 V 0 Z\" fill=\"white\" stroke=\"white\" vector-effect=\"non-scaling-stroke\"/>\n </defs>\n <rect mask=\"url(#${maskId})\" width=\"40\" height=${barHeight} x=\"-32\" y=${barY} fill=${colors.box} stroke=${colors.box} vector-effect=\"non-scaling-stroke\"/>`;\n const advicesSvg = advice.map((a) =>\n renderAdvice(height, a, flipAdicePattern)\n );\n\n return [container, track, tickmarks, bar, advicesSvg];\n}\n\nfunction thrusterBottom(\n height: number,\n value: number,\n colors: {box: string; container: string},\n hideTicks: boolean\n) {\n const container = svg`\n <g transform=\"rotate(180)\">\n ${thrusterTop(height, value, colors, hideTicks)}\n </g>\n `;\n return container;\n}\n\nfunction thrusterBottomSingleSided(\n height: number,\n value: number,\n colors: {box: string; container: string},\n hideTicks: boolean,\n advices: LinearAdviceRaw[]\n) {\n const container = svg`\n <g transform=\"rotate(180) scale(-1,1)\">\n ${thrusterTopSingleSided(height, value, colors, hideTicks, advices, true)}\n </g>\n `;\n return container;\n}\n\nfunction setpointSvg(\n height: number,\n value: number,\n setpointAtZero: boolean,\n colors: {fill: string; stroke: string},\n options: {\n inCommand: boolean;\n singleSided: boolean;\n }\n) {\n const y = -(setpointAtZero\n ? 0\n : Math.sign(value) * ((height * Math.abs(value)) / 100 + 2));\n const extra = options.singleSided ? -12 : 0;\n let path;\n if (options.inCommand) {\n path =\n 'M23.5119 8C24.6981 6.35191 23.5696 4 21.5926 4L2.39959 4C0.422598 4 -0.705911 6.35191 0.480283 8L11.9961 24L23.5119 8Z';\n } else {\n path =\n 'M18.5836 8L5.4086 8L11.9961 17.1526L18.5836 8ZM23.5119 8C24.6981 6.35191 23.5696 4 21.5926 4L2.39959 4C0.422598 4 -0.705911 6.35191 0.480283 8L11.9961 24L23.5119 8Z';\n }\n return svg`\n <defs>\n <g id=\"thrusterSetpoint\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\" transform=\"translate(24 -12) rotate(90)\" d=${path} vector-effect=\"non-scaling-stroke\"/>\n </g>\n <mask id=\"thrusterSetpointMask\">\n <rect x=\"-20\" y=\"-20\" width=\"50\" height=\"50\" fill=\"white\" />\n <use href=\"#thrusterSetpoint\" fill=\"black\" />\n </mask>\n </defs>\n <g transform=\"translate(0 ${y})\">\n <use href=\"#thrusterSetpoint\" fill=${colors.fill} stroke=\"none\" transform=\"translate(${28 + extra} 0)\"/>\n <use href=\"#thrusterSetpoint\" mask=\"url(#thrusterSetpointMask)\" transform=\"translate(${28 + extra} 0)\" fill=\"none\" stroke=${colors.stroke} stroke-width=\"2\" stroke-linejoin=\"round\" vector-effect=\"non-scaling-stroke\"/>\n ${\n options.singleSided\n ? null\n : svg`\n <use href=\"#thrusterSetpoint\" transform=\"rotate(180) translate(28 0)\" fill=${colors.fill} stroke=\"none\"/>\n <use href=\"#thrusterSetpoint\" transform=\"rotate(180) translate(28 0)\" mask=\"url(#thrusterSetpointMask)\" fill=\"none\" stroke=${colors.stroke} stroke-width=\"2\" stroke-linejoin=\"round\" vector-effect=\"non-scaling-stroke\"/>\n `\n }\n </g>\n `;\n}\n\nexport function thruster(\n thrust: number,\n setpoint: number | undefined,\n state: InstrumentState,\n options: {\n atSetpoint: boolean;\n tunnel: boolean;\n singleSided: boolean;\n singleDirection: boolean;\n singleDirectionHalfSize: boolean;\n setpointAtZeroDeadband: number;\n autoAtSetpoint: boolean;\n autoSetpointDeadband: number;\n touching: boolean;\n advices: LinearAdvice[];\n topPropeller: PropellerType;\n bottomPropeller: PropellerType;\n }\n) {\n if (!options.singleSided && options.advices.length > 0) {\n throw new Error('Double sided thruster does not support advice');\n }\n\n if (options.autoAtSetpoint && setpoint !== undefined) {\n options.atSetpoint =\n Math.abs(thrust - setpoint) < options.autoSetpointDeadband;\n }\n\n if (options.touching) {\n options.atSetpoint = false;\n }\n\n let boxColor = 'var(--instrument-enhanced-secondary-color)';\n let setPointColor = 'var(--instrument-enhanced-primary-color)';\n let arrowColor = 'var(--instrument-regular-secondary-color)';\n let containerBackgroundColor = 'var(--instrument-frame-primary-color)';\n let zeroLineColor = 'var(--instrument-enhanced-secondary-color)';\n let hideTicks = false;\n if (options.atSetpoint) {\n setPointColor = boxColor;\n }\n if (state === InstrumentState.active) {\n boxColor = 'var(--instrument-regular-secondary-color)';\n zeroLineColor = 'var(--instrument-regular-secondary-color)';\n setPointColor = 'var(--instrument-regular-primary-color)';\n arrowColor = 'var(--instrument-regular-secondary-color)';\n if (options.atSetpoint) {\n setPointColor = boxColor;\n }\n } else if (state === InstrumentState.loading) {\n boxColor = 'transparent';\n setPointColor = 'var(--instrument-frame-tertiary-color)';\n zeroLineColor = 'var(--instrument-frame-tertiary-color)';\n arrowColor = 'var(--instrument-regular-secondary-color)';\n thrust = 0;\n hideTicks = true;\n if (setpoint !== undefined) {\n setpoint = 0;\n }\n } else if (state === InstrumentState.off) {\n boxColor = 'transparent';\n setPointColor = 'var(--instrument-frame-tertiary-color)';\n arrowColor = 'var(--instrument-frame-tertiary-color)';\n zeroLineColor = 'var(--instrument-frame-tertiary-color)';\n thrust = 0;\n hideTicks = true;\n containerBackgroundColor = 'transparent';\n if (setpoint !== undefined) {\n setpoint = 0;\n }\n }\n\n const centerLine = options.singleSided\n ? svg`<rect x=\"-32\" y=\"-2\" width=\"64\" height=\"4\" stroke-width=\"1\" fill=${zeroLineColor} stroke=${zeroLineColor} vector-effect=\"non-scaling-stroke\"/>`\n : svg`\n <rect x=\"-44\" y=\"-2\" width=\"88\" height=\"4\" stroke-width=\"1\" fill=${zeroLineColor} stroke=${zeroLineColor} vector-effect=\"non-scaling-stroke\"/>\n `;\n\n const setpointAtZero =\n Math.abs(setpoint || 0) < options.setpointAtZeroDeadband;\n\n const advices: LinearAdviceRaw[] = options.advices.map((a) => {\n const triggered = thrust >= a.min && thrust <= a.max;\n let state: AdviceState;\n if (triggered) {\n state = AdviceState.triggered;\n } else if (a.hinted) {\n state = AdviceState.hinted;\n } else {\n state = AdviceState.regular;\n }\n return {\n min: a.min,\n max: a.max,\n type: a.type,\n state,\n };\n });\n\n const topAdvices = advices.filter((a) => a.min >= 0);\n const bottomAdvices = advices\n .filter((a) => a.max <= 0)\n .map((a) => ({...a, min: -a.max, max: -a.min}));\n\n const thrusterSvg = [];\n const baseheight = options.topPropeller === PropellerType.none ? 134 : 106;\n const height = options.singleDirection ? baseheight * 2 : baseheight;\n if (options.singleSided) {\n thrusterSvg.push(\n thrusterTopSingleSided(\n height,\n Math.max(thrust, 0),\n {box: boxColor, container: containerBackgroundColor},\n hideTicks,\n topAdvices\n )\n );\n if (!(options.singleDirection || options.singleDirectionHalfSize)) {\n thrusterSvg.push(\n thrusterBottomSingleSided(\n height,\n Math.max(-thrust, 0),\n {box: boxColor, container: containerBackgroundColor},\n hideTicks,\n bottomAdvices\n )\n );\n }\n thrusterSvg.push(centerLine);\n } else {\n thrusterSvg.push(\n thrusterTop(\n height,\n Math.max(thrust, 0),\n {box: boxColor, container: containerBackgroundColor},\n hideTicks\n )\n );\n if (!options.singleDirection) {\n thrusterSvg.push(\n thrusterBottom(\n height,\n Math.max(-thrust, 0),\n {box: boxColor, container: containerBackgroundColor},\n hideTicks\n )\n );\n }\n thrusterSvg.push(centerLine);\n }\n if (setpoint !== undefined) {\n thrusterSvg.push(\n setpointSvg(\n height,\n setpoint,\n setpointAtZero,\n {\n fill: setPointColor,\n stroke: 'var(--border-silhouette-color)',\n },\n {\n inCommand: state === InstrumentState.inCommand,\n singleSided: options.singleSided,\n }\n )\n );\n }\n\n if (options.tunnel) {\n return svg`\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"-160 -64 320 128\" x=\"-160\" y=\"-64\">\n <g transform=\"rotate(90)\">\n ${thrusterSvg}\n </g>\n </svg>`;\n } else {\n let viewBox = '-80 -160 160 320';\n let y = -160;\n if (options.singleDirection) {\n viewBox = '-80 -300 160 320';\n y = -320;\n }\n const top = topPropeller(height, arrowColor, options.topPropeller);\n const bottom = bottomPropeller(\n options.singleDirectionHalfSize ? 0.5 : height,\n options.bottomPropeller\n );\n return svg`\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=${viewBox} x=\"-80\" y=${y} width=\"160\" height=\"320\">\n ${top}\n ${bottom}\n ${thrusterSvg}\n </svg>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-thruster': ObcThruster;\n }\n}\n"],"names":["state"],"mappings":"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"}
|
1
|
+
{"version":3,"file":"thruster.js","sources":["../../../src/navigation-instruments/thruster/thruster.ts"],"sourcesContent":["import {LitElement, svg, html, css, nothing} from 'lit';\nimport {customElement, property} from 'lit/decorators.js';\nimport {InstrumentState} from '../types';\nimport {LinearAdvice, LinearAdviceRaw, renderAdvice} from './advice';\nimport {AdviceState} from '../watch/advice';\nimport {TickmarkStyle} from '../watch/tickmark';\nimport {singleSidedTickmark} from './tickmark';\nimport {PropellerType, bottomPropeller, topPropeller} from './propeller';\n\n/**\n * @element obc-thruster\n *\n * @prop {number} thrust - The thrust of the thruster in percent (-100 - +100)\n * @prop {boolean} touching - Highlight the thruster when the lever is being touched\n */\n@customElement('obc-thruster')\nexport class ObcThruster extends LitElement {\n @property({type: Number}) thrust: number = 0;\n @property({type: Number}) setpoint: number | undefined;\n @property({type: Boolean}) touching: boolean = false;\n @property({type: Boolean}) atSetpoint: boolean = false;\n @property({type: Boolean}) disableAutoAtSetpoint: boolean = false;\n @property({type: Number}) autoAtSetpointDeadband: number = 1;\n @property({type: Number}) setpointAtZeroDeadband: number = 0.5;\n @property({type: String}) state: InstrumentState = InstrumentState.inCommand;\n @property({type: Boolean}) tunnel: boolean = false;\n @property({type: Boolean}) singleSided: boolean = false;\n @property({type: Boolean}) singleDirection: boolean = false;\n @property({type: Boolean}) singleDirectionHalfSize: boolean = false;\n @property({type: Array}) advices: LinearAdvice[] = [];\n @property({type: String}) topPropeller: PropellerType = PropellerType.none;\n @property({type: String}) bottomPropeller: PropellerType = PropellerType.none;\n\n override render() {\n return html`<div class=\"container\">\n ${thruster(this.thrust, this.setpoint, this.state, {\n atSetpoint: this.atSetpoint,\n tunnel: this.tunnel,\n setpointAtZeroDeadband: this.setpointAtZeroDeadband,\n autoAtSetpoint: !this.disableAutoAtSetpoint,\n autoSetpointDeadband: this.autoAtSetpointDeadband,\n touching: this.touching,\n singleSided: this.singleSided,\n advices: this.advices,\n singleDirection: this.singleDirection,\n singleDirectionHalfSize: this.singleDirectionHalfSize,\n topPropeller: this.topPropeller,\n bottomPropeller: this.bottomPropeller,\n narrow: !this.tunnel,\n })}\n </div>`;\n }\n\n static override styles = css`\n .container {\n height: 100%;\n width: 100%;\n }\n\n .container > svg {\n height: 100%;\n width: 100%;\n }\n `;\n}\n\nexport function thrusterTop(\n height: number,\n value: number,\n colors: {box: string; container: string},\n options: {hideTicks: boolean; hideContainer: boolean}\n) {\n const container = svg`\n <path transform=\"translate(0 -2)\" d=\"M -44 0 v -${height - 8} a 8 8 0 0 1 8 -8 h 72 a 8 8 0 0 1 8 8 V 0 Z\" fill=${colors.container} stroke=\"var(--instrument-frame-tertiary-color)\" vector-effect=\"non-scaling-stroke\"/>\n `;\n const track = svg`<rect width=\"40\" height=${height} x=\"-20\" y=${-2 - height} fill=\"var(--instrument-frame-secondary-color)\" stroke=\"var(--instrument-frame-tertiary-color)\" vector-effect=\"non-scaling-stroke\"/>`;\n\n const tickmarks = [];\n\n const nTicks = 2;\n const delta = height / nTicks;\n if (!options.hideTicks) {\n for (let i = 1; i < nTicks; i++) {\n tickmarks.push(\n svg`<line x1=\"-24\" x2=\"-44\" y1=${-i * delta - 2} y2=${\n -i * delta - 2\n } stroke=\"var(--instrument-frame-tertiary-color)\" stroke-width=\"1\" vector-effect=\"non-scaling-stroke\"/>`\n );\n tickmarks.push(\n svg`<line x1=\"24\" x2=\"44\" y1=${-i * delta - 2} y2=${\n -i * delta - 2\n } stroke=\"var(--instrument-frame-tertiary-color)\" stroke-width=\"1\" vector-effect=\"non-scaling-stroke\"/>`\n );\n }\n }\n\n const barHeight = (height * value) / 100;\n const barY = -2 - barHeight;\n const bar = svg`<rect width=\"40\" height=${barHeight} x=\"-20\" y=${barY} fill=${colors.box} stroke=${colors.box} vector-effect=\"non-scaling-stroke\"/>`;\n if (options.hideContainer) {\n return [track, tickmarks, bar];\n } else {\n return [container, track, tickmarks, bar];\n }\n}\n\nexport function thrusterTopSingleSided(\n height: number,\n value: number,\n colors: {box: string; container: string},\n options: {\n hideTicks: boolean;\n flipAdicePattern: boolean;\n hideContainer: boolean;\n narrow: boolean;\n },\n advice: LinearAdviceRaw[]\n) {\n const container = options.narrow\n ? svg`\n <path transform=\"translate(0 -2)\" d=\"M -32 0 v -${height - 8} a 8 8 0 0 1 8 -8 h 48 a 8 8 0 0 1 8 8 V 0 Z\" fill=${colors.container} stroke=\"var(--instrument-frame-tertiary-color)\" vector-effect=\"non-scaling-stroke\"/>\n `\n : svg`\n <path transform=\"translate(0 -2)\" d=\"M -40 0 v -${height - 8} a 8 8 0 0 1 8 -8 h 56 a 8 8 0 0 1 8 8 V 0 Z\" fill=${colors.container} stroke=\"var(--instrument-frame-tertiary-color)\" vector-effect=\"non-scaling-stroke\"/>\n `;\n const track = options.narrow\n ? svg`\n <path transform=\"translate(0 -2)\" d=\"M -32 0 v -${height - 8} a 8 8 0 0 1 8 -8 h 32 V 0 Z\" fill=\"var(--instrument-frame-secondary-color)\" stroke=\"var(--instrument-frame-tertiary-color)\" vector-effect=\"non-scaling-stroke\"/>\n `\n : svg`\n <path transform=\"translate(0 -2)\" d=\"M -40 0 v -${height - 8} a 8 8 0 0 1 8 -8 h 40 V 0 Z\" fill=\"var(--instrument-frame-secondary-color)\" stroke=\"var(--instrument-frame-tertiary-color)\" vector-effect=\"non-scaling-stroke\"/>\n `;\n\n const tickmarks = options.hideTicks\n ? []\n : [singleSidedTickmark(height, 50, TickmarkStyle.hinted)];\n\n const barHeight = (height * value) / 100;\n const barWidth = options.narrow ? 40 : 48;\n const barX = options.narrow ? -32 : -40;\n const barY = -2 - barHeight;\n const maskId = options.flipAdicePattern\n ? 'thrusterBarMask1'\n : 'thrusterBarMask2';\n // The mask is used to clip the bar to the container shape\n const mask = options.hideContainer\n ? nothing\n : svg`\n <defs>\n <mask id=${maskId}>\n <path transform=\"translate(0 -2)\" d=\"M ${barX} 0 v -${height - 8} a 8 8 0 0 1 8 -8 h ${barWidth} V 0 Z\" fill=\"white\" stroke=\"white\" vector-effect=\"non-scaling-stroke\"/>\n </defs>`;\n const maskAttr = options.hideContainer ? '' : `mask=\"url(#${maskId})\"`;\n const bar = svg`\n ${mask}\n <rect ${maskAttr} width=${barWidth} height=${barHeight} x=${barX} y=${barY} fill=${colors.box} stroke=${colors.box} vector-effect=\"non-scaling-stroke\"/>`;\n const advicesSvg = advice.map((a) =>\n renderAdvice(height, a, options.flipAdicePattern)\n );\n const all = [tickmarks, bar, advicesSvg];\n if (!options.hideContainer) {\n all.splice(0, 0, [container, track]);\n }\n if (!options.narrow) {\n return svg`<g transform=\"translate(4 0)\">${all}</g>`;\n } else {\n return all;\n }\n}\n\nexport function thrusterBottom(\n height: number,\n value: number,\n colors: {box: string; container: string},\n options: {hideTicks: boolean; hideContainer: boolean}\n) {\n const container = svg`\n <g transform=\"rotate(180)\">\n ${thrusterTop(height, value, colors, options)}\n </g>\n `;\n return container;\n}\n\nfunction thrusterBottomSingleSided(\n height: number,\n value: number,\n colors: {box: string; container: string},\n options: {\n hideTicks: boolean;\n flipAdicePattern: boolean;\n hideContainer: boolean;\n narrow: boolean;\n },\n advice: LinearAdviceRaw[]\n) {\n const container = svg`\n <g transform=\"rotate(180) scale(-1,1)\">\n ${thrusterTopSingleSided(height, value, colors, {hideTicks: options.hideTicks, flipAdicePattern: options.flipAdicePattern, hideContainer: options.hideContainer, narrow: options.narrow}, advice)}\n </g>\n `;\n return container;\n}\n\nexport function setpointSvg(\n height: number,\n value: number,\n setpointAtZero: boolean,\n colors: {fill: string; stroke: string},\n options: {\n inCommand: boolean;\n singleSided: boolean;\n narrow: boolean;\n }\n) {\n const y = -(setpointAtZero\n ? 0\n : Math.sign(value) * ((height * Math.abs(value)) / 100 + 2));\n const extra = (options.singleSided ? -12 : 0) + (options.narrow ? 0 : 4);\n let path;\n if (options.inCommand) {\n path =\n 'M23.5119 8C24.6981 6.35191 23.5696 4 21.5926 4L2.39959 4C0.422598 4 -0.705911 6.35191 0.480283 8L11.9961 24L23.5119 8Z';\n } else {\n path =\n 'M18.5836 8L5.4086 8L11.9961 17.1526L18.5836 8ZM23.5119 8C24.6981 6.35191 23.5696 4 21.5926 4L2.39959 4C0.422598 4 -0.705911 6.35191 0.480283 8L11.9961 24L23.5119 8Z';\n }\n return svg`\n <defs>\n <g id=\"thrusterSetpoint\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\" transform=\"translate(24 -12) rotate(90)\" d=${path} vector-effect=\"non-scaling-stroke\"/>\n </g>\n <mask id=\"thrusterSetpointMask\">\n <rect x=\"-20\" y=\"-20\" width=\"50\" height=\"50\" fill=\"white\" />\n <use href=\"#thrusterSetpoint\" fill=\"black\" />\n </mask>\n </defs>\n <g transform=\"translate(0 ${y})\">\n <use href=\"#thrusterSetpoint\" fill=${colors.fill} stroke=\"none\" transform=\"translate(${28 + extra} 0)\"/>\n <use href=\"#thrusterSetpoint\" mask=\"url(#thrusterSetpointMask)\" transform=\"translate(${28 + extra} 0)\" fill=\"none\" stroke=${colors.stroke} stroke-width=\"2\" stroke-linejoin=\"round\" vector-effect=\"non-scaling-stroke\"/>\n ${\n options.singleSided\n ? null\n : svg`\n <use href=\"#thrusterSetpoint\" transform=\"rotate(180) translate(28 0)\" fill=${colors.fill} stroke=\"none\"/>\n <use href=\"#thrusterSetpoint\" transform=\"rotate(180) translate(28 0)\" mask=\"url(#thrusterSetpointMask)\" fill=\"none\" stroke=${colors.stroke} stroke-width=\"2\" stroke-linejoin=\"round\" vector-effect=\"non-scaling-stroke\"/>\n `\n }\n </g>\n `;\n}\n\nexport function atSetpoint(\n thrust: number,\n setpoint: number | undefined,\n options: {\n autoAtSetpoint: boolean;\n autoSetpointDeadband: number;\n touching: boolean;\n atSetpoint: boolean;\n }\n): boolean {\n if (options.touching) {\n return false;\n }\n\n if (options.autoAtSetpoint && setpoint !== undefined) {\n return Math.abs(thrust - setpoint) < options.autoSetpointDeadband;\n }\n\n return options.atSetpoint;\n}\n\nexport function thruster(\n thrust: number,\n setpoint: number | undefined,\n state: InstrumentState,\n options: {\n atSetpoint: boolean;\n tunnel: boolean;\n singleSided: boolean;\n singleDirection: boolean;\n singleDirectionHalfSize: boolean;\n setpointAtZeroDeadband: number;\n autoAtSetpoint: boolean;\n autoSetpointDeadband: number;\n touching: boolean;\n advices: LinearAdvice[];\n topPropeller: PropellerType;\n bottomPropeller: PropellerType;\n narrow: boolean;\n }\n) {\n if (options.tunnel) {\n thrust = -thrust;\n setpoint = setpoint === undefined ? undefined : -setpoint;\n }\n\n if (!options.singleSided && options.advices.length > 0) {\n throw new Error('Double sided thruster does not support advice');\n }\n\n options.atSetpoint = atSetpoint(thrust, setpoint, options);\n\n const tc = thrusterColors(options, state);\n\n let centerLine = svg`\n <rect x=\"-44\" y=\"-2\" width=\"88\" height=\"4\" stroke-width=\"1\" fill=${tc.zeroLineColor} stroke=${tc.zeroLineColor} vector-effect=\"non-scaling-stroke\"/>\n `;\n if (options.singleSided) {\n const width = options.narrow ? 64 : 72;\n const x = options.narrow ? -32 : -36;\n centerLine = svg`<rect x=${x} y=\"-2\" width=${width} height=\"4\" stroke-width=\"1\" fill=${tc.zeroLineColor} stroke=${tc.zeroLineColor} vector-effect=\"non-scaling-stroke\"/>`;\n }\n\n const setpointAtZero =\n Math.abs(setpoint || 0) < options.setpointAtZeroDeadband;\n\n const {topAdvices, bottomAdvices} = convertThrustAdvices(\n options.advices,\n thrust\n );\n\n const thrusterSvg = [];\n const baseheight = options.topPropeller === PropellerType.none ? 134 : 106;\n const height = options.singleDirection ? baseheight * 2 : baseheight;\n if (options.singleSided) {\n thrusterSvg.push(\n thrusterTopSingleSided(\n height,\n Math.max(thrust, 0),\n {box: tc.boxColor, container: tc.containerBackgroundColor},\n {\n hideTicks: tc.hideTicks,\n flipAdicePattern: false,\n hideContainer: false,\n narrow: options.narrow,\n },\n topAdvices\n )\n );\n if (!(options.singleDirection || options.singleDirectionHalfSize)) {\n thrusterSvg.push(\n thrusterBottomSingleSided(\n height,\n Math.max(-thrust, 0),\n {box: tc.boxColor, container: tc.containerBackgroundColor},\n {\n hideTicks: tc.hideTicks,\n flipAdicePattern: true,\n hideContainer: false,\n narrow: options.narrow,\n },\n bottomAdvices\n )\n );\n }\n thrusterSvg.push(centerLine);\n } else {\n thrusterSvg.push(\n thrusterTop(\n height,\n Math.max(thrust, 0),\n {box: tc.boxColor, container: tc.containerBackgroundColor},\n {hideTicks: tc.hideTicks, hideContainer: false}\n )\n );\n if (!options.singleDirection) {\n thrusterSvg.push(\n thrusterBottom(\n height,\n Math.max(-thrust, 0),\n {box: tc.boxColor, container: tc.containerBackgroundColor},\n {hideTicks: tc.hideTicks, hideContainer: false}\n )\n );\n }\n thrusterSvg.push(centerLine);\n }\n if (setpoint !== undefined) {\n thrusterSvg.push(\n setpointSvg(\n height,\n setpoint,\n setpointAtZero,\n {\n fill: tc.setPointColor,\n stroke: 'var(--border-silhouette-color)',\n },\n {\n inCommand: state === InstrumentState.inCommand,\n singleSided: options.singleSided,\n narrow: options.narrow,\n }\n )\n );\n }\n\n if (options.tunnel) {\n return svg`\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"-160 -64 320 128\" x=\"-160\" y=\"-64\">\n <g transform=\"rotate(-90)\">\n ${thrusterSvg}\n </g>\n </svg>`;\n } else {\n let viewBox = '-80 -160 160 320';\n let y = -160;\n if (options.singleDirection) {\n viewBox = '-80 -300 160 320';\n y = -320;\n }\n const top = topPropeller(height, tc.arrowColor, options.topPropeller);\n const bottom = bottomPropeller(\n options.singleDirectionHalfSize ? 0.5 : height,\n options.bottomPropeller\n );\n return svg`\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=${viewBox} x=\"-80\" y=${y} width=\"160\" height=\"320\">\n ${top}\n ${bottom}\n ${thrusterSvg}\n </svg>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-thruster': ObcThruster;\n }\n}\n\nexport function convertThrustAdvices(\n advices: LinearAdvice[],\n thrust: number\n): {topAdvices: LinearAdviceRaw[]; bottomAdvices: LinearAdviceRaw[]} {\n const rawAdvices: LinearAdviceRaw[] = advices.map((a) => {\n const triggered = thrust >= a.min && thrust <= a.max;\n let state: AdviceState;\n if (triggered) {\n state = AdviceState.triggered;\n } else if (a.hinted) {\n state = AdviceState.hinted;\n } else {\n state = AdviceState.regular;\n }\n return {\n min: a.min,\n max: a.max,\n type: a.type,\n state,\n hinted: a.hinted,\n };\n });\n\n const topAdvices = rawAdvices.filter((a) => a.min >= 0);\n const bottomAdvices = rawAdvices\n .filter((a) => a.max <= 0)\n .map((a) => ({...a, min: -a.max, max: -a.min}));\n return {topAdvices, bottomAdvices};\n}\n\nexport function thrusterColors(\n options: {atSetpoint: boolean; touching: boolean},\n state: InstrumentState\n) {\n let boxColor = 'var(--instrument-enhanced-secondary-color)';\n let setPointColor = 'var(--instrument-enhanced-primary-color)';\n let arrowColor = 'var(--instrument-regular-secondary-color)';\n let containerBackgroundColor = 'var(--instrument-frame-primary-color)';\n let zeroLineColor = 'var(--instrument-enhanced-secondary-color)';\n let hideTicks = false;\n if (options.atSetpoint) {\n setPointColor = boxColor;\n }\n if (state === InstrumentState.active) {\n boxColor = 'var(--instrument-regular-secondary-color)';\n zeroLineColor = 'var(--instrument-regular-secondary-color)';\n setPointColor = 'var(--instrument-regular-primary-color)';\n arrowColor = 'var(--instrument-regular-secondary-color)';\n if (options.atSetpoint) {\n setPointColor = boxColor;\n }\n } else if (state === InstrumentState.loading) {\n boxColor = 'transparent';\n setPointColor = 'var(--instrument-frame-tertiary-color)';\n zeroLineColor = 'var(--instrument-frame-tertiary-color)';\n arrowColor = 'var(--instrument-regular-secondary-color)';\n hideTicks = true;\n } else if (state === InstrumentState.off) {\n boxColor = 'transparent';\n setPointColor = 'var(--instrument-frame-tertiary-color)';\n arrowColor = 'var(--instrument-frame-tertiary-color)';\n zeroLineColor = 'var(--instrument-frame-tertiary-color)';\n hideTicks = true;\n containerBackgroundColor = 'transparent';\n }\n return {\n zeroLineColor,\n boxColor,\n containerBackgroundColor,\n hideTicks,\n setPointColor,\n arrowColor,\n };\n}\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
@@ -0,0 +1,54 @@
|
|
1
|
+
import type {Meta, StoryObj} from '@storybook/web-components';
|
2
|
+
import {ObcMainEngine} from './main-engine';
|
3
|
+
import './main-engine';
|
4
|
+
import {beta6Decorator, widthDecorator} from '../../storybook-util';
|
5
|
+
import {InstrumentState} from '../types';
|
6
|
+
|
7
|
+
const meta: Meta<typeof ObcMainEngine> = {
|
8
|
+
title: 'Navigation instruments/Main Engine',
|
9
|
+
tags: ['autodocs'],
|
10
|
+
component: 'obc-main-engine',
|
11
|
+
args: {
|
12
|
+
width: 352,
|
13
|
+
thrust: 50,
|
14
|
+
thrustSetpoint: 30,
|
15
|
+
speed: 50,
|
16
|
+
speedSetpoint: 30,
|
17
|
+
},
|
18
|
+
argTypes: {
|
19
|
+
width: {control: {type: 'range', min: 32, max: 1028, step: 1}},
|
20
|
+
thrust: {control: {type: 'range', min: -100, max: 100, step: 1}},
|
21
|
+
thrustSetpoint: {control: {type: 'range', min: -100, max: 100, step: 1}},
|
22
|
+
speed: {control: {type: 'range', min: 0, max: 100, step: 1}},
|
23
|
+
speedSetpoint: {control: {type: 'range', min: 0, max: 100, step: 1}},
|
24
|
+
state: {
|
25
|
+
options: Object.values(InstrumentState),
|
26
|
+
},
|
27
|
+
},
|
28
|
+
decorators: [widthDecorator, beta6Decorator],
|
29
|
+
} satisfies Meta<ObcMainEngine>;
|
30
|
+
|
31
|
+
export default meta;
|
32
|
+
type Story = StoryObj<ObcMainEngine>;
|
33
|
+
|
34
|
+
export const InCommand: Story = {
|
35
|
+
args: {
|
36
|
+
state: InstrumentState.inCommand,
|
37
|
+
},
|
38
|
+
};
|
39
|
+
|
40
|
+
export const Active: Story = {
|
41
|
+
args: {
|
42
|
+
state: InstrumentState.active,
|
43
|
+
},
|
44
|
+
};
|
45
|
+
|
46
|
+
export const Off: Story = {
|
47
|
+
args: {
|
48
|
+
state: InstrumentState.off,
|
49
|
+
speed: 0,
|
50
|
+
thrust: 0,
|
51
|
+
speedSetpoint: 0,
|
52
|
+
thrustSetpoint: 0,
|
53
|
+
},
|
54
|
+
};
|