@oicl/openbridge-webcomponents-full-bundle 2.0.0-next.151 → 2.0.0-next.152
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/.storybook/vitest.setup.ts +12 -1
- package/bundle/openbridge-webcomponents.bundle.js +989 -319
- package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
- package/custom-elements.json +1514 -77
- package/dist/alert-severity.d.ts +12 -9
- package/dist/alert-severity.d.ts.map +1 -1
- package/dist/alert-severity.js +30 -38
- package/dist/alert-severity.js.map +1 -1
- package/dist/building-blocks/bar-horizontal/bar-horizontal.d.ts +6 -0
- package/dist/building-blocks/bar-horizontal/bar-horizontal.d.ts.map +1 -1
- package/dist/building-blocks/bar-horizontal/bar-horizontal.js +6 -1
- package/dist/building-blocks/bar-horizontal/bar-horizontal.js.map +1 -1
- package/dist/building-blocks/bar-vertical/bar-vertical.d.ts +6 -0
- package/dist/building-blocks/bar-vertical/bar-vertical.d.ts.map +1 -1
- package/dist/building-blocks/bar-vertical/bar-vertical.js +6 -1
- package/dist/building-blocks/bar-vertical/bar-vertical.js.map +1 -1
- package/dist/building-blocks/chart-line/chart-line-base.d.ts +129 -0
- package/dist/building-blocks/chart-line/chart-line-base.d.ts.map +1 -1
- package/dist/building-blocks/chart-line/chart-line-base.js +464 -79
- package/dist/building-blocks/chart-line/chart-line-base.js.map +1 -1
- package/dist/building-blocks/external-scale/external-scale.d.ts +11 -0
- package/dist/building-blocks/external-scale/external-scale.d.ts.map +1 -1
- package/dist/building-blocks/external-scale/external-scale.js +45 -12
- package/dist/building-blocks/external-scale/external-scale.js.map +1 -1
- package/dist/charthelpers/index.d.ts +1 -0
- package/dist/charthelpers/index.d.ts.map +1 -1
- package/dist/charthelpers/index.js +7 -1
- package/dist/charthelpers/index.js.map +1 -1
- package/dist/charthelpers/range-labels.d.ts +55 -0
- package/dist/charthelpers/range-labels.d.ts.map +1 -0
- package/dist/charthelpers/range-labels.js +36 -0
- package/dist/charthelpers/range-labels.js.map +1 -0
- package/dist/components/alert-button/alert-button.css.js +13 -21
- package/dist/components/alert-button/alert-button.css.js.map +1 -1
- package/dist/components/alert-button/alert-button.d.ts +9 -4
- package/dist/components/alert-button/alert-button.d.ts.map +1 -1
- package/dist/components/alert-button/alert-button.js +24 -15
- package/dist/components/alert-button/alert-button.js.map +1 -1
- package/dist/components/alert-frame/alert-frame.css.js +109 -33
- package/dist/components/alert-frame/alert-frame.css.js.map +1 -1
- package/dist/components/alert-frame/alert-frame.d.ts +34 -7
- package/dist/components/alert-frame/alert-frame.d.ts.map +1 -1
- package/dist/components/alert-frame/alert-frame.js +134 -30
- package/dist/components/alert-frame/alert-frame.js.map +1 -1
- package/dist/components/alert-icon/alert-icon.d.ts +10 -7
- package/dist/components/alert-icon/alert-icon.d.ts.map +1 -1
- package/dist/components/alert-icon/alert-icon.js +37 -60
- package/dist/components/alert-icon/alert-icon.js.map +1 -1
- package/dist/components/alert-menu-item/alert-menu-item.css.js +1 -4
- package/dist/components/alert-menu-item/alert-menu-item.css.js.map +1 -1
- package/dist/components/date-item/date-item.css.js +3 -3
- package/dist/components/keyboard-full/keyboard-full.css.js +4 -4
- package/dist/components/message-menu-item/message-menu-item.css.js +2 -6
- package/dist/components/message-menu-item/message-menu-item.css.js.map +1 -1
- package/dist/components/sequence-toolbar/sequence-toolbar.css.js +1 -2
- package/dist/components/sequence-toolbar/sequence-toolbar.css.js.map +1 -1
- package/dist/index.js +2 -1
- package/dist/navigation-instruments/gauge-trend/gauge-trend.d.ts +6 -0
- package/dist/navigation-instruments/gauge-trend/gauge-trend.d.ts.map +1 -1
- package/dist/navigation-instruments/gauge-trend/gauge-trend.js +8 -0
- package/dist/navigation-instruments/gauge-trend/gauge-trend.js.map +1 -1
- package/dist/navigation-instruments/instrument-field/instrument-field.css.js +2 -2
- package/dist/navigation-instruments/readout/readout.d.ts.map +1 -1
- package/dist/navigation-instruments/readout/readout.js +2 -1
- package/dist/navigation-instruments/readout/readout.js.map +1 -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 +2 -1
- package/dist/navigation-instruments/readout-list-item/readout-list-item.js.map +1 -1
- package/dist/openbridge.css +19 -4
- package/dist/palettes/blinking.d.ts +14 -4
- package/dist/palettes/blinking.d.ts.map +1 -1
- package/dist/palettes/blinking.js +41 -35
- package/dist/palettes/blinking.js.map +1 -1
- package/dist/palettes/flashing-controller.d.ts +21 -0
- package/dist/palettes/flashing-controller.d.ts.map +1 -0
- package/dist/palettes/flashing-controller.js +45 -0
- package/dist/palettes/flashing-controller.js.map +1 -0
- package/dist/svghelpers/index.d.ts +1 -0
- package/dist/svghelpers/index.d.ts.map +1 -1
- package/dist/svghelpers/index.js +2 -0
- package/dist/svghelpers/index.js.map +1 -1
- package/dist/svghelpers/rounded-rect.d.ts +15 -0
- package/dist/svghelpers/rounded-rect.d.ts.map +1 -0
- package/dist/svghelpers/rounded-rect.js +29 -0
- package/dist/svghelpers/rounded-rect.js.map +1 -0
- package/dist/types.d.ts +14 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
- package/script/check-css-variables.ts +2 -15
- package/src/alert-severity.spec.ts +56 -0
- package/src/alert-severity.ts +45 -43
- package/src/bars-graphs/area-graph/area-graph.stories.ts +235 -1
- package/src/bars-graphs/line-graph/line-graph.stories.ts +24 -0
- package/src/building-blocks/bar-horizontal/bar-horizontal.ts +7 -0
- package/src/building-blocks/bar-vertical/bar-vertical.ts +7 -0
- package/src/building-blocks/chart-line/chart-line-base.spec.ts +767 -0
- package/src/building-blocks/chart-line/chart-line-base.stories.ts +124 -0
- package/src/building-blocks/chart-line/chart-line-base.ts +671 -97
- package/src/building-blocks/chart-line/chart-sizing-battleground.stories.ts +17 -0
- package/src/building-blocks/external-scale/external-scale.spec.ts +154 -0
- package/src/building-blocks/external-scale/external-scale.ts +78 -20
- package/src/charthelpers/index.ts +1 -0
- package/src/charthelpers/range-labels.spec.ts +46 -0
- package/src/charthelpers/range-labels.ts +93 -0
- package/src/components/alert-button/alert-button.css +10 -23
- package/src/components/alert-button/alert-button.spec.ts +56 -15
- package/src/components/alert-button/alert-button.stories.ts +5 -1
- package/src/components/alert-button/alert-button.ts +33 -24
- package/src/components/alert-frame/alert-flash-scenario.stories.ts +669 -0
- package/src/components/alert-frame/alert-frame.css +106 -33
- package/src/components/alert-frame/alert-frame.spec.ts +176 -17
- package/src/components/alert-frame/alert-frame.stories.ts +61 -0
- package/src/components/alert-frame/alert-frame.ts +179 -41
- package/src/components/alert-icon/alert-icon.spec.ts +82 -27
- package/src/components/alert-icon/alert-icon.stories.ts +7 -1
- package/src/components/alert-icon/alert-icon.ts +48 -74
- package/src/components/alert-menu-item/alert-menu-item.css +1 -4
- package/src/components/date-item/date-item.css +3 -3
- package/src/components/keyboard-full/keyboard-full.css +4 -4
- package/src/components/message-menu-item/message-menu-item.css +2 -6
- package/src/components/sequence-toolbar/sequence-toolbar.css +1 -2
- package/src/navigation-instruments/gauge-trend/gauge-trend.stories.ts +29 -0
- package/src/navigation-instruments/gauge-trend/gauge-trend.ts +11 -0
- package/src/navigation-instruments/instrument-field/instrument-field.css +2 -2
- package/src/navigation-instruments/readout/readout.ts +2 -1
- package/src/navigation-instruments/readout-list-item/readout-list-item.ts +2 -1
- package/src/palettes/blinking.spec.ts +83 -0
- package/src/palettes/blinking.ts +47 -35
- package/src/palettes/flashing-controller.ts +62 -0
- package/src/palettes/manual.css +18 -4
- package/src/svghelpers/index.ts +1 -0
- package/src/svghelpers/rounded-rect.spec.ts +47 -0
- package/src/svghelpers/rounded-rect.ts +42 -0
- package/src/types.ts +20 -0
|
@@ -27,8 +27,6 @@
|
|
|
27
27
|
width: 100%;
|
|
28
28
|
max-width: var(--menu-navigation-components-date-item-touch-target);
|
|
29
29
|
height: var(--menu-navigation-components-date-item-touch-target);
|
|
30
|
-
padding: var(--menu-navigation-components-date-item-padding-vertical)
|
|
31
|
-
var(--menu-navigation-components-date-item-padding-horizontal);
|
|
32
30
|
|
|
33
31
|
/* Keyboard press visual feedback */
|
|
34
32
|
&.pressing .date-container {
|
|
@@ -175,7 +173,9 @@
|
|
|
175
173
|
display: flex;
|
|
176
174
|
width: var(--menu-navigation-components-date-item-touch-target, 48px);
|
|
177
175
|
height: var(--menu-navigation-components-date-item-touch-target, 48px);
|
|
178
|
-
|
|
176
|
+
/* TODO(designer): Figma pads this frame with Date item/padding-bottom, 12 and 16px in
|
|
177
|
+
large and xl, less room than the date container needs; 8px fits every size (#929) */
|
|
178
|
+
padding: 8px
|
|
179
179
|
var(--menu-navigation-components-date-item-padding-horizontal, 8px);
|
|
180
180
|
flex-direction: column;
|
|
181
181
|
justify-content: center;
|
|
@@ -109,8 +109,8 @@ obc-input::part(input) {
|
|
|
109
109
|
.key-button {
|
|
110
110
|
display: flex;
|
|
111
111
|
flex: 1 0 0;
|
|
112
|
-
min-width: var(--ui-components-keyboard-
|
|
113
|
-
min-height: var(--ui-components-keyboard-
|
|
112
|
+
min-width: var(--ui-components-keyboard-button-size-min);
|
|
113
|
+
min-height: var(--ui-components-keyboard-button-size-min);
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
obc-button.key-button::part(wrapper) {
|
|
@@ -121,8 +121,8 @@ obc-button.key-button::part(visible-wrapper) {
|
|
|
121
121
|
box-sizing: border-box;
|
|
122
122
|
display: flex;
|
|
123
123
|
width: 100%;
|
|
124
|
-
min-width: var(--ui-components-keyboard-
|
|
125
|
-
min-height: var(--ui-components-keyboard-
|
|
124
|
+
min-width: var(--ui-components-keyboard-button-size-min);
|
|
125
|
+
min-height: var(--ui-components-keyboard-button-size-min);
|
|
126
126
|
align-items: center;
|
|
127
127
|
justify-content: center;
|
|
128
128
|
align-self: stretch;
|
|
@@ -167,12 +167,8 @@
|
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
.trailing-icon {
|
|
170
|
-
width: var(
|
|
171
|
-
|
|
172
|
-
);
|
|
173
|
-
height: var(
|
|
174
|
-
--app-components-alert-components-general-notification-item-icon-size-large
|
|
175
|
-
);
|
|
170
|
+
width: var(--app-components-message-menu-item-icon-size-large);
|
|
171
|
+
height: var(--app-components-message-menu-item-icon-size-large);
|
|
176
172
|
display: flex;
|
|
177
173
|
align-items: center;
|
|
178
174
|
justify-content: center;
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
align-items: center;
|
|
13
13
|
padding: 5px;
|
|
14
14
|
border: 1px solid var(--border-outline-color);
|
|
15
|
-
background-color: var(--
|
|
15
|
+
background-color: var(--container-global-color);
|
|
16
16
|
|
|
17
17
|
&.type-sequential,
|
|
18
18
|
&.type-unordered {
|
|
@@ -28,7 +28,6 @@
|
|
|
28
28
|
|
|
29
29
|
&.type-condensed {
|
|
30
30
|
border-radius: 100px;
|
|
31
|
-
background-color: var(--normal-enabled-background-color);
|
|
32
31
|
|
|
33
32
|
.condensed-label__current {
|
|
34
33
|
font-weight: var(--font-weight-Bold, 670);
|
|
@@ -170,6 +170,10 @@ const meta: Meta = {
|
|
|
170
170
|
chartFill: {
|
|
171
171
|
control: 'boolean',
|
|
172
172
|
},
|
|
173
|
+
rangeLabels: {
|
|
174
|
+
control: {type: 'radio'},
|
|
175
|
+
options: ['none', 'y', 'x', 'xy'],
|
|
176
|
+
},
|
|
173
177
|
touching: {
|
|
174
178
|
control: 'boolean',
|
|
175
179
|
},
|
|
@@ -190,6 +194,7 @@ const meta: Meta = {
|
|
|
190
194
|
fillMin: 0,
|
|
191
195
|
// Note: fillMax intentionally omitted - in 'fill' mode it auto-derives from value
|
|
192
196
|
chartFill: true,
|
|
197
|
+
rangeLabels: 'none',
|
|
193
198
|
touching: false,
|
|
194
199
|
},
|
|
195
200
|
render: (args) => html`
|
|
@@ -199,6 +204,7 @@ const meta: Meta = {
|
|
|
199
204
|
.height=${args.height}
|
|
200
205
|
.priority=${args.priority}
|
|
201
206
|
.chartFill=${args.chartFill}
|
|
207
|
+
.rangeLabels=${args.rangeLabels}
|
|
202
208
|
.minValue=${args.minValue}
|
|
203
209
|
.maxValue=${args.maxValue}
|
|
204
210
|
.value=${args.value}
|
|
@@ -242,6 +248,7 @@ export const GaugeTrend: Story = {
|
|
|
242
248
|
.height=${_args.height}
|
|
243
249
|
.priority=${_args.priority}
|
|
244
250
|
.chartFill=${_args.chartFill}
|
|
251
|
+
.rangeLabels=${_args.rangeLabels}
|
|
245
252
|
.minValue=${_args.minValue ?? 0}
|
|
246
253
|
.maxValue=${_args.maxValue ?? 100}
|
|
247
254
|
.value=${_args.value}
|
|
@@ -266,6 +273,21 @@ export const GaugeTrend: Story = {
|
|
|
266
273
|
`,
|
|
267
274
|
};
|
|
268
275
|
|
|
276
|
+
export const CompactRangeLabels: Story = {
|
|
277
|
+
name: 'Compact With Range Labels (160px)',
|
|
278
|
+
play: async () => {
|
|
279
|
+
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
280
|
+
},
|
|
281
|
+
args: {
|
|
282
|
+
browserContainerWidth: 160,
|
|
283
|
+
width: 160,
|
|
284
|
+
height: 160,
|
|
285
|
+
rangeLabels: 'xy',
|
|
286
|
+
hasBar: true,
|
|
287
|
+
hasScale: true,
|
|
288
|
+
},
|
|
289
|
+
};
|
|
290
|
+
|
|
269
291
|
export const UnevenTimeIntervals: Story = {
|
|
270
292
|
name: 'Uneven Time Intervals (Auto Time Axis)',
|
|
271
293
|
play: async () => {
|
|
@@ -279,6 +301,7 @@ export const UnevenTimeIntervals: Story = {
|
|
|
279
301
|
.height=${_args.height}
|
|
280
302
|
.priority=${_args.priority}
|
|
281
303
|
.chartFill=${_args.chartFill}
|
|
304
|
+
.rangeLabels=${_args.rangeLabels}
|
|
282
305
|
.minValue=${_args.minValue ?? 0}
|
|
283
306
|
.maxValue=${_args.maxValue ?? 100}
|
|
284
307
|
.value=${_args.value}
|
|
@@ -311,6 +334,7 @@ export const GaugeTrendScaleReferenceSize: Story = {
|
|
|
311
334
|
.height=${_args.height}
|
|
312
335
|
.priority=${_args.priority}
|
|
313
336
|
.chartFill=${_args.chartFill}
|
|
337
|
+
.rangeLabels=${_args.rangeLabels}
|
|
314
338
|
.minValue=${_args.minValue ?? 0}
|
|
315
339
|
.maxValue=${_args.maxValue ?? 100}
|
|
316
340
|
.value=${_args.value}
|
|
@@ -531,6 +555,7 @@ export const GaugeTrendWithoutScale: Story = {
|
|
|
531
555
|
.height=${_args.height}
|
|
532
556
|
.priority=${_args.priority}
|
|
533
557
|
.chartFill=${_args.chartFill}
|
|
558
|
+
.rangeLabels=${_args.rangeLabels}
|
|
534
559
|
.minValue=${_args.minValue ?? 0}
|
|
535
560
|
.maxValue=${_args.maxValue ?? 100}
|
|
536
561
|
.value=${_args.value}
|
|
@@ -572,6 +597,7 @@ export const GaugeTrendWithoutBar: Story = {
|
|
|
572
597
|
.height=${_args.height}
|
|
573
598
|
.priority=${_args.priority}
|
|
574
599
|
.chartFill=${_args.chartFill}
|
|
600
|
+
.rangeLabels=${_args.rangeLabels}
|
|
575
601
|
.minValue=${_args.minValue ?? 0}
|
|
576
602
|
.maxValue=${_args.maxValue ?? 100}
|
|
577
603
|
.value=${_args.value}
|
|
@@ -617,6 +643,7 @@ export const GaugeTrendWithAdvice: Story = {
|
|
|
617
643
|
.height=${_args.height}
|
|
618
644
|
.priority=${_args.priority}
|
|
619
645
|
.chartFill=${_args.chartFill}
|
|
646
|
+
.rangeLabels=${_args.rangeLabels}
|
|
620
647
|
.minValue=${_args.minValue ?? 0}
|
|
621
648
|
.maxValue=${_args.maxValue ?? 100}
|
|
622
649
|
.value=${_args.value}
|
|
@@ -708,6 +735,7 @@ export const GaugeTrendCustomScaleRange: Story = {
|
|
|
708
735
|
.height=${_args.height}
|
|
709
736
|
.priority=${_args.priority}
|
|
710
737
|
.chartFill=${_args.chartFill}
|
|
738
|
+
.rangeLabels=${_args.rangeLabels}
|
|
711
739
|
.minValue=${_args.minValue}
|
|
712
740
|
.maxValue=${_args.maxValue}
|
|
713
741
|
.value=${_args.value}
|
|
@@ -753,6 +781,7 @@ export const GaugeTrendLabelsOnly: Story = {
|
|
|
753
781
|
.height=${_args.height}
|
|
754
782
|
.priority=${_args.priority}
|
|
755
783
|
.chartFill=${_args.chartFill}
|
|
784
|
+
.rangeLabels=${_args.rangeLabels}
|
|
756
785
|
.minValue=${_args.minValue ?? 0}
|
|
757
786
|
.maxValue=${_args.maxValue ?? 100}
|
|
758
787
|
.value=${_args.value}
|
|
@@ -442,6 +442,17 @@ export class ObcGaugeTrend extends SetpointMixin(ObcChartLineBase) {
|
|
|
442
442
|
return false;
|
|
443
443
|
}
|
|
444
444
|
|
|
445
|
+
/**
|
|
446
|
+
* The right scale is this component's own bar, ranged by `minValue` /
|
|
447
|
+
* `maxValue`. `chartMinValue` / `chartMaxValue` exist so the plotted range
|
|
448
|
+
* can differ from it, so the chart's axis range must not overwrite it.
|
|
449
|
+
*/
|
|
450
|
+
protected override ownsSlottedScaleRange(
|
|
451
|
+
side: 'left' | 'right' | 'top' | 'bottom'
|
|
452
|
+
): boolean {
|
|
453
|
+
return side !== 'right';
|
|
454
|
+
}
|
|
455
|
+
|
|
445
456
|
override willUpdate(changed: Map<PropertyKey, unknown>) {
|
|
446
457
|
// Auto axis detection: {x, value} data switches to time spacing, {label,
|
|
447
458
|
// value} stays category. An explicit xAxisType assignment (anything we
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
|
|
77
77
|
.tag {
|
|
78
78
|
@mixin font-instrument-label;
|
|
79
|
-
width: var(--obc-instrument-field-tag-width);
|
|
79
|
+
width: var(--obc-instrument-field-tag-width, auto);
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
.unit {
|
|
@@ -109,7 +109,7 @@
|
|
|
109
109
|
@mixin font-instrument-unit;
|
|
110
110
|
color: var(--element-neutral-color);
|
|
111
111
|
justify-content: end;
|
|
112
|
-
width: var(--obc-instrument-field-source-width);
|
|
112
|
+
width: var(--obc-instrument-field-source-width, auto);
|
|
113
113
|
box-sizing: content-box;
|
|
114
114
|
}
|
|
115
115
|
|
|
@@ -55,7 +55,7 @@ import {
|
|
|
55
55
|
ObcAlertFrameThickness,
|
|
56
56
|
ObcAlertFrameMode,
|
|
57
57
|
} from '../../components/alert-frame/alert-frame.js';
|
|
58
|
-
import {AlertType} from '../../types.js';
|
|
58
|
+
import {AlertType, FlashingSpeed} from '../../types.js';
|
|
59
59
|
import '../../components/button/button.js';
|
|
60
60
|
import '../../components/context-menu-input/context-menu-input.js';
|
|
61
61
|
import {
|
|
@@ -866,6 +866,7 @@ export class ObcReadout extends LitElement {
|
|
|
866
866
|
.thickness=${thickness}
|
|
867
867
|
.status=${alert.status ?? AlertType.Alarm}
|
|
868
868
|
.mode=${alert.mode ?? ObcAlertFrameMode.ackedActive}
|
|
869
|
+
.flashingSpeed=${alert.flashingSpeed ?? FlashingSpeed.Default}
|
|
869
870
|
.showIcon=${alert.showIcon ?? false}
|
|
870
871
|
.showAlertCategoryIcon=${alert.showAlertCategoryIcon ?? true}
|
|
871
872
|
.wrapContent=${false}
|
|
@@ -44,7 +44,7 @@ import {
|
|
|
44
44
|
ObcAlertFrameThickness,
|
|
45
45
|
ObcAlertFrameMode,
|
|
46
46
|
} from '../../components/alert-frame/alert-frame.js';
|
|
47
|
-
import {AlertType} from '../../types.js';
|
|
47
|
+
import {AlertType, FlashingSpeed} from '../../types.js';
|
|
48
48
|
|
|
49
49
|
// The value weight maps straight to obc-textbox's font weights (regular /
|
|
50
50
|
// semibold / bold). Re-exported so consumers can set `valueOptions.weight`
|
|
@@ -941,6 +941,7 @@ export class ObcReadoutListItem extends LitElement {
|
|
|
941
941
|
.thickness=${thickness}
|
|
942
942
|
.status=${alert.status ?? AlertType.Alarm}
|
|
943
943
|
.mode=${alert.mode ?? ObcAlertFrameMode.ackedActive}
|
|
944
|
+
.flashingSpeed=${alert.flashingSpeed ?? FlashingSpeed.Default}
|
|
944
945
|
.showIcon=${alert.showIcon ?? false}
|
|
945
946
|
.showAlertCategoryIcon=${alert.showAlertCategoryIcon ?? true}
|
|
946
947
|
.wrapContent=${false}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import {afterEach, describe, expect, it} from 'vitest';
|
|
2
|
+
import '../main.css';
|
|
3
|
+
import {
|
|
4
|
+
FLASH_OFF_MS,
|
|
5
|
+
FLASH_ON_MS,
|
|
6
|
+
FLASH_TEMPOS,
|
|
7
|
+
blinkingAll,
|
|
8
|
+
flashPeriodMs,
|
|
9
|
+
flashVariable,
|
|
10
|
+
installFlashing,
|
|
11
|
+
} from './blinking.js';
|
|
12
|
+
import {FlashingSpeed} from '../types.js';
|
|
13
|
+
|
|
14
|
+
describe('installFlashing', () => {
|
|
15
|
+
const hosts: HTMLElement[] = [];
|
|
16
|
+
function host(): HTMLElement {
|
|
17
|
+
const el = document.createElement('div');
|
|
18
|
+
document.body.append(el);
|
|
19
|
+
hosts.push(el);
|
|
20
|
+
return el;
|
|
21
|
+
}
|
|
22
|
+
afterEach(() => {
|
|
23
|
+
hosts.splice(0).forEach((el) => el.remove());
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it.each(FLASH_TEMPOS)(
|
|
27
|
+
'%s runs on for its on-time, off for 400 ms, from the document origin',
|
|
28
|
+
(tempo) => {
|
|
29
|
+
const el = host();
|
|
30
|
+
const cancel = installFlashing(el, tempo);
|
|
31
|
+
const [anim] = el.getAnimations();
|
|
32
|
+
const effect = anim.effect as KeyframeEffect;
|
|
33
|
+
const timing = effect.getTiming();
|
|
34
|
+
expect(timing.duration).toBe(FLASH_ON_MS[tempo] + FLASH_OFF_MS);
|
|
35
|
+
expect(timing.iterations).toBe(Infinity);
|
|
36
|
+
const frames = effect.getKeyframes();
|
|
37
|
+
expect(frames).toHaveLength(3);
|
|
38
|
+
// Chromium reports the normalised form of `step-end`.
|
|
39
|
+
expect(frames[0].easing).toMatch(/^(step-end|steps\(1\))$/);
|
|
40
|
+
expect(frames[1].offset).toBeCloseTo(
|
|
41
|
+
FLASH_ON_MS[tempo] / flashPeriodMs(tempo)
|
|
42
|
+
);
|
|
43
|
+
expect(anim.startTime).toBe(0);
|
|
44
|
+
cancel();
|
|
45
|
+
expect(el.getAnimations()).toHaveLength(0);
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
it('nests the cycles so every tempo dips together', () => {
|
|
50
|
+
expect(flashPeriodMs(FlashingSpeed.Fast)).toBe(800);
|
|
51
|
+
expect(flashPeriodMs(FlashingSpeed.Slow)).toBe(1600);
|
|
52
|
+
expect(flashPeriodMs(FlashingSpeed.VerySlow)).toBe(3200);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('drives the on/off variables in step', () => {
|
|
56
|
+
const el = host();
|
|
57
|
+
installFlashing(el, FlashingSpeed.Fast);
|
|
58
|
+
const [anim] = el.getAnimations();
|
|
59
|
+
const on = () =>
|
|
60
|
+
getComputedStyle(el).getPropertyValue(
|
|
61
|
+
flashVariable(FlashingSpeed.Fast, 'on')
|
|
62
|
+
);
|
|
63
|
+
const off = () =>
|
|
64
|
+
getComputedStyle(el).getPropertyValue(
|
|
65
|
+
flashVariable(FlashingSpeed.Fast, 'off')
|
|
66
|
+
);
|
|
67
|
+
anim.pause();
|
|
68
|
+
anim.currentTime = 100;
|
|
69
|
+
expect(on().trim()).toBe('1');
|
|
70
|
+
expect(off().trim()).toBe('0');
|
|
71
|
+
anim.currentTime = 500;
|
|
72
|
+
expect(on().trim()).toBe('0');
|
|
73
|
+
expect(off().trim()).toBe('1');
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('blinkingAll installs one animation per tempo and cancels them together', () => {
|
|
77
|
+
const el = host();
|
|
78
|
+
const cancel = blinkingAll(el);
|
|
79
|
+
expect(el.getAnimations()).toHaveLength(FLASH_TEMPOS.length);
|
|
80
|
+
cancel();
|
|
81
|
+
expect(el.getAnimations()).toHaveLength(0);
|
|
82
|
+
});
|
|
83
|
+
});
|
package/src/palettes/blinking.ts
CHANGED
|
@@ -1,46 +1,58 @@
|
|
|
1
|
-
|
|
2
|
-
const ALARM_PERIOD = 2000; // ms
|
|
3
|
-
const WARNING_PERIOD = 4000; // ms
|
|
4
|
-
const LOW_PERIOD = 8000; // ms
|
|
1
|
+
import {FlashingSpeed, type FlashTempo} from '../types.js';
|
|
5
2
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
period: number,
|
|
9
|
-
label: string
|
|
10
|
-
): () => void {
|
|
11
|
-
const anim = el.animate(
|
|
12
|
-
[
|
|
13
|
-
{[label + '-on']: 1, [label + '-off']: 0},
|
|
14
|
-
{[label + '-on']: 0, [label + '-off']: 1},
|
|
15
|
-
],
|
|
16
|
-
{duration: period, iterations: Infinity, easing: 'steps(2, jump-none)'}
|
|
17
|
-
);
|
|
18
|
-
anim.startTime = 0; // Common time origin for all animations, so they blink in sync.
|
|
19
|
-
return () => anim.cancel();
|
|
20
|
-
}
|
|
3
|
+
/** Shared off phase: nested cycles (800/1600/3200 ms) then dip together (#1224). */
|
|
4
|
+
export const FLASH_OFF_MS = 400;
|
|
21
5
|
|
|
22
|
-
export
|
|
23
|
-
|
|
24
|
-
|
|
6
|
+
export const FLASH_ON_MS: Record<FlashTempo, number> = {
|
|
7
|
+
[FlashingSpeed.Fast]: 400,
|
|
8
|
+
[FlashingSpeed.Slow]: 1200,
|
|
9
|
+
[FlashingSpeed.VerySlow]: 2800,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const FLASH_TEMPOS: readonly FlashTempo[] = [
|
|
13
|
+
FlashingSpeed.Fast,
|
|
14
|
+
FlashingSpeed.Slow,
|
|
15
|
+
FlashingSpeed.VerySlow,
|
|
16
|
+
];
|
|
25
17
|
|
|
26
|
-
export function
|
|
27
|
-
return
|
|
18
|
+
export function flashPeriodMs(tempo: FlashTempo): number {
|
|
19
|
+
return FLASH_ON_MS[tempo] + FLASH_OFF_MS;
|
|
28
20
|
}
|
|
29
21
|
|
|
30
|
-
|
|
31
|
-
|
|
22
|
+
/** Animated custom property name; `on` reads 1 during the on phase, `off` 1 during the off phase. */
|
|
23
|
+
export function flashVariable(tempo: FlashTempo, phase: 'on' | 'off'): string {
|
|
24
|
+
return `--flash-${tempo}-${phase}`;
|
|
32
25
|
}
|
|
33
26
|
|
|
34
|
-
|
|
35
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Animates `--flash-<tempo>-on` / `-off` on `el` for one tempo. Returns the
|
|
29
|
+
* cancel function.
|
|
30
|
+
*/
|
|
31
|
+
export function installFlashing(
|
|
32
|
+
el: HTMLElement,
|
|
33
|
+
tempo: FlashTempo
|
|
34
|
+
): () => void {
|
|
35
|
+
const on = flashVariable(tempo, 'on');
|
|
36
|
+
const off = flashVariable(tempo, 'off');
|
|
37
|
+
const period = flashPeriodMs(tempo);
|
|
38
|
+
const frames: Keyframe[] = [
|
|
39
|
+
{[on]: 1, [off]: 0, easing: 'step-end'},
|
|
40
|
+
{
|
|
41
|
+
[on]: 0,
|
|
42
|
+
[off]: 1,
|
|
43
|
+
offset: FLASH_ON_MS[tempo] / period,
|
|
44
|
+
easing: 'step-end',
|
|
45
|
+
},
|
|
46
|
+
{[on]: 0, [off]: 1},
|
|
47
|
+
];
|
|
48
|
+
const anim = el.animate(frames, {duration: period, iterations: Infinity});
|
|
49
|
+
// Document-timeline origin, so every flashing element is in the same phase.
|
|
50
|
+
anim.startTime = 0;
|
|
51
|
+
return () => anim.cancel();
|
|
36
52
|
}
|
|
37
53
|
|
|
54
|
+
/** Installs every tempo on `el`, for CSS that reads the variables directly. */
|
|
38
55
|
export function blinkingAll(el: HTMLElement): () => void {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
blinkingAlarm(el),
|
|
42
|
-
blinkingWarning(el),
|
|
43
|
-
blinkingLow(el),
|
|
44
|
-
];
|
|
45
|
-
return () => animes.forEach((anim) => anim());
|
|
56
|
+
const cancels = FLASH_TEMPOS.map((tempo) => installFlashing(el, tempo));
|
|
57
|
+
return () => cancels.forEach((cancel) => cancel());
|
|
46
58
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type {LitElement, ReactiveController} from 'lit';
|
|
2
|
+
import {
|
|
3
|
+
FlashingSpeed,
|
|
4
|
+
type FlashTempo,
|
|
5
|
+
type ResolvedFlashingSpeed,
|
|
6
|
+
} from '../types.js';
|
|
7
|
+
import {installFlashing} from './blinking.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Keeps one flash animation on the host in step with the tempo the host
|
|
11
|
+
* resolves after every update. `fixed` or a disconnect removes it; a
|
|
12
|
+
* reconnect re-syncs without waiting for a property change (#1224).
|
|
13
|
+
*/
|
|
14
|
+
export class FlashingController implements ReactiveController {
|
|
15
|
+
private cancel?: () => void;
|
|
16
|
+
private installed?: FlashTempo;
|
|
17
|
+
|
|
18
|
+
constructor(
|
|
19
|
+
private readonly host: LitElement,
|
|
20
|
+
private readonly resolve: () => ResolvedFlashingSpeed
|
|
21
|
+
) {
|
|
22
|
+
host.addController(this);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
get tempo(): FlashTempo | undefined {
|
|
26
|
+
return this.installed;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
hostConnected(): void {
|
|
30
|
+
if (this.host.hasUpdated) {
|
|
31
|
+
this.sync();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
hostUpdated(): void {
|
|
36
|
+
this.sync();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
hostDisconnected(): void {
|
|
40
|
+
this.stop();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private sync(): void {
|
|
44
|
+
const wanted = this.host.isConnected ? this.resolve() : FlashingSpeed.Fixed;
|
|
45
|
+
if (wanted === FlashingSpeed.Fixed) {
|
|
46
|
+
this.stop();
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (wanted === this.installed) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
this.stop();
|
|
53
|
+
this.cancel = installFlashing(this.host, wanted);
|
|
54
|
+
this.installed = wanted;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private stop(): void {
|
|
58
|
+
this.cancel?.();
|
|
59
|
+
this.cancel = undefined;
|
|
60
|
+
this.installed = undefined;
|
|
61
|
+
}
|
|
62
|
+
}
|
package/src/palettes/manual.css
CHANGED
|
@@ -98,25 +98,39 @@
|
|
|
98
98
|
--alert-notification-container-border-color: rgb(226, 240, 255);
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
/* Animated per element by palettes/blinking.ts; registered so the numbers
|
|
102
|
+
feed calc() (#1224). */
|
|
103
|
+
@property --flash-fast-on {
|
|
102
104
|
syntax: "<number>";
|
|
103
105
|
inherits: true;
|
|
104
106
|
initial-value: 1;
|
|
105
107
|
}
|
|
106
108
|
|
|
107
|
-
@property --
|
|
109
|
+
@property --flash-fast-off {
|
|
108
110
|
syntax: "<number>";
|
|
109
111
|
inherits: true;
|
|
110
112
|
initial-value: 0;
|
|
111
113
|
}
|
|
112
114
|
|
|
113
|
-
@property --
|
|
115
|
+
@property --flash-slow-on {
|
|
114
116
|
syntax: "<number>";
|
|
115
117
|
inherits: true;
|
|
116
118
|
initial-value: 1;
|
|
117
119
|
}
|
|
118
120
|
|
|
119
|
-
@property --
|
|
121
|
+
@property --flash-slow-off {
|
|
122
|
+
syntax: "<number>";
|
|
123
|
+
inherits: true;
|
|
124
|
+
initial-value: 0;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
@property --flash-very-slow-on {
|
|
128
|
+
syntax: "<number>";
|
|
129
|
+
inherits: true;
|
|
130
|
+
initial-value: 1;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
@property --flash-very-slow-off {
|
|
120
134
|
syntax: "<number>";
|
|
121
135
|
inherits: true;
|
|
122
136
|
initial-value: 0;
|
package/src/svghelpers/index.ts
CHANGED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import {describe, expect, it} from 'vitest';
|
|
2
|
+
import {roundedRectPath} from './rounded-rect.js';
|
|
3
|
+
|
|
4
|
+
describe('roundedRectPath', () => {
|
|
5
|
+
it('draws square corners for zero radii', () => {
|
|
6
|
+
expect(
|
|
7
|
+
roundedRectPath({x: 0, y: 0, width: 100, height: 50, radii: [0, 0, 0, 0]})
|
|
8
|
+
).toBe('M0 0 H100 V50 H0 V0 Z');
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('draws a clockwise arc per rounded corner', () => {
|
|
12
|
+
expect(
|
|
13
|
+
roundedRectPath({
|
|
14
|
+
x: 1,
|
|
15
|
+
y: 1,
|
|
16
|
+
width: 100,
|
|
17
|
+
height: 50,
|
|
18
|
+
radii: [10, 10, 10, 10],
|
|
19
|
+
})
|
|
20
|
+
).toBe(
|
|
21
|
+
'M11 1 H91 A10 10 0 0 1 101 11 V41 A10 10 0 0 1 91 51 H11 A10 10 0 0 1 1 41 V11 A10 10 0 0 1 11 1 Z'
|
|
22
|
+
);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('keeps individual corners square', () => {
|
|
26
|
+
const d = roundedRectPath({
|
|
27
|
+
x: 0,
|
|
28
|
+
y: 0,
|
|
29
|
+
width: 100,
|
|
30
|
+
height: 50,
|
|
31
|
+
radii: [0, 8, 0, 8],
|
|
32
|
+
});
|
|
33
|
+
expect(d.startsWith('M0 0 H92 A8 8 0 0 1 100 8 V50 H8')).toBe(true);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('clamps radii to half the shorter side', () => {
|
|
37
|
+
const d = roundedRectPath({
|
|
38
|
+
x: 0,
|
|
39
|
+
y: 0,
|
|
40
|
+
width: 100,
|
|
41
|
+
height: 20,
|
|
42
|
+
radii: [50, 50, 50, 50],
|
|
43
|
+
});
|
|
44
|
+
expect(d).toContain('A10 10 0 0 1');
|
|
45
|
+
expect(d).not.toContain('A50');
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export interface RoundedRect {
|
|
2
|
+
x: number;
|
|
3
|
+
y: number;
|
|
4
|
+
width: number;
|
|
5
|
+
height: number;
|
|
6
|
+
/** Corner radii in CSS order: top-left, top-right, bottom-right, bottom-left. */
|
|
7
|
+
radii: [number, number, number, number];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* SVG path of a rectangle with per-corner radii, so a stroke can follow a
|
|
12
|
+
* box whose corners are individually sharp (the alert frame's
|
|
13
|
+
* `sharpEdge*` flags). Radii are clamped to half the shorter side.
|
|
14
|
+
*/
|
|
15
|
+
export function roundedRectPath({
|
|
16
|
+
x,
|
|
17
|
+
y,
|
|
18
|
+
width,
|
|
19
|
+
height,
|
|
20
|
+
radii,
|
|
21
|
+
}: RoundedRect): string {
|
|
22
|
+
const max = Math.min(width, height) / 2;
|
|
23
|
+
const [tl, tr, br, bl] = radii.map((r) => Math.max(0, Math.min(r, max)));
|
|
24
|
+
const right = x + width;
|
|
25
|
+
const bottom = y + height;
|
|
26
|
+
const arc = (r: number, endX: number, endY: number) =>
|
|
27
|
+
r > 0 ? `A${r} ${r} 0 0 1 ${endX} ${endY}` : '';
|
|
28
|
+
return [
|
|
29
|
+
`M${x + tl} ${y}`,
|
|
30
|
+
`H${right - tr}`,
|
|
31
|
+
arc(tr, right, y + tr),
|
|
32
|
+
`V${bottom - br}`,
|
|
33
|
+
arc(br, right - br, bottom),
|
|
34
|
+
`H${x + bl}`,
|
|
35
|
+
arc(bl, x, bottom - bl),
|
|
36
|
+
`V${y + tl}`,
|
|
37
|
+
arc(tl, x + tl, y),
|
|
38
|
+
'Z',
|
|
39
|
+
]
|
|
40
|
+
.filter(Boolean)
|
|
41
|
+
.join(' ');
|
|
42
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -16,6 +16,26 @@ export enum AlertType {
|
|
|
16
16
|
LevelDiagnostic = 'level-diagnostic',
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Flash tempo of an alert element. `default` resolves per alert type and
|
|
21
|
+
* phase (see `resolveFlashingSpeed` in `alert-severity.ts`); `fixed` never
|
|
22
|
+
* flashes.
|
|
23
|
+
*/
|
|
24
|
+
export enum FlashingSpeed {
|
|
25
|
+
Default = 'default',
|
|
26
|
+
Fast = 'fast',
|
|
27
|
+
Slow = 'slow',
|
|
28
|
+
VerySlow = 'very-slow',
|
|
29
|
+
Fixed = 'fixed',
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export type ResolvedFlashingSpeed = Exclude<
|
|
33
|
+
FlashingSpeed,
|
|
34
|
+
FlashingSpeed.Default
|
|
35
|
+
>;
|
|
36
|
+
|
|
37
|
+
export type FlashTempo = Exclude<ResolvedFlashingSpeed, FlashingSpeed.Fixed>;
|
|
38
|
+
|
|
19
39
|
export const ALERT_SEVERITY_PRIORITY = [
|
|
20
40
|
AlertType.LevelCritical,
|
|
21
41
|
AlertType.Alarm,
|