@oicl/openbridge-webcomponents-full-bundle 2.0.0-next.112 → 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.
- package/bundle/openbridge-webcomponents.bundle.js +112 -13
- package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
- package/custom-elements.json +101 -14
- package/dist/building-blocks/readout-block/readout-block.d.ts +29 -5
- package/dist/building-blocks/readout-block/readout-block.d.ts.map +1 -1
- package/dist/building-blocks/readout-block/readout-block.js +21 -7
- package/dist/building-blocks/readout-block/readout-block.js.map +1 -1
- package/dist/navigation-instruments/readout/readout-formatters.d.ts +31 -0
- package/dist/navigation-instruments/readout/readout-formatters.d.ts.map +1 -1
- package/dist/navigation-instruments/readout/readout-formatters.js +55 -1
- package/dist/navigation-instruments/readout/readout-formatters.js.map +1 -1
- package/dist/navigation-instruments/readout/readout.d.ts +26 -1
- package/dist/navigation-instruments/readout/readout.d.ts.map +1 -1
- package/dist/navigation-instruments/readout/readout.js +16 -3
- package/dist/navigation-instruments/readout/readout.js.map +1 -1
- package/dist/navigation-instruments/readout-list/readout-list.d.ts +6 -1
- package/dist/navigation-instruments/readout-list/readout-list.d.ts.map +1 -1
- package/dist/navigation-instruments/readout-list/readout-list.js +21 -4
- package/dist/navigation-instruments/readout-list/readout-list.js.map +1 -1
- package/dist/navigation-instruments/readout-list-item/readout-list-item.d.ts +26 -1
- package/dist/navigation-instruments/readout-list-item/readout-list-item.d.ts.map +1 -1
- package/dist/navigation-instruments/readout-list-item/readout-list-item.js +15 -3
- package/dist/navigation-instruments/readout-list-item/readout-list-item.js.map +1 -1
- package/package.json +1 -1
- package/src/building-blocks/readout-block/readout-block.stories.ts +112 -3
- package/src/building-blocks/readout-block/readout-block.ts +64 -10
- package/src/navigation-instruments/readout/readout-formatters.spec.ts +229 -0
- package/src/navigation-instruments/readout/readout-formatters.ts +105 -0
- package/src/navigation-instruments/readout/readout.stories.ts +167 -3
- package/src/navigation-instruments/readout/readout.ts +52 -4
- package/src/navigation-instruments/readout-list/readout-list.stories.ts +122 -1
- package/src/navigation-instruments/readout-list/readout-list.ts +54 -5
- package/src/navigation-instruments/readout-list-item/readout-list-item.stories.ts +124 -4
- package/src/navigation-instruments/readout-list-item/readout-list-item.ts +53 -4
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
type ReadoutAdviceOptions,
|
|
17
17
|
type ReadoutReserverOptions,
|
|
18
18
|
type ReadoutSrcOptions,
|
|
19
|
+
ReadoutValueType,
|
|
19
20
|
} from './readout-list-item.js';
|
|
20
21
|
import type {AlertFrameConfig} from '../../components/alert-frame/alert-frame.js';
|
|
21
22
|
import {
|
|
@@ -36,7 +37,8 @@ type ReadoutListItemStoryArgs = {
|
|
|
36
37
|
unit: string;
|
|
37
38
|
src: string;
|
|
38
39
|
hasValue: boolean;
|
|
39
|
-
value: number;
|
|
40
|
+
value: number | string;
|
|
41
|
+
valueType: ReadoutValueType;
|
|
40
42
|
off: boolean;
|
|
41
43
|
hasSetpoint: boolean;
|
|
42
44
|
setpoint: number;
|
|
@@ -90,7 +92,8 @@ type ReadoutItemConfig = {
|
|
|
90
92
|
unit?: string;
|
|
91
93
|
src?: string;
|
|
92
94
|
hasValue?: boolean;
|
|
93
|
-
value?: number | null;
|
|
95
|
+
value?: number | string | null;
|
|
96
|
+
valueType?: ReadoutValueType;
|
|
94
97
|
off?: boolean;
|
|
95
98
|
hasSetpoint?: boolean;
|
|
96
99
|
setpoint?: number;
|
|
@@ -159,6 +162,7 @@ function renderItem(config: ReadoutItemConfig) {
|
|
|
159
162
|
.src=${config.src}
|
|
160
163
|
.hasValue=${config.hasValue ?? true}
|
|
161
164
|
.value=${config.value ?? null}
|
|
165
|
+
.valueType=${config.valueType ?? ReadoutValueType.number}
|
|
162
166
|
.off=${config.off ?? false}
|
|
163
167
|
.hasSetpoint=${config.hasSetpoint ?? false}
|
|
164
168
|
.setpoint=${config.setpoint}
|
|
@@ -245,6 +249,7 @@ const defaultArgs: ReadoutListItemStoryArgs = {
|
|
|
245
249
|
src: 'SRC',
|
|
246
250
|
hasValue: true,
|
|
247
251
|
value: 123,
|
|
252
|
+
valueType: ReadoutValueType.number,
|
|
248
253
|
off: false,
|
|
249
254
|
hasSetpoint: false,
|
|
250
255
|
setpoint: 120,
|
|
@@ -313,6 +318,7 @@ const meta = {
|
|
|
313
318
|
src: args.src,
|
|
314
319
|
hasValue: args.hasValue,
|
|
315
320
|
value: args.value,
|
|
321
|
+
valueType: args.valueType,
|
|
316
322
|
off: args.off,
|
|
317
323
|
hasSetpoint: args.hasSetpoint,
|
|
318
324
|
setpoint: args.setpoint,
|
|
@@ -331,7 +337,16 @@ const meta = {
|
|
|
331
337
|
hasValue: {name: 'Has Value', table: {category: 'Data'}},
|
|
332
338
|
value: {
|
|
333
339
|
name: 'Value',
|
|
334
|
-
control
|
|
340
|
+
// Text control (not number) so both value types are exercisable. Under
|
|
341
|
+
// valueType=number a numeric string resolves back to a number; entering
|
|
342
|
+
// non-numeric text there throws, which is the intended contract.
|
|
343
|
+
control: {type: 'text'},
|
|
344
|
+
table: {category: 'Data'},
|
|
345
|
+
},
|
|
346
|
+
valueType: {
|
|
347
|
+
name: 'Value Type',
|
|
348
|
+
control: {type: 'inline-radio'},
|
|
349
|
+
options: Object.values(ReadoutValueType),
|
|
335
350
|
table: {category: 'Data'},
|
|
336
351
|
},
|
|
337
352
|
off: {name: 'Off', table: {category: 'Data'}},
|
|
@@ -461,6 +476,96 @@ export const Off: Story = {
|
|
|
461
476
|
]),
|
|
462
477
|
};
|
|
463
478
|
|
|
479
|
+
/**
|
|
480
|
+
* **Text values** — `valueType="text"` renders `value` verbatim instead of
|
|
481
|
+
* formatting it as a number, for readings that are states rather than
|
|
482
|
+
* quantities ("Thermo On", "Auto", "Normal").
|
|
483
|
+
*
|
|
484
|
+
* The first section reproduces the reference design: two status rows sharing a
|
|
485
|
+
* bar, each a label with a bold text value, separated by a vertical divider.
|
|
486
|
+
*
|
|
487
|
+
* Under `valueType="text"` the numeric format options (`fractionDigits`,
|
|
488
|
+
* `maxDigits`, `hintedZeros`) are ignored; an explicit `spaceReserver` still
|
|
489
|
+
* applies. Passing text while `valueType` is `number` throws a `TypeError`
|
|
490
|
+
* rather than rendering `NaN`.
|
|
491
|
+
*/
|
|
492
|
+
const STATUS_BAR_ROWS: {label: string; value: string}[] = [
|
|
493
|
+
{label: 'Operating mode', value: 'Thermo On'},
|
|
494
|
+
{label: 'Status', value: 'Normal'},
|
|
495
|
+
];
|
|
496
|
+
|
|
497
|
+
export const TextValue: Story = {
|
|
498
|
+
render: () => html`
|
|
499
|
+
<style>
|
|
500
|
+
.rli-status-bar {
|
|
501
|
+
display: flex;
|
|
502
|
+
align-items: stretch;
|
|
503
|
+
width: 100%;
|
|
504
|
+
background: var(--container-background-color);
|
|
505
|
+
}
|
|
506
|
+
.rli-status-cell {
|
|
507
|
+
flex: 1;
|
|
508
|
+
display: flex;
|
|
509
|
+
align-items: center;
|
|
510
|
+
padding: 0 16px;
|
|
511
|
+
}
|
|
512
|
+
.rli-status-cell + .rli-status-cell {
|
|
513
|
+
border-left: 1px solid var(--border-divider-color, #ccc);
|
|
514
|
+
}
|
|
515
|
+
.rli-status-cell > obc-readout-list-item {
|
|
516
|
+
width: 100%;
|
|
517
|
+
}
|
|
518
|
+
.rli-text-grid {
|
|
519
|
+
display: grid;
|
|
520
|
+
grid-template-columns: repeat(2, minmax(240px, max-content));
|
|
521
|
+
gap: 12px 24px;
|
|
522
|
+
margin-top: 32px;
|
|
523
|
+
}
|
|
524
|
+
</style>
|
|
525
|
+
<div class="rli-status-bar">
|
|
526
|
+
${STATUS_BAR_ROWS.map(
|
|
527
|
+
(row) => html`
|
|
528
|
+
<div class="rli-status-cell">
|
|
529
|
+
${renderItem({
|
|
530
|
+
label: row.label,
|
|
531
|
+
value: row.value,
|
|
532
|
+
valueType: ReadoutValueType.text,
|
|
533
|
+
options: {
|
|
534
|
+
size: ReadoutListItemSize.medium,
|
|
535
|
+
value: {weight: ObcTextboxFontWeight.bold},
|
|
536
|
+
},
|
|
537
|
+
})}
|
|
538
|
+
</div>
|
|
539
|
+
`
|
|
540
|
+
)}
|
|
541
|
+
</div>
|
|
542
|
+
<div class="rli-text-grid">
|
|
543
|
+
${[
|
|
544
|
+
{label: 'Mode', value: 'Auto', valueType: ReadoutValueType.text},
|
|
545
|
+
{
|
|
546
|
+
label: 'Thruster',
|
|
547
|
+
value: 'Standby',
|
|
548
|
+
valueType: ReadoutValueType.text,
|
|
549
|
+
},
|
|
550
|
+
// Numeric rows for contrast — the same component, unchanged.
|
|
551
|
+
{label: 'Speed', value: 12.4, valueType: ReadoutValueType.number},
|
|
552
|
+
// Verbatim text preserves formatting a number could not round-trip.
|
|
553
|
+
{label: 'Bearing', value: '1.50', valueType: ReadoutValueType.text},
|
|
554
|
+
].map((row) =>
|
|
555
|
+
renderItem({
|
|
556
|
+
label: row.label,
|
|
557
|
+
value: row.value,
|
|
558
|
+
valueType: row.valueType,
|
|
559
|
+
options: {
|
|
560
|
+
size: ReadoutListItemSize.medium,
|
|
561
|
+
fractionDigits: 1,
|
|
562
|
+
},
|
|
563
|
+
})
|
|
564
|
+
)}
|
|
565
|
+
</div>
|
|
566
|
+
`,
|
|
567
|
+
};
|
|
568
|
+
|
|
464
569
|
const SIZES = [
|
|
465
570
|
ReadoutListItemSize.small,
|
|
466
571
|
ReadoutListItemSize.medium,
|
|
@@ -1596,7 +1701,8 @@ export const MissingParts: Story = {
|
|
|
1596
1701
|
*/
|
|
1597
1702
|
type AlignmentRow = {
|
|
1598
1703
|
label: string;
|
|
1599
|
-
value: number | null;
|
|
1704
|
+
value: number | string | null;
|
|
1705
|
+
valueType?: ReadoutValueType;
|
|
1600
1706
|
unit: string;
|
|
1601
1707
|
size?: ReadoutListItemSize;
|
|
1602
1708
|
hasDegree?: boolean;
|
|
@@ -1722,6 +1828,19 @@ const ALIGNMENT_ROWS: AlignmentRow[] = [
|
|
|
1722
1828
|
type: ObcAlertFrameType.Regular,
|
|
1723
1829
|
},
|
|
1724
1830
|
},
|
|
1831
|
+
// text value — `valueType="text"` renders verbatim and ignores maxDigits /
|
|
1832
|
+
// fractionDigits, but still honours an explicit `spaceReserver`. So these
|
|
1833
|
+
// rows hug their text in the left column and join the shared value column in
|
|
1834
|
+
// the right one, confirming text does not disturb the numeric alignment.
|
|
1835
|
+
// (Inside `obc-readout-list`, which owns the reservers, text rows are instead
|
|
1836
|
+
// excluded from the computed numeric width — see that component's stories.)
|
|
1837
|
+
{label: 'Mode', value: 'Auto', valueType: ReadoutValueType.text, unit: ''},
|
|
1838
|
+
{
|
|
1839
|
+
label: 'Thruster',
|
|
1840
|
+
value: 'Standby',
|
|
1841
|
+
valueType: ReadoutValueType.text,
|
|
1842
|
+
unit: '',
|
|
1843
|
+
},
|
|
1725
1844
|
// size variants — value digit edges do NOT fully align cross-size (the degree
|
|
1726
1845
|
// column scales 6/8/12px with the value size); see the ColumnAlignment doc.
|
|
1727
1846
|
|
|
@@ -1771,6 +1890,7 @@ function renderAlignmentColumn(aligned: boolean, showDebugOverlay: boolean) {
|
|
|
1771
1890
|
unit: row.unit,
|
|
1772
1891
|
src: '',
|
|
1773
1892
|
value: row.value,
|
|
1893
|
+
valueType: row.valueType,
|
|
1774
1894
|
hasSetpoint: row.hasSetpoint,
|
|
1775
1895
|
setpoint: row.setpoint,
|
|
1776
1896
|
hasAdvice: row.hasAdvice,
|
|
@@ -15,7 +15,12 @@ import {
|
|
|
15
15
|
ReadoutBlockDataQuality,
|
|
16
16
|
ReadoutBlockHidePhase,
|
|
17
17
|
} from '../../building-blocks/readout-block/readout-block.js';
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
assertReadoutValueType,
|
|
20
|
+
resolveReadoutNumericValue,
|
|
21
|
+
ReadoutValueType,
|
|
22
|
+
type ReadoutNumericFormatOptions,
|
|
23
|
+
} from '../readout/readout-formatters.js';
|
|
19
24
|
import {
|
|
20
25
|
isDisplayedAtSetpoint,
|
|
21
26
|
readoutNumericFormatOptions,
|
|
@@ -39,6 +44,9 @@ import {AlertType} from '../../types.js';
|
|
|
39
44
|
// without a second import path.
|
|
40
45
|
export {ObcTextboxFontWeight} from '../../components/textbox/textbox.js';
|
|
41
46
|
|
|
47
|
+
// Re-exported so consumers can type `valueType` without a second import path.
|
|
48
|
+
export {ReadoutValueType} from '../readout/readout-formatters.js';
|
|
49
|
+
|
|
42
50
|
/**
|
|
43
51
|
* Density/size scale of the readout row (an alias of `ReadoutBlockSize`).
|
|
44
52
|
* - `small`: regular value typography (smallest, densest).
|
|
@@ -207,6 +215,8 @@ export interface ReadoutSrcOptions extends ReadoutBlockState {
|
|
|
207
215
|
* `round-corners`, or `round` corners.
|
|
208
216
|
* - **Formatting:** shared `fractionDigits`, width reservation via `maxDigits`
|
|
209
217
|
* and per-segment `hintedZeros`; a `null` value renders a dash (`-`).
|
|
218
|
+
* - **Text values:** `valueType="text"` renders `value` verbatim (e.g.
|
|
219
|
+
* `"Thermo On"`) instead of formatting it as a number.
|
|
210
220
|
*
|
|
211
221
|
* ### Usage Guidelines
|
|
212
222
|
* Use for dense readout rows in lists/tables. Prefer `<obc-readout>` for rich
|
|
@@ -242,7 +252,18 @@ export class ObcReadoutListItem extends LitElement {
|
|
|
242
252
|
* block at full size, so the row does not shift when data arrives.
|
|
243
253
|
*/
|
|
244
254
|
@property({type: Boolean, attribute: false}) hasValue = true;
|
|
245
|
-
|
|
255
|
+
/**
|
|
256
|
+
* The value; `null` renders a dash. A number by default, or text when
|
|
257
|
+
* {@link valueType} is `text`.
|
|
258
|
+
*/
|
|
259
|
+
@property({type: String}) value: number | string | null = null;
|
|
260
|
+
/**
|
|
261
|
+
* How {@link value} is interpreted. `number` (default) formats it via
|
|
262
|
+
* `fractionDigits`; `text` renders it verbatim and ignores the numeric
|
|
263
|
+
* format options. Passing text while this is `number` throws.
|
|
264
|
+
*/
|
|
265
|
+
@property({type: String}) valueType: ReadoutValueType =
|
|
266
|
+
ReadoutValueType.number;
|
|
246
267
|
/** Render the value as `offText` (e.g. equipment powered down). Affects the value only. */
|
|
247
268
|
@property({type: Boolean}) off = false;
|
|
248
269
|
/** Text shown in place of the value when `off` is true. @availableWhen off==true */
|
|
@@ -265,7 +286,17 @@ export class ObcReadoutListItem extends LitElement {
|
|
|
265
286
|
@property({type: Boolean}) hasLeadingIcon = false;
|
|
266
287
|
@property({type: Boolean}) hasDegree = false;
|
|
267
288
|
@property({type: Boolean}) hasDegreeSpacer = false;
|
|
289
|
+
/**
|
|
290
|
+
* Also formats the numeric setpoint / advice blocks, which stay numeric
|
|
291
|
+
* even when the value is text.
|
|
292
|
+
* @availableWhen valueType==number || hasSetpoint==true || hasAdvice==true
|
|
293
|
+
*/
|
|
268
294
|
@property({type: Number}) fractionDigits = 0;
|
|
295
|
+
/**
|
|
296
|
+
* Also formats the numeric setpoint / advice blocks, which stay numeric
|
|
297
|
+
* even when the value is text.
|
|
298
|
+
* @availableWhen valueType==number || hasSetpoint==true || hasAdvice==true
|
|
299
|
+
*/
|
|
269
300
|
@property({type: Number}) maxDigits = 0;
|
|
270
301
|
@property({type: String}) dataQuality?: ReadoutListItemDataQuality;
|
|
271
302
|
// `boolean | …` (not `false | …`): the generated Angular wrapper widens a
|
|
@@ -329,8 +360,10 @@ export class ObcReadoutListItem extends LitElement {
|
|
|
329
360
|
if (!this.hasSetpoint) {
|
|
330
361
|
return false;
|
|
331
362
|
}
|
|
363
|
+
// A text value never compares equal to a setpoint, so flip-flop / pop-up
|
|
364
|
+
// stay dormant for `valueType="text"`.
|
|
332
365
|
return isDisplayedAtSetpoint(
|
|
333
|
-
this.value,
|
|
366
|
+
resolveReadoutNumericValue(this.value, this.valueType) ?? null,
|
|
334
367
|
this.setpoint,
|
|
335
368
|
this.numericFormatOptions(this.resolvedMaxDigits)
|
|
336
369
|
);
|
|
@@ -451,7 +484,9 @@ export class ObcReadoutListItem extends LitElement {
|
|
|
451
484
|
|
|
452
485
|
private renderBlock(config: {
|
|
453
486
|
variant: ReadoutBlockVariant;
|
|
454
|
-
value: number | null | undefined;
|
|
487
|
+
value: number | string | null | undefined;
|
|
488
|
+
/** Only the value block is ever text; setpoint / advice stay numeric. */
|
|
489
|
+
valueType?: ReadoutValueType;
|
|
455
490
|
valueSize: ObcTextboxSize;
|
|
456
491
|
enhanced: boolean;
|
|
457
492
|
weight: ObcTextboxFontWeight;
|
|
@@ -473,6 +508,7 @@ export class ObcReadoutListItem extends LitElement {
|
|
|
473
508
|
exportparts="block, block-content, block-text, block-icon, degree"
|
|
474
509
|
.variant=${config.variant}
|
|
475
510
|
.value=${config.value ?? null}
|
|
511
|
+
.valueType=${config.valueType ?? ReadoutValueType.number}
|
|
476
512
|
.size=${this.resolvedSize}
|
|
477
513
|
.valueSize=${config.valueSize}
|
|
478
514
|
.enhanced=${config.enhanced}
|
|
@@ -684,6 +720,7 @@ export class ObcReadoutListItem extends LitElement {
|
|
|
684
720
|
? this.renderBlock({
|
|
685
721
|
variant: ReadoutBlockVariant.value,
|
|
686
722
|
value: this.value,
|
|
723
|
+
valueType: this.valueType,
|
|
687
724
|
valueSize: this.valueSize,
|
|
688
725
|
enhanced: this.rowEnhanced,
|
|
689
726
|
weight: this.valueWeight,
|
|
@@ -821,6 +858,18 @@ export class ObcReadoutListItem extends LitElement {
|
|
|
821
858
|
`;
|
|
822
859
|
}
|
|
823
860
|
|
|
861
|
+
protected override willUpdate(changed: Map<string, unknown>): void {
|
|
862
|
+
super.willUpdate(changed);
|
|
863
|
+
// Validated on EVERY update, deliberately NOT gated on `value`/`valueType`
|
|
864
|
+
// appearing in `changed`. When this assertion throws, Lit's `performUpdate`
|
|
865
|
+
// catch calls `__markUpdated()`, which clears the changed-properties map. A
|
|
866
|
+
// later update driven by any OTHER property — inside `obc-readout-list`,
|
|
867
|
+
// `align()` writing the shared reservers — would then see no `value` in
|
|
868
|
+
// `changed`, skip the check, and render the invalid value as a plain dash:
|
|
869
|
+
// exactly the silent failure this assertion exists to prevent.
|
|
870
|
+
assertReadoutValueType('obc-readout-list-item', this.value, this.valueType);
|
|
871
|
+
}
|
|
872
|
+
|
|
824
873
|
override updated(changed: Map<string, unknown>): void {
|
|
825
874
|
super.updated(changed);
|
|
826
875
|
|