@oicl/openbridge-webcomponents 2.0.0-next.111 → 2.0.0-next.113

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 (60) hide show
  1. package/bundle/openbridge-webcomponents.bundle.js +185 -29
  2. package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
  3. package/custom-elements.json +180 -21
  4. package/dist/building-blocks/readout-block/readout-block.d.ts +29 -5
  5. package/dist/building-blocks/readout-block/readout-block.d.ts.map +1 -1
  6. package/dist/building-blocks/readout-block/readout-block.js +21 -7
  7. package/dist/building-blocks/readout-block/readout-block.js.map +1 -1
  8. package/dist/navigation-instruments/compass/compass.d.ts +1 -1
  9. package/dist/navigation-instruments/compass/compass.d.ts.map +1 -1
  10. package/dist/navigation-instruments/compass/compass.js +1 -1
  11. package/dist/navigation-instruments/compass/compass.js.map +1 -1
  12. package/dist/navigation-instruments/current/current.d.ts +25 -0
  13. package/dist/navigation-instruments/current/current.d.ts.map +1 -1
  14. package/dist/navigation-instruments/current/current.js +25 -4
  15. package/dist/navigation-instruments/current/current.js.map +1 -1
  16. package/dist/navigation-instruments/heading/heading.js +1 -1
  17. package/dist/navigation-instruments/heading/heading.js.map +1 -1
  18. package/dist/navigation-instruments/pitch-roll-heave/pitch-roll-heave.d.ts +6 -0
  19. package/dist/navigation-instruments/pitch-roll-heave/pitch-roll-heave.d.ts.map +1 -1
  20. package/dist/navigation-instruments/pitch-roll-heave/pitch-roll-heave.js +8 -1
  21. package/dist/navigation-instruments/pitch-roll-heave/pitch-roll-heave.js.map +1 -1
  22. package/dist/navigation-instruments/rate-of-turn/rate-of-turn.d.ts +5 -2
  23. package/dist/navigation-instruments/rate-of-turn/rate-of-turn.d.ts.map +1 -1
  24. package/dist/navigation-instruments/rate-of-turn/rate-of-turn.js.map +1 -1
  25. package/dist/navigation-instruments/readout/readout-formatters.d.ts +31 -0
  26. package/dist/navigation-instruments/readout/readout-formatters.d.ts.map +1 -1
  27. package/dist/navigation-instruments/readout/readout-formatters.js +55 -1
  28. package/dist/navigation-instruments/readout/readout-formatters.js.map +1 -1
  29. package/dist/navigation-instruments/readout/readout.d.ts +26 -1
  30. package/dist/navigation-instruments/readout/readout.d.ts.map +1 -1
  31. package/dist/navigation-instruments/readout/readout.js +16 -3
  32. package/dist/navigation-instruments/readout/readout.js.map +1 -1
  33. package/dist/navigation-instruments/readout-list/readout-list.d.ts +6 -1
  34. package/dist/navigation-instruments/readout-list/readout-list.d.ts.map +1 -1
  35. package/dist/navigation-instruments/readout-list/readout-list.js +21 -4
  36. package/dist/navigation-instruments/readout-list/readout-list.js.map +1 -1
  37. package/dist/navigation-instruments/readout-list-item/readout-list-item.d.ts +26 -1
  38. package/dist/navigation-instruments/readout-list-item/readout-list-item.d.ts.map +1 -1
  39. package/dist/navigation-instruments/readout-list-item/readout-list-item.js +15 -3
  40. package/dist/navigation-instruments/readout-list-item/readout-list-item.js.map +1 -1
  41. package/dist/navigation-instruments/top-view-propulsion/top-view-propulsion.d.ts +6 -0
  42. package/dist/navigation-instruments/top-view-propulsion/top-view-propulsion.d.ts.map +1 -1
  43. package/dist/navigation-instruments/top-view-propulsion/top-view-propulsion.js +19 -4
  44. package/dist/navigation-instruments/top-view-propulsion/top-view-propulsion.js.map +1 -1
  45. package/dist/navigation-instruments/watch/environment.d.ts +8 -0
  46. package/dist/navigation-instruments/watch/environment.d.ts.map +1 -1
  47. package/dist/navigation-instruments/watch/environment.js +3 -0
  48. package/dist/navigation-instruments/watch/environment.js.map +1 -1
  49. package/dist/navigation-instruments/watch/force-pattern.d.ts +20 -2
  50. package/dist/navigation-instruments/watch/force-pattern.d.ts.map +1 -1
  51. package/dist/navigation-instruments/watch/force-pattern.js +12 -5
  52. package/dist/navigation-instruments/watch/force-pattern.js.map +1 -1
  53. package/dist/navigation-instruments/watch/watch.d.ts.map +1 -1
  54. package/dist/navigation-instruments/watch/watch.js +6 -4
  55. package/dist/navigation-instruments/watch/watch.js.map +1 -1
  56. package/dist/navigation-instruments/wind/wind.d.ts +5 -2
  57. package/dist/navigation-instruments/wind/wind.d.ts.map +1 -1
  58. package/dist/navigation-instruments/wind/wind.js +5 -1
  59. package/dist/navigation-instruments/wind/wind.js.map +1 -1
  60. package/package.json +1 -1
