@oicl/openbridge-webcomponents-full-bundle 2.0.0-next.128 → 2.0.0-next.129
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 +12321 -11895
- package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
- package/custom-elements.json +227 -3
- package/dist/building-blocks/readout-block/readout-block.css.js +53 -19
- package/dist/building-blocks/readout-block/readout-block.css.js.map +1 -1
- package/dist/building-blocks/readout-block/readout-block.d.ts +55 -0
- package/dist/building-blocks/readout-block/readout-block.d.ts.map +1 -1
- package/dist/building-blocks/readout-block/readout-block.js +57 -2
- package/dist/building-blocks/readout-block/readout-block.js.map +1 -1
- package/dist/navigation-instruments/readout/readout-shared.d.ts +23 -0
- package/dist/navigation-instruments/readout/readout-shared.d.ts.map +1 -1
- package/dist/navigation-instruments/readout/readout-shared.js +8 -0
- package/dist/navigation-instruments/readout/readout-shared.js.map +1 -1
- package/dist/navigation-instruments/readout/readout.css.js +138 -31
- package/dist/navigation-instruments/readout/readout.css.js.map +1 -1
- package/dist/navigation-instruments/readout/readout.d.ts +63 -3
- package/dist/navigation-instruments/readout/readout.d.ts.map +1 -1
- package/dist/navigation-instruments/readout/readout.js +127 -27
- package/dist/navigation-instruments/readout/readout.js.map +1 -1
- package/dist/navigation-instruments/readout-list-item/readout-list-item.css.js +64 -1
- package/dist/navigation-instruments/readout-list-item/readout-list-item.css.js.map +1 -1
- package/dist/navigation-instruments/readout-list-item/readout-list-item.d.ts +77 -2
- 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 +100 -23
- 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.css +49 -20
- package/src/building-blocks/readout-block/readout-block.stories.ts +54 -0
- package/src/building-blocks/readout-block/readout-block.ts +101 -2
- package/src/navigation-instruments/instrument-field/instrument-field.stories.ts +1150 -180
- package/src/navigation-instruments/readout/readout-shared.spec.ts +50 -0
- package/src/navigation-instruments/readout/readout-shared.ts +33 -0
- package/src/navigation-instruments/readout/readout.css +124 -32
- package/src/navigation-instruments/readout/readout.stories.ts +536 -19
- package/src/navigation-instruments/readout/readout.ts +184 -31
- package/src/navigation-instruments/readout-list-item/readout-list-item.css +55 -1
- package/src/navigation-instruments/readout-list-item/readout-list-item.stories.ts +341 -0
- package/src/navigation-instruments/readout-list-item/readout-list-item.ts +169 -25
|
@@ -14,14 +14,19 @@ import {
|
|
|
14
14
|
ReadoutDataQuality,
|
|
15
15
|
ReadoutSetpointInteraction,
|
|
16
16
|
ReadoutSourceInteraction,
|
|
17
|
+
ReadoutAdviceCategory,
|
|
18
|
+
ReadoutSourceState,
|
|
17
19
|
ObcTextboxFontWeight,
|
|
18
20
|
type ReadoutValueOptions,
|
|
19
21
|
type ReadoutSetpointOptions,
|
|
20
22
|
type ReadoutAdviceOptions,
|
|
23
|
+
type ReadoutLabelOptions,
|
|
21
24
|
type ReadoutReserverOptions,
|
|
22
25
|
type ReadoutSourceOptions,
|
|
23
26
|
ReadoutValueType,
|
|
24
27
|
} from './readout.js';
|
|
28
|
+
import {ObcTextboxSize} from '../../components/textbox/textbox.js';
|
|
29
|
+
import '../../icons/icon-input-right.js';
|
|
25
30
|
import {
|
|
26
31
|
type AlertFrameConfig,
|
|
27
32
|
ObcAlertFrameMode,
|
|
@@ -55,12 +60,20 @@ type ReadoutStoryArgs = {
|
|
|
55
60
|
'options.fractionDigits': number;
|
|
56
61
|
'options.maxDigits': number;
|
|
57
62
|
'options.dataQuality': ReadoutDataQuality | typeof NONE;
|
|
63
|
+
'options.hasLeadingIcon': boolean;
|
|
58
64
|
'options.value.weight': ObcTextboxFontWeight;
|
|
59
65
|
'options.value.hasIcon': boolean;
|
|
60
66
|
'options.value.hintedZeros': boolean;
|
|
61
67
|
'options.setpoint.interaction': ReadoutSetpointInteraction;
|
|
62
68
|
'options.setpoint.touching': boolean;
|
|
69
|
+
'options.advice.category': ReadoutAdviceCategory;
|
|
70
|
+
'options.advice.active': boolean;
|
|
71
|
+
'options.label.size': ObcTextboxSize | typeof NONE;
|
|
72
|
+
'options.label.spaceReserver': string;
|
|
63
73
|
'options.src.interaction': ReadoutSourceInteraction;
|
|
74
|
+
'options.src.state': ReadoutSourceState;
|
|
75
|
+
'options.src.deviation'?: number;
|
|
76
|
+
'options.src.spaceReserver': string;
|
|
64
77
|
'options.unit.spaceReserver': string;
|
|
65
78
|
};
|
|
66
79
|
|
|
@@ -80,9 +93,11 @@ type StoryOptions = {
|
|
|
80
93
|
maxDigits?: number;
|
|
81
94
|
dataQuality?: ReadoutDataQuality;
|
|
82
95
|
alert?: false | AlertFrameConfig;
|
|
96
|
+
hasLeadingIcon?: boolean;
|
|
83
97
|
value?: ReadoutValueOptions;
|
|
84
98
|
setpoint?: ReadoutSetpointOptions;
|
|
85
99
|
advice?: ReadoutAdviceOptions;
|
|
100
|
+
label?: ReadoutLabelOptions;
|
|
86
101
|
unit?: ReadoutReserverOptions;
|
|
87
102
|
src?: ReadoutSourceOptions;
|
|
88
103
|
};
|
|
@@ -179,9 +194,11 @@ function renderReadout(config: ReadoutConfig) {
|
|
|
179
194
|
.maxDigits=${o.maxDigits ?? 0}
|
|
180
195
|
.dataQuality=${o.dataQuality}
|
|
181
196
|
.alert=${o.alert ?? false}
|
|
197
|
+
.hasLeadingIcon=${o.hasLeadingIcon ?? false}
|
|
182
198
|
.valueOptions=${o.value}
|
|
183
199
|
.setpointOptions=${o.setpoint}
|
|
184
200
|
.adviceOptions=${o.advice}
|
|
201
|
+
.labelOptions=${o.label}
|
|
185
202
|
.unitOptions=${o.unit}
|
|
186
203
|
.srcOptions=${o.src}
|
|
187
204
|
.showDebugOverlay=${config.showDebugOverlay ?? false}
|
|
@@ -189,6 +206,9 @@ function renderReadout(config: ReadoutConfig) {
|
|
|
189
206
|
${config.hasValueIcon
|
|
190
207
|
? html`<obi-placeholder slot="value-icon"></obi-placeholder>`
|
|
191
208
|
: nothing}
|
|
209
|
+
${o.hasLeadingIcon
|
|
210
|
+
? html`<obi-placeholder slot="leading-icon"></obi-placeholder>`
|
|
211
|
+
: nothing}
|
|
192
212
|
</obc-readout>
|
|
193
213
|
`;
|
|
194
214
|
}
|
|
@@ -261,12 +281,19 @@ const defaultArgs: ReadoutStoryArgs = {
|
|
|
261
281
|
'options.fractionDigits': 0,
|
|
262
282
|
'options.maxDigits': 0,
|
|
263
283
|
'options.dataQuality': NONE,
|
|
284
|
+
'options.hasLeadingIcon': false,
|
|
264
285
|
'options.value.weight': ObcTextboxFontWeight.regular,
|
|
265
286
|
'options.value.hasIcon': false,
|
|
266
287
|
'options.value.hintedZeros': false,
|
|
267
288
|
'options.setpoint.interaction': ReadoutSetpointInteraction.alwaysVisible,
|
|
268
289
|
'options.setpoint.touching': false,
|
|
290
|
+
'options.advice.category': ReadoutAdviceCategory.regular,
|
|
291
|
+
'options.advice.active': false,
|
|
292
|
+
'options.label.size': NONE,
|
|
293
|
+
'options.label.spaceReserver': '',
|
|
269
294
|
'options.src.interaction': ReadoutSourceInteraction.none,
|
|
295
|
+
'options.src.state': ReadoutSourceState.regular,
|
|
296
|
+
'options.src.spaceReserver': '',
|
|
270
297
|
'options.unit.spaceReserver': '',
|
|
271
298
|
};
|
|
272
299
|
|
|
@@ -285,6 +312,7 @@ function argsToOptions(args: ReadoutStoryArgs): StoryOptions {
|
|
|
285
312
|
args['options.dataQuality'] === NONE
|
|
286
313
|
? undefined
|
|
287
314
|
: args['options.dataQuality'],
|
|
315
|
+
hasLeadingIcon: args['options.hasLeadingIcon'],
|
|
288
316
|
value: {
|
|
289
317
|
weight: args['options.value.weight'],
|
|
290
318
|
hasIcon: args['options.value.hasIcon'],
|
|
@@ -294,7 +322,23 @@ function argsToOptions(args: ReadoutStoryArgs): StoryOptions {
|
|
|
294
322
|
interaction: args['options.setpoint.interaction'],
|
|
295
323
|
touching: args['options.setpoint.touching'],
|
|
296
324
|
},
|
|
297
|
-
|
|
325
|
+
advice: {
|
|
326
|
+
category: args['options.advice.category'],
|
|
327
|
+
active: args['options.advice.active'],
|
|
328
|
+
},
|
|
329
|
+
label: {
|
|
330
|
+
size:
|
|
331
|
+
args['options.label.size'] === NONE
|
|
332
|
+
? undefined
|
|
333
|
+
: args['options.label.size'],
|
|
334
|
+
spaceReserver: args['options.label.spaceReserver'] || undefined,
|
|
335
|
+
},
|
|
336
|
+
src: {
|
|
337
|
+
interaction: args['options.src.interaction'],
|
|
338
|
+
state: args['options.src.state'],
|
|
339
|
+
deviation: args['options.src.deviation'],
|
|
340
|
+
spaceReserver: args['options.src.spaceReserver'] || undefined,
|
|
341
|
+
},
|
|
298
342
|
unit: {spaceReserver: args['options.unit.spaceReserver'] || undefined},
|
|
299
343
|
};
|
|
300
344
|
}
|
|
@@ -357,8 +401,11 @@ const meta = {
|
|
|
357
401
|
},
|
|
358
402
|
'options.size': {
|
|
359
403
|
name: 'Size',
|
|
404
|
+
description:
|
|
405
|
+
'Vertical only — the horizontal arrangement exists in the large tier alone.',
|
|
360
406
|
control: {type: 'select'},
|
|
361
407
|
options: Object.values(ReadoutSize),
|
|
408
|
+
if: {arg: 'options.direction', eq: ReadoutDirection.vertical},
|
|
362
409
|
table: {category: 'Layout'},
|
|
363
410
|
},
|
|
364
411
|
'options.priority': {
|
|
@@ -436,12 +483,59 @@ const meta = {
|
|
|
436
483
|
if: {arg: 'hasSetpoint', truthy: true},
|
|
437
484
|
table: {category: 'Setpoint'},
|
|
438
485
|
},
|
|
486
|
+
'options.hasLeadingIcon': {
|
|
487
|
+
name: 'Has Leading Icon',
|
|
488
|
+
table: {category: 'Label'},
|
|
489
|
+
},
|
|
490
|
+
'options.label.size': {
|
|
491
|
+
name: 'Label Size',
|
|
492
|
+
description:
|
|
493
|
+
'Default derives from the tier (large → s, otherwise xs); the design defines xs and s.',
|
|
494
|
+
control: {type: 'select'},
|
|
495
|
+
options: [NONE, ObcTextboxSize.xs, ObcTextboxSize.s],
|
|
496
|
+
table: {category: 'Label'},
|
|
497
|
+
},
|
|
498
|
+
'options.label.spaceReserver': {
|
|
499
|
+
name: 'Label Space Reserver',
|
|
500
|
+
control: {type: 'text'},
|
|
501
|
+
table: {category: 'Label'},
|
|
502
|
+
},
|
|
503
|
+
'options.advice.category': {
|
|
504
|
+
name: 'Advice Category',
|
|
505
|
+
control: {type: 'select'},
|
|
506
|
+
options: Object.values(ReadoutAdviceCategory),
|
|
507
|
+
if: {arg: 'hasAdvice', truthy: true},
|
|
508
|
+
table: {category: 'Advice'},
|
|
509
|
+
},
|
|
510
|
+
'options.advice.active': {
|
|
511
|
+
name: 'Advice Active (triggered)',
|
|
512
|
+
if: {arg: 'hasAdvice', truthy: true},
|
|
513
|
+
table: {category: 'Advice'},
|
|
514
|
+
},
|
|
439
515
|
'options.src.interaction': {
|
|
440
516
|
name: 'Source Interaction',
|
|
441
517
|
control: {type: 'select'},
|
|
442
518
|
options: Object.values(ReadoutSourceInteraction),
|
|
443
519
|
table: {category: 'Source'},
|
|
444
520
|
},
|
|
521
|
+
'options.src.state': {
|
|
522
|
+
name: 'Source State',
|
|
523
|
+
description:
|
|
524
|
+
'Applies to the plain source only — picker / flyout buttons carry no state chip.',
|
|
525
|
+
control: {type: 'select'},
|
|
526
|
+
options: Object.values(ReadoutSourceState),
|
|
527
|
+
table: {category: 'Source'},
|
|
528
|
+
},
|
|
529
|
+
'options.src.deviation': {
|
|
530
|
+
name: 'Source Deviation (Δ)',
|
|
531
|
+
control: {type: 'number'},
|
|
532
|
+
table: {category: 'Source'},
|
|
533
|
+
},
|
|
534
|
+
'options.src.spaceReserver': {
|
|
535
|
+
name: 'Source Space Reserver',
|
|
536
|
+
control: {type: 'text'},
|
|
537
|
+
table: {category: 'Source'},
|
|
538
|
+
},
|
|
445
539
|
'options.unit.spaceReserver': {
|
|
446
540
|
name: 'Unit Space Reserver',
|
|
447
541
|
control: {type: 'text'},
|
|
@@ -464,8 +558,11 @@ const SIZES = [
|
|
|
464
558
|
const INTERACTIONS = Object.values(ReadoutSetpointInteraction);
|
|
465
559
|
|
|
466
560
|
/** One row per size; columns = interaction modes × value≠/=setpoint. */
|
|
467
|
-
function interactionMatrix(
|
|
468
|
-
|
|
561
|
+
function interactionMatrix(
|
|
562
|
+
direction: ReadoutDirection,
|
|
563
|
+
sizes: readonly ReadoutSize[] = SIZES
|
|
564
|
+
): ShowcaseCase[] {
|
|
565
|
+
return sizes.flatMap((size) =>
|
|
469
566
|
INTERACTIONS.flatMap((interaction) =>
|
|
470
567
|
[123, 120].map((value) => ({
|
|
471
568
|
label: `${size} / ${interaction} / ${
|
|
@@ -504,37 +601,42 @@ export const Vertical: Story = {
|
|
|
504
601
|
},
|
|
505
602
|
{
|
|
506
603
|
title: 'Vertical — Setpoint Interactions',
|
|
507
|
-
columns:
|
|
604
|
+
columns: 8,
|
|
508
605
|
cases: interactionMatrix(ReadoutDirection.vertical),
|
|
509
606
|
},
|
|
510
607
|
]),
|
|
511
608
|
};
|
|
512
609
|
|
|
610
|
+
/**
|
|
611
|
+
* The horizontal arrangement exists in the large tier only (Figma 6.1: it
|
|
612
|
+
* relies on the label+unit stack aligning with the L-size value caps — label
|
|
613
|
+
* cap top and unit cap bottom line up with the value's cap edges). `size` is
|
|
614
|
+
* ignored when `direction` is `horizontal`.
|
|
615
|
+
*/
|
|
513
616
|
export const Horizontal: Story = {
|
|
514
617
|
render: () =>
|
|
515
618
|
renderShowcase([
|
|
516
619
|
{
|
|
517
|
-
title: 'Horizontal
|
|
620
|
+
title: 'Horizontal (large Only) — Priority',
|
|
518
621
|
columns: 2,
|
|
519
|
-
cases:
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
priority,
|
|
527
|
-
direction: ReadoutDirection.horizontal,
|
|
528
|
-
},
|
|
622
|
+
cases: [ReadoutPriority.regular, ReadoutPriority.enhanced].map(
|
|
623
|
+
(priority) => ({
|
|
624
|
+
label: `large / ${priority}`,
|
|
625
|
+
config: {
|
|
626
|
+
options: {
|
|
627
|
+
priority,
|
|
628
|
+
direction: ReadoutDirection.horizontal,
|
|
529
629
|
},
|
|
530
|
-
}
|
|
531
|
-
)
|
|
630
|
+
},
|
|
631
|
+
})
|
|
532
632
|
),
|
|
533
633
|
},
|
|
534
634
|
{
|
|
535
635
|
title: 'Horizontal — Setpoint Interactions',
|
|
536
|
-
columns:
|
|
537
|
-
cases: interactionMatrix(ReadoutDirection.horizontal
|
|
636
|
+
columns: 8,
|
|
637
|
+
cases: interactionMatrix(ReadoutDirection.horizontal, [
|
|
638
|
+
ReadoutSize.large,
|
|
639
|
+
]),
|
|
538
640
|
},
|
|
539
641
|
]),
|
|
540
642
|
};
|
|
@@ -921,6 +1023,35 @@ export const SetpointPopUpAnimated: Story = {
|
|
|
921
1023
|
tags: ['skip-test'],
|
|
922
1024
|
};
|
|
923
1025
|
|
|
1026
|
+
export const SetpointAlwaysVisibleAnimated: Story = {
|
|
1027
|
+
...animatedInteractionStory({
|
|
1028
|
+
name: 'Always-Visible (Animated)',
|
|
1029
|
+
interaction: ReadoutSetpointInteraction.alwaysVisible,
|
|
1030
|
+
intro:
|
|
1031
|
+
'Always-visible (the default, Figma "Primary secondary"): the setpoint stays at the secondary size in both states — nothing resizes or hides as the value reaches the setpoint (120); only the touch highlight shows during the sweep. Contrast with flip-flop / pop-up. Press Play, or use the buttons.',
|
|
1032
|
+
awayLabel: 'Away (124)',
|
|
1033
|
+
reachLabel: 'Reach setpoint (120)',
|
|
1034
|
+
}),
|
|
1035
|
+
tags: ['skip-test'],
|
|
1036
|
+
};
|
|
1037
|
+
|
|
1038
|
+
export const SetpointEqualSizeAnimated: Story = {
|
|
1039
|
+
...animatedInteractionStory({
|
|
1040
|
+
name: 'Equal-Size (Animated)',
|
|
1041
|
+
interaction: ReadoutSetpointInteraction.equalSize,
|
|
1042
|
+
intro:
|
|
1043
|
+
'Equal-size (Figma 6.1 "Equal size"): value and setpoint share the primary size in both states — like always-visible, nothing resizes or hides as the value reaches the setpoint (120); only the touch highlight shows during the sweep. Press Play, or use the buttons.',
|
|
1044
|
+
awayLabel: 'Away (124)',
|
|
1045
|
+
reachLabel: 'Reach setpoint (120)',
|
|
1046
|
+
}),
|
|
1047
|
+
tags: ['skip-test'],
|
|
1048
|
+
};
|
|
1049
|
+
|
|
1050
|
+
/**
|
|
1051
|
+
* The degree glyph renders on the ACTUAL VALUE only — setpoint and advice
|
|
1052
|
+
* blocks never carry one (Figma 6.1 review: the unit is written once for the
|
|
1053
|
+
* readout, and the degree follows the same rule).
|
|
1054
|
+
*/
|
|
924
1055
|
export const Degree: Story = {
|
|
925
1056
|
render: () =>
|
|
926
1057
|
renderShowcase([
|
|
@@ -950,6 +1081,35 @@ export const Degree: Story = {
|
|
|
950
1081
|
},
|
|
951
1082
|
],
|
|
952
1083
|
},
|
|
1084
|
+
{
|
|
1085
|
+
title: 'Degree on The Actual Value Only (setpoint / Advice Carry None)',
|
|
1086
|
+
columns: 2,
|
|
1087
|
+
cases: [
|
|
1088
|
+
{
|
|
1089
|
+
label: 'vertical / setpoint + advice',
|
|
1090
|
+
config: {
|
|
1091
|
+
label: 'HDG',
|
|
1092
|
+
unit: 'DEG',
|
|
1093
|
+
hasSetpoint: true,
|
|
1094
|
+
hasAdvice: true,
|
|
1095
|
+
options: {hasDegree: true},
|
|
1096
|
+
},
|
|
1097
|
+
},
|
|
1098
|
+
{
|
|
1099
|
+
label: 'horizontal / setpoint + advice',
|
|
1100
|
+
config: {
|
|
1101
|
+
label: 'HDG',
|
|
1102
|
+
unit: 'DEG',
|
|
1103
|
+
hasSetpoint: true,
|
|
1104
|
+
hasAdvice: true,
|
|
1105
|
+
options: {
|
|
1106
|
+
hasDegree: true,
|
|
1107
|
+
direction: ReadoutDirection.horizontal,
|
|
1108
|
+
},
|
|
1109
|
+
},
|
|
1110
|
+
},
|
|
1111
|
+
],
|
|
1112
|
+
},
|
|
953
1113
|
]),
|
|
954
1114
|
};
|
|
955
1115
|
|
|
@@ -1451,3 +1611,360 @@ export const TestCases: Story = {
|
|
|
1451
1611
|
</div>`;
|
|
1452
1612
|
},
|
|
1453
1613
|
};
|
|
1614
|
+
|
|
1615
|
+
/**
|
|
1616
|
+
* Figma 6.1 "Equal size": value and setpoint always share the primary size —
|
|
1617
|
+
* the missing fourth mode beside primary-secondary (`always-visible`),
|
|
1618
|
+
* flip-flop and pop-up. Static in both states; only flip-flop / pop-up
|
|
1619
|
+
* resize or hide at runtime — see the `SetpointEqualSizeAnimated` story for
|
|
1620
|
+
* the in-motion contrast. `touching` keeps the setpoint at the primary size
|
|
1621
|
+
* (it only adds the SemiBold focus weight and marker highlight), and the
|
|
1622
|
+
* marker arrow follows the block's rendered size, so an equal-size setpoint
|
|
1623
|
+
* carries the large arrow. The sizing rule lives in `readoutSetpointSize()`
|
|
1624
|
+
* (`readout-shared.ts`, unit-tested), shared with `obc-readout-list-item` /
|
|
1625
|
+
* `obc-readout`.
|
|
1626
|
+
*/
|
|
1627
|
+
export const SetpointEqualSize: Story = {
|
|
1628
|
+
render: () =>
|
|
1629
|
+
renderShowcase([
|
|
1630
|
+
{
|
|
1631
|
+
title: 'Equal Size — Off/At Setpoint × Direction',
|
|
1632
|
+
columns: 2,
|
|
1633
|
+
cases: [ReadoutDirection.vertical, ReadoutDirection.horizontal].flatMap(
|
|
1634
|
+
(direction) =>
|
|
1635
|
+
[123, 120].map((value) => ({
|
|
1636
|
+
label: `${direction} / ${value === 120 ? 'at' : 'off'} setpoint`,
|
|
1637
|
+
config: {
|
|
1638
|
+
value,
|
|
1639
|
+
hasSetpoint: true,
|
|
1640
|
+
setpoint: 120,
|
|
1641
|
+
options: {
|
|
1642
|
+
size: ReadoutSize.large,
|
|
1643
|
+
priority: ReadoutPriority.enhanced,
|
|
1644
|
+
direction,
|
|
1645
|
+
setpoint: {
|
|
1646
|
+
interaction: ReadoutSetpointInteraction.equalSize,
|
|
1647
|
+
},
|
|
1648
|
+
},
|
|
1649
|
+
},
|
|
1650
|
+
}))
|
|
1651
|
+
),
|
|
1652
|
+
},
|
|
1653
|
+
]),
|
|
1654
|
+
};
|
|
1655
|
+
|
|
1656
|
+
/**
|
|
1657
|
+
* Label ("readout-block-title") options — Figma 6.1. Large readouts default
|
|
1658
|
+
* the label to textbox `s` (a scannable label should not sit at the smallest
|
|
1659
|
+
* size); `labelOptions.size` opts a tight layout back down to `xs`, and
|
|
1660
|
+
* `labelOptions.spaceReserver` aligns ragged labels across stacked readouts
|
|
1661
|
+
* (the legacy `AlignMultiple` gap). The label is SemiBold only on enhanced
|
|
1662
|
+
* readouts.
|
|
1663
|
+
*/
|
|
1664
|
+
export const LabelOptions: Story = {
|
|
1665
|
+
render: () =>
|
|
1666
|
+
renderShowcase([
|
|
1667
|
+
{
|
|
1668
|
+
title: 'Label size — tier default vs explicit',
|
|
1669
|
+
columns: 3,
|
|
1670
|
+
cases: [
|
|
1671
|
+
{
|
|
1672
|
+
label: 'large / default (s)',
|
|
1673
|
+
config: {options: {size: ReadoutSize.large}},
|
|
1674
|
+
},
|
|
1675
|
+
{
|
|
1676
|
+
label: 'large / xs override',
|
|
1677
|
+
config: {
|
|
1678
|
+
options: {
|
|
1679
|
+
size: ReadoutSize.large,
|
|
1680
|
+
label: {size: ObcTextboxSize.xs},
|
|
1681
|
+
},
|
|
1682
|
+
},
|
|
1683
|
+
},
|
|
1684
|
+
{
|
|
1685
|
+
label: 'small / default (xs)',
|
|
1686
|
+
config: {options: {size: ReadoutSize.small}},
|
|
1687
|
+
},
|
|
1688
|
+
],
|
|
1689
|
+
},
|
|
1690
|
+
{
|
|
1691
|
+
title: 'Label weight — regular vs enhanced priority',
|
|
1692
|
+
columns: 2,
|
|
1693
|
+
cases: [
|
|
1694
|
+
{
|
|
1695
|
+
label: 'regular (label regular)',
|
|
1696
|
+
config: {
|
|
1697
|
+
options: {
|
|
1698
|
+
size: ReadoutSize.large,
|
|
1699
|
+
priority: ReadoutPriority.regular,
|
|
1700
|
+
},
|
|
1701
|
+
},
|
|
1702
|
+
},
|
|
1703
|
+
{
|
|
1704
|
+
label: 'enhanced (label semibold)',
|
|
1705
|
+
config: {
|
|
1706
|
+
options: {
|
|
1707
|
+
size: ReadoutSize.large,
|
|
1708
|
+
priority: ReadoutPriority.enhanced,
|
|
1709
|
+
},
|
|
1710
|
+
},
|
|
1711
|
+
},
|
|
1712
|
+
],
|
|
1713
|
+
},
|
|
1714
|
+
{
|
|
1715
|
+
title: 'Label reserver — stacked readouts align',
|
|
1716
|
+
columns: 1,
|
|
1717
|
+
cases: [
|
|
1718
|
+
{
|
|
1719
|
+
label: 'labelOptions.spaceReserver: "DEPTH"',
|
|
1720
|
+
config: {
|
|
1721
|
+
label: 'SOG',
|
|
1722
|
+
options: {
|
|
1723
|
+
size: ReadoutSize.large,
|
|
1724
|
+
stacking: ReadoutStacking.stacked,
|
|
1725
|
+
label: {spaceReserver: 'DEPTH'},
|
|
1726
|
+
},
|
|
1727
|
+
},
|
|
1728
|
+
},
|
|
1729
|
+
],
|
|
1730
|
+
},
|
|
1731
|
+
]),
|
|
1732
|
+
};
|
|
1733
|
+
|
|
1734
|
+
/** The `leading-icon` slot before the label/unit meta zone (Figma `has Leading icon`). */
|
|
1735
|
+
export const LeadingIcon: Story = {
|
|
1736
|
+
render: () =>
|
|
1737
|
+
renderShowcase([
|
|
1738
|
+
{
|
|
1739
|
+
title: 'Leading icon × size',
|
|
1740
|
+
columns: 3,
|
|
1741
|
+
cases: SIZES.map((size) => ({
|
|
1742
|
+
label: size,
|
|
1743
|
+
config: {options: {size, hasLeadingIcon: true}},
|
|
1744
|
+
})),
|
|
1745
|
+
},
|
|
1746
|
+
{
|
|
1747
|
+
title: 'Leading icon — horizontal',
|
|
1748
|
+
columns: 1,
|
|
1749
|
+
cases: [
|
|
1750
|
+
{
|
|
1751
|
+
label: 'horizontal / large',
|
|
1752
|
+
config: {
|
|
1753
|
+
options: {
|
|
1754
|
+
size: ReadoutSize.large,
|
|
1755
|
+
direction: ReadoutDirection.horizontal,
|
|
1756
|
+
hasLeadingIcon: true,
|
|
1757
|
+
},
|
|
1758
|
+
},
|
|
1759
|
+
},
|
|
1760
|
+
],
|
|
1761
|
+
},
|
|
1762
|
+
]),
|
|
1763
|
+
};
|
|
1764
|
+
|
|
1765
|
+
/**
|
|
1766
|
+
* Advice semantic categories (Figma 6.1 Readout-block-advice): resting
|
|
1767
|
+
* categories carry a neutral outline marker; `active` swaps in the filled /
|
|
1768
|
+
* status icon and the triggered text styling. See the Readout Block
|
|
1769
|
+
* `AdviceCategories` story for the full per-block matrix.
|
|
1770
|
+
*/
|
|
1771
|
+
export const AdviceCategories: Story = {
|
|
1772
|
+
render: () =>
|
|
1773
|
+
renderShowcase([
|
|
1774
|
+
{
|
|
1775
|
+
title: 'Advice categories — resting vs active',
|
|
1776
|
+
columns: 7,
|
|
1777
|
+
cases: Object.values(ReadoutAdviceCategory).flatMap((category) =>
|
|
1778
|
+
[false, true].map((active) => ({
|
|
1779
|
+
label: `${category}${active ? ' / active' : ''}`,
|
|
1780
|
+
config: {
|
|
1781
|
+
hasAdvice: true,
|
|
1782
|
+
options: {
|
|
1783
|
+
size: ReadoutSize.large,
|
|
1784
|
+
advice: {category, active},
|
|
1785
|
+
},
|
|
1786
|
+
},
|
|
1787
|
+
}))
|
|
1788
|
+
),
|
|
1789
|
+
},
|
|
1790
|
+
]),
|
|
1791
|
+
};
|
|
1792
|
+
|
|
1793
|
+
/**
|
|
1794
|
+
* Source states + deviation (Figma 6.1 Readout-block-source): `enhanced`
|
|
1795
|
+
* renders the amplified chip, `caution` / `warning` the alert chip, and
|
|
1796
|
+
* `deviation` adds the Δ line under the source name. The chips use `outline`
|
|
1797
|
+
* so a live state change never shifts the layout.
|
|
1798
|
+
*/
|
|
1799
|
+
export const SourceStates: Story = {
|
|
1800
|
+
render: () =>
|
|
1801
|
+
renderShowcase([
|
|
1802
|
+
{
|
|
1803
|
+
title: 'Source state × deviation',
|
|
1804
|
+
columns: 4,
|
|
1805
|
+
cases: Object.values(ReadoutSourceState).flatMap((state) =>
|
|
1806
|
+
[undefined, 0.5].map((deviation) => ({
|
|
1807
|
+
label: `${state}${deviation !== undefined ? ' / Δ' : ''}`,
|
|
1808
|
+
config: {
|
|
1809
|
+
src: 'GPS 1',
|
|
1810
|
+
options: {
|
|
1811
|
+
size: ReadoutSize.large,
|
|
1812
|
+
src: {state, deviation},
|
|
1813
|
+
},
|
|
1814
|
+
},
|
|
1815
|
+
}))
|
|
1816
|
+
),
|
|
1817
|
+
},
|
|
1818
|
+
]),
|
|
1819
|
+
};
|
|
1820
|
+
|
|
1821
|
+
/**
|
|
1822
|
+
* TODO(designer): open question from the 6.1 review — while a pop-up setpoint
|
|
1823
|
+
* is hidden at-setpoint, should the reading keep a setpoint arrow so it still
|
|
1824
|
+
* reads as "a value you are in control of"? The existing `value-icon` slot
|
|
1825
|
+
* already expresses that today, demonstrated here; no new API until decided.
|
|
1826
|
+
*/
|
|
1827
|
+
export const SetpointPopUpWithValueArrow: Story = {
|
|
1828
|
+
render: () => html`
|
|
1829
|
+
<style>
|
|
1830
|
+
${showcaseStyle}
|
|
1831
|
+
</style>
|
|
1832
|
+
<div class="ro-sections">
|
|
1833
|
+
<p class="ro-note">
|
|
1834
|
+
Pop-up at setpoint, with an <code>obi-input-right</code> slotted into
|
|
1835
|
+
<code>value-icon</code> so the collapsed reading keeps the in-control
|
|
1836
|
+
marker.
|
|
1837
|
+
</p>
|
|
1838
|
+
<obc-readout
|
|
1839
|
+
.label=${'HDG'}
|
|
1840
|
+
.unit=${'/min'}
|
|
1841
|
+
.src=${'Source'}
|
|
1842
|
+
.value=${10}
|
|
1843
|
+
.hasSetpoint=${true}
|
|
1844
|
+
.setpoint=${10}
|
|
1845
|
+
.size=${ReadoutSize.large}
|
|
1846
|
+
.priority=${ReadoutPriority.enhanced}
|
|
1847
|
+
.setpointOptions=${{interaction: ReadoutSetpointInteraction.popUp}}
|
|
1848
|
+
.valueOptions=${{hasIcon: true}}
|
|
1849
|
+
>
|
|
1850
|
+
<obi-input-right slot="value-icon"></obi-input-right>
|
|
1851
|
+
</obc-readout>
|
|
1852
|
+
</div>
|
|
1853
|
+
`,
|
|
1854
|
+
};
|
|
1855
|
+
|
|
1856
|
+
// ---------------------------------------------------------------------------
|
|
1857
|
+
// Figma 6.1 bird's-eye matrices — static expansions of the design file's
|
|
1858
|
+
// component sheets (parent node 46596-102878), so every combination can be
|
|
1859
|
+
// reviewed at a glance without touching controls:
|
|
1860
|
+
// - Readout-vertical-trailing-title (46390-197995): Size × Priority ×
|
|
1861
|
+
// Value priority × State × has Degree — split into one story per
|
|
1862
|
+
// interaction below so each snapshot stays a reviewable size. The
|
|
1863
|
+
// `has Leading icon` axis is covered by the LeadingIcon story, and the
|
|
1864
|
+
// Readout-vertical-block sheet (46551-303919) differs only in title sizing
|
|
1865
|
+
// (tracked by the medium-tier label TODO); the leading-title sheet
|
|
1866
|
+
// (46551-341292) is marked WIP in Figma and deliberately not expanded.
|
|
1867
|
+
// - Readout-horizontal (46471-75814): large-only, one story. Its
|
|
1868
|
+
// leading-label stacking column is obc-readout-list-item's job (see the
|
|
1869
|
+
// Readout List Item FigmaMatrix story).
|
|
1870
|
+
// ---------------------------------------------------------------------------
|
|
1871
|
+
|
|
1872
|
+
const MATRIX_PRIORITIES = [
|
|
1873
|
+
ReadoutPriority.regular,
|
|
1874
|
+
ReadoutPriority.enhanced,
|
|
1875
|
+
] as const;
|
|
1876
|
+
|
|
1877
|
+
/** The composite sheets' State axis (At/Not-at setpoint, Low integrity, Invalid). */
|
|
1878
|
+
const MATRIX_STATES: {
|
|
1879
|
+
key: string;
|
|
1880
|
+
value: number;
|
|
1881
|
+
dataQuality?: ReadoutDataQuality;
|
|
1882
|
+
}[] = [
|
|
1883
|
+
{key: 'off setpoint', value: 123},
|
|
1884
|
+
{key: 'at setpoint', value: 120},
|
|
1885
|
+
{
|
|
1886
|
+
key: 'low-integrity',
|
|
1887
|
+
value: 123,
|
|
1888
|
+
dataQuality: ReadoutDataQuality.lowIntegrity,
|
|
1889
|
+
},
|
|
1890
|
+
{key: 'invalid', value: 123, dataQuality: ReadoutDataQuality.invalid},
|
|
1891
|
+
];
|
|
1892
|
+
|
|
1893
|
+
function verticalMatrixStory(
|
|
1894
|
+
interaction: ReadoutSetpointInteraction
|
|
1895
|
+
): Story['render'] {
|
|
1896
|
+
return () =>
|
|
1897
|
+
renderShowcase(
|
|
1898
|
+
MATRIX_STATES.map((state) => ({
|
|
1899
|
+
title: `${interaction} — ${state.key}`,
|
|
1900
|
+
columns: 4,
|
|
1901
|
+
cases: SIZES.flatMap((size) =>
|
|
1902
|
+
MATRIX_PRIORITIES.flatMap((priority) =>
|
|
1903
|
+
[false, true].map((hasDegree) => ({
|
|
1904
|
+
label: `${size} / ${priority}${hasDegree ? ' / °' : ''}`,
|
|
1905
|
+
config: {
|
|
1906
|
+
value: state.value,
|
|
1907
|
+
hasSetpoint: true,
|
|
1908
|
+
setpoint: 120,
|
|
1909
|
+
hasAdvice: true,
|
|
1910
|
+
options: {
|
|
1911
|
+
size,
|
|
1912
|
+
priority,
|
|
1913
|
+
hasDegree,
|
|
1914
|
+
dataQuality: state.dataQuality,
|
|
1915
|
+
setpoint: {interaction},
|
|
1916
|
+
},
|
|
1917
|
+
},
|
|
1918
|
+
}))
|
|
1919
|
+
)
|
|
1920
|
+
),
|
|
1921
|
+
}))
|
|
1922
|
+
);
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
export const FigmaMatrixVerticalAlwaysVisible: Story = {
|
|
1926
|
+
render: verticalMatrixStory(ReadoutSetpointInteraction.alwaysVisible),
|
|
1927
|
+
};
|
|
1928
|
+
|
|
1929
|
+
export const FigmaMatrixVerticalEqualSize: Story = {
|
|
1930
|
+
render: verticalMatrixStory(ReadoutSetpointInteraction.equalSize),
|
|
1931
|
+
};
|
|
1932
|
+
|
|
1933
|
+
export const FigmaMatrixVerticalFlipFlop: Story = {
|
|
1934
|
+
render: verticalMatrixStory(ReadoutSetpointInteraction.flipFlop),
|
|
1935
|
+
};
|
|
1936
|
+
|
|
1937
|
+
export const FigmaMatrixVerticalPopUp: Story = {
|
|
1938
|
+
render: verticalMatrixStory(ReadoutSetpointInteraction.popUp),
|
|
1939
|
+
};
|
|
1940
|
+
|
|
1941
|
+
export const FigmaMatrixHorizontal: Story = {
|
|
1942
|
+
render: () =>
|
|
1943
|
+
renderShowcase(
|
|
1944
|
+
INTERACTIONS.map((interaction) => ({
|
|
1945
|
+
title: `${interaction}`,
|
|
1946
|
+
columns: 4,
|
|
1947
|
+
cases: MATRIX_STATES.flatMap((state) =>
|
|
1948
|
+
MATRIX_PRIORITIES.flatMap((priority) =>
|
|
1949
|
+
[false, true].map((hasDegree) => ({
|
|
1950
|
+
label: `${state.key} / ${priority}${hasDegree ? ' / °' : ''}`,
|
|
1951
|
+
config: {
|
|
1952
|
+
value: state.value,
|
|
1953
|
+
hasSetpoint: true,
|
|
1954
|
+
setpoint: 120,
|
|
1955
|
+
hasAdvice: true,
|
|
1956
|
+
src: 'GPS 1',
|
|
1957
|
+
options: {
|
|
1958
|
+
direction: ReadoutDirection.horizontal,
|
|
1959
|
+
priority,
|
|
1960
|
+
hasDegree,
|
|
1961
|
+
dataQuality: state.dataQuality,
|
|
1962
|
+
setpoint: {interaction},
|
|
1963
|
+
},
|
|
1964
|
+
},
|
|
1965
|
+
}))
|
|
1966
|
+
)
|
|
1967
|
+
),
|
|
1968
|
+
}))
|
|
1969
|
+
),
|
|
1970
|
+
};
|