@oicl/openbridge-webcomponents 0.0.15-dev-20240915195432 → 0.0.15-dev-20240916185711

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/__snapshots__/navigation-instruments-azimuth-thruster--in-command-at-setpoint-disable-auto-setpoint.png +0 -0
  2. package/__snapshots__/navigation-instruments-azimuth-thruster--in-command-at-setpoint.png +0 -0
  3. package/__snapshots__/navigation-instruments-azimuth-thruster--in-command.png +0 -0
  4. package/__snapshots__/navigation-instruments-azimuth-thruster--pod.png +0 -0
  5. package/__snapshots__/navigation-instruments-azimuth-thruster--single-direction-with-propeller.png +0 -0
  6. package/__snapshots__/navigation-instruments-azimuth-thruster--single-direction.png +0 -0
  7. package/__snapshots__/navigation-instruments-azimuth-thruster-labeled--large.png +0 -0
  8. package/__snapshots__/navigation-instruments-main-engine--active.png +0 -0
  9. package/__snapshots__/navigation-instruments-main-engine--in-command.png +0 -0
  10. package/__snapshots__/navigation-instruments-main-engine--off.png +0 -0
  11. package/__snapshots__/navigation-instruments-thruster--tunnel.png +0 -0
  12. package/custom-elements.json +570 -7
  13. package/dist/navigation-instruments/azimuth-thruster/azimuth-thruster.d.ts.map +1 -1
  14. package/dist/navigation-instruments/azimuth-thruster/azimuth-thruster.js +2 -1
  15. package/dist/navigation-instruments/azimuth-thruster/azimuth-thruster.js.map +1 -1
  16. package/dist/navigation-instruments/main-engine/main-engine.css.js +22 -0
  17. package/dist/navigation-instruments/main-engine/main-engine.css.js.map +1 -0
  18. package/dist/navigation-instruments/main-engine/main-engine.d.ts +29 -0
  19. package/dist/navigation-instruments/main-engine/main-engine.d.ts.map +1 -0
  20. package/dist/navigation-instruments/main-engine/main-engine.js +196 -0
  21. package/dist/navigation-instruments/main-engine/main-engine.js.map +1 -0
  22. package/dist/navigation-instruments/thruster/thruster.d.ts +54 -1
  23. package/dist/navigation-instruments/thruster/thruster.d.ts.map +1 -1
  24. package/dist/navigation-instruments/thruster/thruster.js +163 -99
  25. package/dist/navigation-instruments/thruster/thruster.js.map +1 -1
  26. package/package.json +1 -1
  27. package/src/navigation-instruments/azimuth-thruster/azimuth-thruster.ts +1 -0
  28. package/src/navigation-instruments/main-engine/main-engine.css +17 -0
  29. package/src/navigation-instruments/main-engine/main-engine.stories.ts +54 -0
  30. package/src/navigation-instruments/main-engine/main-engine.ts +160 -0
  31. package/src/navigation-instruments/thruster/thruster.stories.ts +1 -0
  32. package/src/navigation-instruments/thruster/thruster.ts +205 -113
  33. 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, hideTicks) {
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
- return [container, track, tickmarks, bar];
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, hideTicks, advice, flipAdicePattern = false) {
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 bar = svg`
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 -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"/>
154
- </defs>
155
- <rect mask="url(#${maskId})" width="40" height=${barHeight} x="-32" y=${barY} fill=${colors.box} stroke=${colors.box} vector-effect="non-scaling-stroke"/>`;
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
- return [container, track, tickmarks, bar, advicesSvg];
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, hideTicks) {
183
+ function thrusterBottom(height, value, colors, options) {
162
184
  const container = svg`
163
185
  <g transform="rotate(180)">
164
- ${thrusterTop(height, value, colors, hideTicks)}
186
+ ${thrusterTop(height, value, colors, options)}
165
187
  </g>
166
188
  `;
167
189
  return container;
168
190
  }
169
- function thrusterBottomSingleSided(height, value, colors, hideTicks, advices) {
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, advices, true)}
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 thruster(thrust, setpoint, state, options) {
207
- if (!options.singleSided && options.advices.length > 0) {
208
- throw new Error("Double sided thruster does not support advice");
228
+ function atSetpoint(thrust, setpoint, options) {
229
+ if (options.touching) {
230
+ return false;
209
231
  }
210
232
  if (options.autoAtSetpoint && setpoint !== void 0) {
211
- options.atSetpoint = Math.abs(thrust - setpoint) < options.autoSetpointDeadband;
212
- }
213
- if (options.touching) {
214
- options.atSetpoint = false;
233
+ return Math.abs(thrust - setpoint) < options.autoSetpointDeadband;
215
234
  }
216
- let boxColor = "var(--instrument-enhanced-secondary-color)";
217
- let setPointColor = "var(--instrument-enhanced-primary-color)";
218
- let arrowColor = "var(--instrument-regular-secondary-color)";
219
- let containerBackgroundColor = "var(--instrument-frame-primary-color)";
220
- let zeroLineColor = "var(--instrument-enhanced-secondary-color)";
221
- let hideTicks = false;
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 (state === InstrumentState.active) {
226
- boxColor = "var(--instrument-regular-secondary-color)";
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
- const centerLine = options.singleSided ? svg`<rect x="-32" y="-2" width="64" height="4" stroke-width="1" fill=${zeroLineColor} stroke=${zeroLineColor} vector-effect="non-scaling-stroke"/>` : svg`
256
- <rect x="-44" y="-2" width="88" height="4" stroke-width="1" fill=${zeroLineColor} stroke=${zeroLineColor} vector-effect="non-scaling-stroke"/>
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 advices = options.advices.map((a) => {
260
- const triggered = thrust >= a.min && thrust <= a.max;
261
- let state2;
262
- if (triggered) {
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
- hideTicks,
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
- hideTicks,
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
- thruster
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oicl/openbridge-webcomponents",
3
- "version": "0.0.15-dev-20240915195432",
3
+ "version": "0.0.15-dev-20240916185711",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -130,6 +130,7 @@ export class ObcAzimuthThruster extends LitElement {
130
130
  advices: this.thrustAdvices,
131
131
  topPropeller: this.topPropeller,
132
132
  bottomPropeller: this.bottomPropeller,
133
+ narrow: true,
133
134
  })}
134
135
  </svg>
135
136
  </g>
@@ -0,0 +1,17 @@
1
+ * {
2
+ box-sizing: border-box;
3
+ }
4
+
5
+ .container {
6
+ position: relative;
7
+ width: 100%;
8
+ height: 100%;
9
+ }
10
+
11
+ .container>* {
12
+ position: absolute;
13
+ top: 0;
14
+ left: 0;
15
+ width: 100%;
16
+ height: 100%;
17
+ }
@@ -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
+ };