@@ -54698,6 +54698,8 @@ const WIND_SHAFT_BUCKETS = [
54698
54698
  100
54699
54699
  ];
54700
54700
  const WIND_ICON_SCALE = 2;
54701
+ const WIND_ICON_TIP_Y = 22.4453;
54702
+ const WIND_ICON_TIP_TO_BOX_INNER = (24 - WIND_ICON_TIP_Y) * WIND_ICON_SCALE;
54701
54703
  const windIconCache = /* @__PURE__ */ new Map();
54702
54704
  function getWindIconSvg(bucket) {
54703
54705
  const tagName = `obi-wind-true-${bucket}`;
@@ -55267,6 +55269,8 @@ function innerRingRadiusFor(type) {
55267
55269
  }
55268
55270
  }
55269
55271
  const RADIAL_SETPOINT_INWARD_ADJUST = 4;
55272
+ const CURRENT_ICON_OUTSIDE_RADIUS = OUTER_RING_RADIUS + 4;
55273
+ const WIND_ICON_OUTSIDE_RADIUS = CURRENT_ICON_OUTSIDE_RADIUS + WIND_ICON_TIP_TO_BOX_INNER;
55270
55274
  let ObcWatch = class extends i$4 {
55271
55275
  constructor() {
55272
55276
  super(...arguments);
@@ -55819,7 +55823,7 @@ let ObcWatch = class extends i$4 {
55819
55823
  );
55820
55824
  const advices = this.advices ? this.advices.map((a2) => renderAdvice$3(a2, rOff)) : A;
55821
55825
  const showNsweLabels = this.showLabels && !this._labelsHidden;
55822
- const showNorthArrow = this.northArrow && !this._labelsHidden;
55826
+ const showNorthArrow = this.northArrow;
55823
55827
  const insideLabels = this.tickmarksInside && showNsweLabels;
55824
55828
  const includeNorth = !this.northArrow;
55825
55829
  const labelPositions = showNsweLabels ? getLabelPositions({
@@ -55845,7 +55849,7 @@ let ObcWatch = class extends i$4 {
55845
55849
  const wind = this.windKnots != null && this.windFromDirectionDeg != null ? w`<g transform="scale(${this.scaleWindIcon})">${renderWind({
55846
55850
  windKnots: this.windKnots,
55847
55851
  fromDirectionDeg: this.windFromDirectionDeg,
55848
- radius: this.windSymbolRadius ?? 192,
55852
+ radius: this.windSymbolRadius ?? WIND_ICON_OUTSIDE_RADIUS,
55849
55853
  color: this.windColor
55850
55854
  })}</g>` : A;
55851
55855
  const current = this.current != null && this.currentFromDirectionDeg != null ? this.currentIconCentered ? renderCurrentCentered({
@@ -55856,7 +55860,7 @@ let ObcWatch = class extends i$4 {
55856
55860
  }) : renderCurrent({
55857
55861
  current: this.current,
55858
55862
  fromDirectionDeg: this.currentFromDirectionDeg,
55859
- radius: this.currentSymbolRadius ?? 192,
55863
+ radius: this.currentSymbolRadius ?? CURRENT_ICON_OUTSIDE_RADIUS,
55860
55864
  color: this.currentColor
55861
55865
  }) : A;
55862
55866
  return b`
@@ -57244,6 +57248,55 @@ __decorateClass$v_([
57244
57248
  ObiNotificationAdvice = __decorateClass$v_([
57245
57249
  customElement("obi-notification-advice")
57246
57250
  ], ObiNotificationAdvice);
57251
+ var ReadoutValueType = /* @__PURE__ */ ((ReadoutValueType2) => {
57252
+ ReadoutValueType2["number"] = "number";
57253
+ ReadoutValueType2["text"] = "text";
57254
+ return ReadoutValueType2;
57255
+ })(ReadoutValueType || {});
57256
+ const READOUT_VALUE_TYPES = Object.values(ReadoutValueType);
57257
+ function isReadoutValueType(value) {
57258
+ return typeof value === "string" && READOUT_VALUE_TYPES.includes(value);
57259
+ }
57260
+ function isBlank(value) {
57261
+ return value.trim() === "";
57262
+ }
57263
+ function assertReadoutValueType(tagName, value, valueType) {
57264
+ const resolved = valueType ?? "number";
57265
+ if (!isReadoutValueType(resolved)) {
57266
+ throw new TypeError(
57267
+ `<${tagName}>: valueType must be ${READOUT_VALUE_TYPES.map((t2) => `"${t2}"`).join(" or ")} (got ${JSON.stringify(valueType)}).`
57268
+ );
57269
+ }
57270
+ if (resolved !== "number" || typeof value !== "string" || isBlank(value)) {
57271
+ return;
57272
+ }
57273
+ if (Number.isFinite(Number(value))) {
57274
+ return;
57275
+ }
57276
+ throw new TypeError(
57277
+ `<${tagName}>: value must be a number when valueType is "number" (got ${JSON.stringify(value)}). Set valueType="text" to render text.`
57278
+ );
57279
+ }
57280
+ function resolveReadoutNumericValue(value, valueType) {
57281
+ if (valueType === "text" || value === null || value === void 0) {
57282
+ return void 0;
57283
+ }
57284
+ if (typeof value === "number") {
57285
+ return value;
57286
+ }
57287
+ if (isBlank(value)) {
57288
+ return void 0;
57289
+ }
57290
+ const parsed = Number(value);
57291
+ return Number.isFinite(parsed) ? parsed : void 0;
57292
+ }
57293
+ function resolveReadoutTextValue(value, valueType) {
57294
+ if (valueType !== "text" || value === null || value === void 0) {
57295
+ return void 0;
57296
+ }
57297
+ const text = typeof value === "number" ? String(value) : value;
57298
+ return isBlank(text) ? void 0 : text;
57299
+ }
57247
57300
  function dashedGenerator({
57248
57301
  showZeroPadding,
57249
57302
  minValueLength,
@@ -57309,6 +57362,7 @@ let ObcReadoutBlock = class extends i$4 {
57309
57362
  super(...arguments);
57310
57363
  this.variant = "value";
57311
57364
  this.value = null;
57365
+ this.valueType = ReadoutValueType.number;
57312
57366
  this.size = "small";
57313
57367
  this.enhanced = false;
57314
57368
  this.weight = ObcTextboxFontWeight.regular;
@@ -57415,14 +57469,23 @@ let ObcReadoutBlock = class extends i$4 {
57415
57469
  </span>
57416
57470
  `;
57417
57471
  }
57472
+ willUpdate(changed) {
57473
+ super.willUpdate(changed);
57474
+ assertReadoutValueType("obc-readout-block", this.value, this.valueType);
57475
+ }
57418
57476
  render() {
57419
57477
  const valueSize = this.resolvedValueSize;
57420
57478
  const formatOptions = this.numericFormatOptions;
57421
- const valueForFormat = this.value ?? void 0;
57422
- const text = this.off ? this.offText : formatNumericValue(valueForFormat, formatOptions);
57423
- const hintCount = this.off || !this.hintedZeros || valueForFormat === void 0 || valueForFormat < 0 ? 0 : Math.max(this.maxDigits - readoutFormattedInteger(text), 0);
57479
+ const isTextMode = this.valueType === ReadoutValueType.text;
57480
+ const valueForFormat = resolveReadoutNumericValue(
57481
+ this.value,
57482
+ this.valueType
57483
+ );
57484
+ const textValue = resolveReadoutTextValue(this.value, this.valueType);
57485
+ const text = this.off ? this.offText : isTextMode ? textValue ?? "-" : formatNumericValue(valueForFormat, formatOptions);
57486
+ const hintCount = this.off || isTextMode || !this.hintedZeros || valueForFormat === void 0 || valueForFormat < 0 ? 0 : Math.max(this.maxDigits - readoutFormattedInteger(text), 0);
57424
57487
  const hinted = hintCount > 0 ? "0".repeat(hintCount) : "";
57425
- const reserver = this.hintedZeros ? this.reserverText : this.widerReserver(this.spaceReserver, this.reserverText);
57488
+ const reserver = isTextMode ? this.spaceReserver ?? "" : this.hintedZeros ? this.reserverText : this.widerReserver(this.spaceReserver, this.reserverText);
57426
57489
  const block = b`
57427
57490
  <div
57428
57491
  class=${e$1({
@@ -57464,8 +57527,11 @@ __decorateClass$vZ([
57464
57527
  n$3({ type: String })
57465
57528
  ], ObcReadoutBlock.prototype, "variant", 2);
57466
57529
  __decorateClass$vZ([
57467
- n$3({ type: Number })
57530
+ n$3({ type: String })
57468
57531
  ], ObcReadoutBlock.prototype, "value", 2);
57532
+ __decorateClass$vZ([
57533
+ n$3({ type: String })
57534
+ ], ObcReadoutBlock.prototype, "valueType", 2);
57469
57535
  __decorateClass$vZ([
57470
57536
  n$3({ type: String })
57471
57537
  ], ObcReadoutBlock.prototype, "size", 2);
@@ -58999,6 +59065,7 @@ let ObcReadoutListItem = class extends i$4 {
58999
59065
  super(...arguments);
59000
59066
  this.hasValue = true;
59001
59067
  this.value = null;
59068
+ this.valueType = ReadoutValueType.number;
59002
59069
  this.off = false;
59003
59070
  this.offText = "OFF";
59004
59071
  this.hasSetpoint = false;
@@ -59050,7 +59117,7 @@ let ObcReadoutListItem = class extends i$4 {
59050
59117
  return false;
59051
59118
  }
59052
59119
  return isDisplayedAtSetpoint(
59053
- this.value,
59120
+ resolveReadoutNumericValue(this.value, this.valueType) ?? null,
59054
59121
  this.setpoint,
59055
59122
  this.numericFormatOptions(this.resolvedMaxDigits)
59056
59123
  );
@@ -59143,6 +59210,7 @@ let ObcReadoutListItem = class extends i$4 {
59143
59210
  exportparts="block, block-content, block-text, block-icon, degree"
59144
59211
  .variant=${config.variant}
59145
59212
  .value=${config.value ?? null}
59213
+ .valueType=${config.valueType ?? ReadoutValueType.number}
59146
59214
  .size=${this.resolvedSize}
59147
59215
  .valueSize=${config.valueSize}
59148
59216
  .enhanced=${config.enhanced}
@@ -59328,6 +59396,7 @@ let ObcReadoutListItem = class extends i$4 {
59328
59396
  ${this.hasValue ? this.renderBlock({
59329
59397
  variant: ReadoutBlockVariant.value,
59330
59398
  value: this.value,
59399
+ valueType: this.valueType,
59331
59400
  valueSize: this.valueSize,
59332
59401
  enhanced: this.rowEnhanced,
59333
59402
  weight: this.valueWeight,
@@ -59443,6 +59512,10 @@ let ObcReadoutListItem = class extends i$4 {
59443
59512
  </div>
59444
59513
  `;
59445
59514
  }
59515
+ willUpdate(changed) {
59516
+ super.willUpdate(changed);
59517
+ assertReadoutValueType("obc-readout-list-item", this.value, this.valueType);
59518
+ }
59446
59519
  updated(changed) {
59447
59520
  super.updated(changed);
59448
59521
  const firstUpdate = !this.hasCompletedFirstUpdate;
@@ -59523,8 +59596,11 @@ __decorateClass$vY([
59523
59596
  n$3({ type: Boolean, attribute: false })
59524
59597
  ], ObcReadoutListItem.prototype, "hasValue", 2);
59525
59598
  __decorateClass$vY([
59526
- n$3({ type: Number })
59599
+ n$3({ type: String })
59527
59600
  ], ObcReadoutListItem.prototype, "value", 2);
59601
+ __decorateClass$vY([
59602
+ n$3({ type: String })
59603
+ ], ObcReadoutListItem.prototype, "valueType", 2);
59528
59604
  __decorateClass$vY([
59529
59605
  n$3({ type: Boolean })
59530
59606
  ], ObcReadoutListItem.prototype, "off", 2);
@@ -64173,6 +64249,7 @@ let ObcReadout = class extends i$4 {
64173
64249
  super(...arguments);
64174
64250
  this.hasValue = true;
64175
64251
  this.value = null;
64252
+ this.valueType = ReadoutValueType.number;
64176
64253
  this.off = false;
64177
64254
  this.offText = "OFF";
64178
64255
  this.hasSetpoint = false;
@@ -64247,7 +64324,7 @@ let ObcReadout = class extends i$4 {
64247
64324
  return false;
64248
64325
  }
64249
64326
  return isDisplayedAtSetpoint(
64250
- this.value,
64327
+ resolveReadoutNumericValue(this.value, this.valueType) ?? null,
64251
64328
  this.setpoint,
64252
64329
  this.numericFormatOptions(this.resolvedMaxDigits)
64253
64330
  );
@@ -64349,6 +64426,7 @@ let ObcReadout = class extends i$4 {
64349
64426
  exportparts="block, block-content, block-text, block-icon, degree"
64350
64427
  .variant=${config.variant}
64351
64428
  .value=${config.value ?? null}
64429
+ .valueType=${config.valueType ?? ReadoutValueType.number}
64352
64430
  .size=${this.resolvedSize}
64353
64431
  .valueSize=${config.valueSize}
64354
64432
  .enhanced=${config.enhanced}
@@ -64489,6 +64567,7 @@ let ObcReadout = class extends i$4 {
64489
64567
  ${this.renderBlock({
64490
64568
  variant: ReadoutBlockVariant.value,
64491
64569
  value: this.value,
64570
+ valueType: this.valueType,
64492
64571
  valueSize: this.valueSize,
64493
64572
  enhanced: this.rowEnhanced,
64494
64573
  weight: this.valueWeight,
@@ -64767,6 +64846,7 @@ let ObcReadout = class extends i$4 {
64767
64846
  }) : b`${this.renderBlock({
64768
64847
  variant: ReadoutBlockVariant.value,
64769
64848
  value: this.value,
64849
+ valueType: this.valueType,
64770
64850
  valueSize: this.primarySize,
64771
64851
  enhanced: false,
64772
64852
  weight: this.valueWeight,
@@ -64824,6 +64904,10 @@ let ObcReadout = class extends i$4 {
64824
64904
  </div>
64825
64905
  `;
64826
64906
  }
64907
+ willUpdate(changed) {
64908
+ super.willUpdate(changed);
64909
+ assertReadoutValueType("obc-readout", this.value, this.valueType);
64910
+ }
64827
64911
  updated(changed) {
64828
64912
  super.updated(changed);
64829
64913
  if (changed.has("sourcePickerContentVisible")) {
@@ -64917,8 +65001,11 @@ __decorateClass$vH([
64917
65001
  n$3({ type: Boolean, attribute: false })
64918
65002
  ], ObcReadout.prototype, "hasValue", 2);
64919
65003
  __decorateClass$vH([
64920
- n$3({ type: Number })
65004
+ n$3({ type: String })
64921
65005
  ], ObcReadout.prototype, "value", 2);
65006
+ __decorateClass$vH([
65007
+ n$3({ type: String })
65008
+ ], ObcReadout.prototype, "valueType", 2);
64922
65009
  __decorateClass$vH([
64923
65010
  n$3({ type: Boolean })
64924
65011
  ], ObcReadout.prototype, "off", 2);
@@ -213112,7 +213199,7 @@ let ObcCompass = class extends i$4 {
213112
213199
  .tickmarksInside=${this.tickmarksInside}
213113
213200
  .crosshairEnabled=${true}
213114
213201
  .crosshairCenterCutout=${this.hasCenterReadouts}
213115
- .northArrow=${!frame.labelsHidden}
213202
+ .northArrow=${true}
213116
213203
  .angleSetpoint=${this.headingSetpoint ?? void 0}
213117
213204
  .newAngleSetpoint=${this.newHeadingSetpoint}
213118
213205
  .atAngleSetpoint=${this._headingSp.computeAtSetpoint(this.heading)}
@@ -213392,14 +213479,18 @@ function renderWindForcePattern(options) {
213392
213479
  function renderCurrentForcePattern(options) {
213393
213480
  const { fromDirectionDeg, radius, patternScale } = options;
213394
213481
  const color2 = options.color ?? DEFAULT_COLOR;
213395
- const tile = CURRENT_TILE * patternScale;
213482
+ const lengthScale = Number.isFinite(options.waveLength) && options.waveLength > 0 ? options.waveLength : 1;
213483
+ const intensity = Number.isFinite(options.waveHeight) ? Math.max(0, Math.min(1, options.waveHeight)) : 1;
213484
+ const speed = Number.isFinite(options.waveSpeed) ? options.waveSpeed : 0;
213485
+ const tile = CURRENT_TILE * patternScale * lengthScale;
213396
213486
  const side = DESIGN_PATTERN_SQUARE * patternScale;
213397
- const phase = CURRENT_TILE_PHASE_OFFSET * patternScale;
213487
+ const phase = CURRENT_TILE_PHASE_OFFSET * patternScale * lengthScale;
213488
+ const drift = speed !== 0 ? w`<animateTransform attributeName="transform" attributeType="XML" type="translate" from="0 0" to="0 ${tile * Math.sign(speed)}" dur="${1 / Math.abs(speed)}s" repeatCount="indefinite"/>` : A;
213398
213489
  return w`
213399
213490
  <defs>
213400
213491
  <linearGradient id="current-force-band-gradient" x1="24" y1="0" x2="24" y2="48" gradientUnits="userSpaceOnUse">
213401
213492
  <stop stop-color=${color2} stop-opacity="0"/>
213402
- <stop offset="1" stop-color=${color2}/>
213493
+ <stop offset="1" stop-color=${color2} stop-opacity=${intensity}/>
213403
213494
  </linearGradient>
213404
213495
  <pattern id="current-force-pattern" patternUnits="userSpaceOnUse" x=${-side / 2 + phase} y=${-side / 2 + phase} width=${tile} height=${tile} viewBox="0 0 48 48" preserveAspectRatio="none">
213405
213496
  <rect width="48" height="48" fill="url(#current-force-band-gradient)"/>
@@ -213407,7 +213498,10 @@ function renderCurrentForcePattern(options) {
213407
213498
  <clipPath id="current-force-clip"><circle cx="0" cy="0" r=${radius}/></clipPath>
213408
213499
  </defs>
213409
213500
  <g clip-path="url(#current-force-clip)" transform="rotate(${fromDirectionDeg})">
213410
- <rect x=${-side / 2} y=${-side / 2} width=${side} height=${side} fill="url(#current-force-pattern)"/>
213501
+ <g>
213502
+ ${drift}
213503
+ <rect x=${-side / 2} y=${-side / 2 - tile} width=${side} height=${side + 2 * tile} fill="url(#current-force-pattern)"/>
213504
+ </g>
213411
213505
  </g>
213412
213506
  `;
213413
213507
  }
@@ -213423,7 +213517,9 @@ var __decorateClass$L = (decorators, target, key, kind) => {
213423
213517
  };
213424
213518
  const CURRENT_PATTERN_SCALE_VESSEL = 1.39;
213425
213519
  const CURRENT_PATTERN_SCALE_DIRECTION = 2;
213426
- const CURRENT_ICON_PERIPHERY_RADIUS = 116;
213520
+ const CURRENT_ICON_PERIPHERY_RADIUS = innerRingRadiusFor(
213521
+ WatchCircleType.double
213522
+ );
213427
213523
  const CURRENT_DIRECTION_ICON_SCALE = 7;
213428
213524
  function clampCurrentSpeed(value) {
213429
213525
  if (value == null || !Number.isFinite(value)) {
@@ -213438,6 +213534,10 @@ let ObcCurrent = class extends i$4 {
213438
213534
  this.currentSpeed = null;
213439
213535
  this.currentFromDirection = null;
213440
213536
  this.priority = Priority.regular;
213537
+ this.hasPattern = true;
213538
+ this.waveLength = 1;
213539
+ this.waveHeight = 1;
213540
+ this.waveSpeed = 0;
213441
213541
  this.vesselImage = VesselImage.genericTop;
213442
213542
  this.vesselHeadingDeg = 0;
213443
213543
  }
@@ -213480,7 +213580,7 @@ let ObcCurrent = class extends i$4 {
213480
213580
  `;
213481
213581
  }
213482
213582
  renderForcePattern(watchCircleType) {
213483
- if (this.currentFromDirection == null) {
213583
+ if (!this.hasPattern || this.currentFromDirection == null) {
213484
213584
  return A;
213485
213585
  }
213486
213586
  return b`
@@ -213489,7 +213589,10 @@ let ObcCurrent = class extends i$4 {
213489
213589
  fromDirectionDeg: this.currentFromDirection,
213490
213590
  radius: innerRingRadiusFor(watchCircleType),
213491
213591
  patternScale: this.isVesselType ? CURRENT_PATTERN_SCALE_VESSEL : CURRENT_PATTERN_SCALE_DIRECTION,
213492
- color: this.enhanced ? "var(--instrument-enhanced-tertiary-color)" : void 0
213592
+ color: this.enhanced ? "var(--instrument-enhanced-tertiary-color)" : void 0,
213593
+ waveLength: this.waveLength,
213594
+ waveHeight: this.waveHeight,
213595
+ waveSpeed: this.waveSpeed
213493
213596
  })}
213494
213597
  </svg>
213495
213598
  `;
@@ -213508,6 +213611,18 @@ __decorateClass$L([
213508
213611
  __decorateClass$L([
213509
213612
  n$3({ type: String })
213510
213613
  ], ObcCurrent.prototype, "priority", 2);
213614
+ __decorateClass$L([
213615
+ n$3({ type: Boolean, attribute: false })
213616
+ ], ObcCurrent.prototype, "hasPattern", 2);
213617
+ __decorateClass$L([
213618
+ n$3({ type: Number })
213619
+ ], ObcCurrent.prototype, "waveLength", 2);
213620
+ __decorateClass$L([
213621
+ n$3({ type: Number })
213622
+ ], ObcCurrent.prototype, "waveHeight", 2);
213623
+ __decorateClass$L([
213624
+ n$3({ type: Number })
213625
+ ], ObcCurrent.prototype, "waveSpeed", 2);
213511
213626
  __decorateClass$L([
213512
213627
  n$3({ type: String })
213513
213628
  ], ObcCurrent.prototype, "vesselImage", 2);
@@ -222128,7 +222243,7 @@ let ObcHeading = class extends i$4 {
222128
222243
  .tickmarksInside=${this.tickmarksInside}
222129
222244
  .crosshairEnabled=${true}
222130
222245
  .crosshairCenterCutout=${this.hasCenterReadouts}
222131
- .northArrow=${!frame.labelsHidden}
222246
+ .northArrow=${true}
222132
222247
  .angleSetpoint=${this.headingSetpoint ?? void 0}
222133
222248
  .newAngleSetpoint=${this.newHeadingSetpoint}
222134
222249
  .atAngleSetpoint=${this._headingSp.computeAtSetpoint(this.heading)}
@@ -224483,9 +224598,16 @@ let ObcPitchRollHeave = class extends i$4 {
224483
224598
  * `obc-watch` renders its crosshair after the bands, i.e. on top of them.
224484
224599
  * Drawing it here puts it under the watch layer, so the bands and the heave
224485
224600
  * column mask it naturally.
224601
+ *
224602
+ * In `single-scale` nothing frames the segment above the vessel (the other
224603
+ * three arms end under the pitch band, roll band and heave column), so the
224604
+ * vertical arm stops at the centre instead of continuing upward. In
224605
+ * `dual-scale` the top roll band gives it a natural endpoint, so the full
224606
+ * arm is kept.
224486
224607
  */
224487
224608
  renderCrosshair() {
224488
224609
  const r2 = OUTER_RING_RADIUS;
224610
+ const yTop = this.isDualScale ? -r2 : 0;
224489
224611
  return w`
224490
224612
  <line
224491
224613
  x1=${-r2} y1="0" x2=${r2} y2="0"
@@ -224493,7 +224615,7 @@ let ObcPitchRollHeave = class extends i$4 {
224493
224615
  vector-effect="non-scaling-stroke"
224494
224616
  />
224495
224617
  <line
224496
- x1="0" y1=${-r2} x2="0" y2=${r2}
224618
+ x1="0" y1=${yTop} x2="0" y2=${r2}
224497
224619
  stroke="var(--instrument-frame-tertiary-color)"
224498
224620
  vector-effect="non-scaling-stroke"
224499
224621
  />
@@ -227416,14 +227538,19 @@ const OBSERVED_ATTRIBUTES = [
227416
227538
  "unit",
227417
227539
  "src",
227418
227540
  "value",
227541
+ "valuetype",
227419
227542
  "setpoint",
227420
227543
  "advice",
227544
+ // ⚠ inert — see the note above; the real names have no hyphens.
227421
227545
  "max-digits",
227422
227546
  "fraction-digits",
227423
227547
  "has-degree",
227424
227548
  "has-setpoint",
227425
227549
  "has-advice"
227426
227550
  ];
227551
+ function isTextValueRow(item) {
227552
+ return item.valueType === ReadoutValueType.text;
227553
+ }
227427
227554
  function integerDigitCount(value) {
227428
227555
  if (value === null || value === void 0 || Number.isNaN(value)) {
227429
227556
  return 0;
@@ -227474,11 +227601,22 @@ let ObcReadoutList = class extends i$4 {
227474
227601
  let longestSrc = "";
227475
227602
  let anyDegree = false;
227476
227603
  for (const item of items) {
227477
- maxFractionDigits = Math.max(maxFractionDigits, item.fractionDigits ?? 0);
227604
+ const hasNumericBlock = !isTextValueRow(item) || item.hasSetpoint || item.hasAdvice;
227605
+ if (hasNumericBlock) {
227606
+ maxFractionDigits = Math.max(
227607
+ maxFractionDigits,
227608
+ item.fractionDigits ?? 0
227609
+ );
227610
+ maxIntegerDigits = Math.max(maxIntegerDigits, item.maxDigits ?? 0);
227611
+ }
227478
227612
  maxIntegerDigits = Math.max(
227479
227613
  maxIntegerDigits,
227480
- item.maxDigits ?? 0,
227481
- integerDigitCount(item.value),
227614
+ integerDigitCount(
227615
+ resolveReadoutNumericValue(
227616
+ item.value,
227617
+ item.valueType ?? ReadoutValueType.number
227618
+ )
227619
+ ),
227482
227620
  item.hasSetpoint ? integerDigitCount(item.setpoint) : 0,
227483
227621
  item.hasAdvice ? integerDigitCount(item.advice) : 0
227484
227622
  );
@@ -227497,7 +227635,7 @@ let ObcReadoutList = class extends i$4 {
227497
227635
  for (const item of items) {
227498
227636
  item.valueOptions = {
227499
227637
  ...item.valueOptions,
227500
- spaceReserver: numericReserver
227638
+ spaceReserver: isTextValueRow(item) ? void 0 : numericReserver
227501
227639
  };
227502
227640
  item.setpointOptions = {
227503
227641
  ...item.setpointOptions,
@@ -230747,6 +230885,20 @@ let ObcTopViewPropulsion = class extends i$4 {
230747
230885
  stroke-linecap="round"
230748
230886
  ></path>`;
230749
230887
  }
230888
+ /**
230889
+ * Thin outline on the track band's inner edge, always shown per the
230890
+ * design's track face. Drawn on the overlay because the watch paints its
230891
+ * band bars over the ring circles, which would swallow a watch-side line.
230892
+ */
230893
+ renderInnerRingLine() {
230894
+ return w`<circle
230895
+ r=${BAND_INNER_RADIUS}
230896
+ fill="none"
230897
+ stroke="var(--instrument-frame-tertiary-color)"
230898
+ stroke-width="1"
230899
+ vector-effect="non-scaling-stroke"
230900
+ ></circle>`;
230901
+ }
230750
230902
  renderPropeller() {
230751
230903
  return w`<g transform="scale(${PROPELLER_SCALE}) translate(-80 -80)">${propellerImages[this.propeller]}</g>`;
230752
230904
  }
@@ -230767,6 +230919,7 @@ let ObcTopViewPropulsion = class extends i$4 {
230767
230919
  <obc-watch
230768
230920
  .touching=${this.touching}
230769
230921
  .arcFrame=${frame}
230922
+ .watchCircleType=${WatchCircleType.double}
230770
230923
  .tickmarks=${shownTickmarks}
230771
230924
  .state=${this.state}
230772
230925
  .priority=${this.priority}
@@ -230784,8 +230937,8 @@ let ObcTopViewPropulsion = class extends i$4 {
230784
230937
  .tickmarkStyle=${this.tickmarkStyle}
230785
230938
  ></obc-watch>
230786
230939
  <svg viewBox=${frame.viewBox} xmlns="http://www.w3.org/2000/svg">
230787
- ${this.renderLoadingArc()} ${this.renderSecondaryArc()}
230788
- ${this.renderPropeller()}
230940
+ ${this.renderInnerRingLine()} ${this.renderLoadingArc()}
230941
+ ${this.renderSecondaryArc()} ${this.renderPropeller()}
230789
230942
  </svg>
230790
230943
  </div>
230791
230944
  `;
@@ -232298,7 +232451,10 @@ function resolveHistogramMaxRadius(variant) {
232298
232451
  function resolveWindArrowPlacement(variant) {
232299
232452
  switch (variant) {
232300
232453
  case "large":
232301
- return { windSymbolRadius: 119, scaleWindIcon: 1 };
232454
+ return {
232455
+ windSymbolRadius: innerRingRadiusFor(WatchCircleType.double) + WIND_ICON_TIP_TO_BOX_INNER,
232456
+ scaleWindIcon: 1
232457
+ };
232302
232458
  case "medium":
232303
232459
  return { windSymbolRadius: 62, scaleWindIcon: 1.5 };
232304
232460
  case "small":