@oicl/openbridge-webcomponents-full-bundle 2.0.0-next.118 → 2.0.0-next.120

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 (173) hide show
  1. package/.storybook/manager.ts +18 -16
  2. package/bundle/openbridge-webcomponents.bundle.js +96 -0
  3. package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
  4. package/custom-elements.json +46 -1
  5. package/dist/automation/vertical-line/vertical-line.d.ts +6 -0
  6. package/dist/automation/vertical-line/vertical-line.d.ts.map +1 -1
  7. package/dist/automation/vertical-line/vertical-line.js.map +1 -1
  8. package/dist/components/alert-button/alert-button.d.ts +3 -0
  9. package/dist/components/alert-button/alert-button.d.ts.map +1 -1
  10. package/dist/components/alert-button/alert-button.js +12 -0
  11. package/dist/components/alert-button/alert-button.js.map +1 -1
  12. package/dist/components/alert-frame/alert-frame.css.js +1 -0
  13. package/dist/components/alert-frame/alert-frame.css.js.map +1 -1
  14. package/dist/components/alert-frame/alert-frame.d.ts +5 -0
  15. package/dist/components/alert-frame/alert-frame.d.ts.map +1 -1
  16. package/dist/components/alert-frame/alert-frame.js +24 -0
  17. package/dist/components/alert-frame/alert-frame.js.map +1 -1
  18. package/dist/components/alert-icon/alert-icon.d.ts +5 -0
  19. package/dist/components/alert-icon/alert-icon.d.ts.map +1 -1
  20. package/dist/components/alert-icon/alert-icon.js +26 -0
  21. package/dist/components/alert-icon/alert-icon.js.map +1 -1
  22. package/dist/components/pivot-item-group/pivot-item-group.d.ts +1 -0
  23. package/dist/components/pivot-item-group/pivot-item-group.d.ts.map +1 -1
  24. package/dist/components/pivot-item-group/pivot-item-group.js.map +1 -1
  25. package/dist/openbridge.css +0 -73
  26. package/dist/palettes/blinking.d.ts +6 -0
  27. package/dist/palettes/blinking.d.ts.map +1 -0
  28. package/dist/palettes/blinking.js +44 -0
  29. package/dist/palettes/blinking.js.map +1 -0
  30. package/eslint.config.mjs +355 -0
  31. package/package.json +3 -1
  32. package/script/eslint-rules.test.ts +230 -0
  33. package/src/ar/building-blocks/poi-graphic-line/poi-graphic-line.stories.ts +1 -1
  34. package/src/ar/building-blocks/poi-header/poi-header.stories.ts +1 -1
  35. package/src/ar/building-blocks/poi-line/poi-line.stories.ts +1 -1
  36. package/src/ar/building-blocks/poi-pointer/poi-pointer.stories.ts +1 -1
  37. package/src/ar/building-blocks/poi-selection-frame/poi-selection-frame.stories.ts +1 -1
  38. package/src/ar/building-blocks/ruler-pointer/ruler-pointer.stories.ts +1 -1
  39. package/src/ar/chart-object-vessel-button/chart-object-vessel-button.stories.ts +1 -1
  40. package/src/ar/poi/poi-aton.stories.ts +1 -1
  41. package/src/ar/poi/poi-data.stories.ts +1 -1
  42. package/src/ar/poi/poi-vessel.stories.ts +1 -1
  43. package/src/ar/poi/poi.stories.ts +1 -1
  44. package/src/ar/poi-button/poi-button-aton.stories.ts +1 -1
  45. package/src/ar/poi-button/poi-button-data.stories.ts +1 -1
  46. package/src/ar/poi-button/poi-button-vessel.stories.ts +1 -1
  47. package/src/ar/poi-button/poi-button.stories.ts +1 -1
  48. package/src/ar/poi-card/poi-card.stories.ts +1 -1
  49. package/src/ar/poi-card-header/poi-card-header.stories.ts +1 -1
  50. package/src/ar/poi-controller/poi-controller.stories.ts +1 -1
  51. package/src/ar/poi-group/poi-group.stories.ts +1 -1
  52. package/src/ar/poi-layer/poi-layer.stories.ts +1 -1
  53. package/src/ar/poi-layer-stack/poi-layer-stack.stories.ts +1 -1
  54. package/src/ar/poi-object/poi-object-aton.stories.ts +1 -1
  55. package/src/ar/poi-object/poi-object-data.stories.ts +1 -1
  56. package/src/ar/poi-object/poi-object-vessel.stories.ts +1 -1
  57. package/src/ar/poi-object/poi-object.stories.ts +1 -1
  58. package/src/automation/automation-input-modal/automation-input-modal.stories.ts +1 -1
  59. package/src/automation/automation-readout/automation-readout.stories.ts +1 -1
  60. package/src/automation/automation-tank/automation-tank.stories.ts +1 -1
  61. package/src/automation/bus/bus.stories.ts +1 -1
  62. package/src/automation/corner-line/corner-line.stories.ts +1 -1
  63. package/src/automation/direction-line/direction-line.stories.ts +1 -1
  64. package/src/automation/end-point-line/end-point-line.stories.ts +1 -1
  65. package/src/automation/horizontal-line/horizontal-line.stories.ts +1 -1
  66. package/src/automation/line-cross/line-cross.stories.ts +1 -1
  67. package/src/automation/line-overlap/line-overlap.stories.ts +1 -1
  68. package/src/automation/three-way-line/three-way-line.stories.ts +1 -1
  69. package/src/automation/vertical-line/vertical-line.stories.ts +1 -1
  70. package/src/automation/vertical-line/vertical-line.ts +2 -1
  71. package/src/bars-graphs/area-graph/area-graph.stories.ts +1 -1
  72. package/src/bars-graphs/donut-chart/donut-chart.stories.ts +1 -1
  73. package/src/bars-graphs/line-graph/line-graph.stories.ts +1 -1
  74. package/src/bars-graphs/pie-chart/pie-chart.stories.ts +1 -1
  75. package/src/bars-graphs/polar-chart/polar-chart.stories.ts +1 -1
  76. package/src/bars-graphs/radial-bar-chart/radial-bar-chart.stories.ts +1 -1
  77. package/src/building-blocks/bar-horizontal/bar-horizontal.stories.ts +1 -1
  78. package/src/building-blocks/bar-vertical/bar-vertical.stories.ts +1 -1
  79. package/src/building-blocks/chart-line/chart-line-base.stories.ts +1 -1
  80. package/src/building-blocks/instrument-radial/instrument-radial.stories.ts +1 -1
  81. package/src/building-blocks/readout-block/readout-block.stories.ts +1 -1
  82. package/src/components/advice-floating-item/advice-floating-item.stories.ts +1 -1
  83. package/src/components/advice-menu-item/advice-menu-item.stories.ts +1 -1
  84. package/src/components/advice-message-item/advice-message-item.stories.ts +1 -1
  85. package/src/components/alert-button/alert-button.spec.ts +58 -0
  86. package/src/components/alert-button/alert-button.ts +16 -0
  87. package/src/components/alert-frame/alert-frame.css +1 -0
  88. package/src/components/alert-frame/alert-frame.spec.ts +122 -0
  89. package/src/components/alert-frame/alert-frame.stories.ts +13 -1
  90. package/src/components/alert-frame/alert-frame.ts +37 -0
  91. package/src/components/alert-icon/alert-icon.spec.ts +76 -0
  92. package/src/components/alert-icon/alert-icon.ts +38 -0
  93. package/src/components/attachment-list-item/attachment-list-item.stories.ts +1 -1
  94. package/src/components/audio-output/audio-output.stories.ts +1 -1
  95. package/src/components/audio-recording-item/audio-recording-item.stories.ts +1 -1
  96. package/src/components/automation-button-readout-stack/automation-button-readout-stack.stories.ts +1 -1
  97. package/src/components/badge/badge.stories.ts +1 -1
  98. package/src/components/calendar/calendar.stories.ts +1 -1
  99. package/src/components/command-button/command-button.stories.ts +1 -1
  100. package/src/components/command-menu/command-menu.stories.ts +1 -1
  101. package/src/components/communication-table/communication-table.stories.ts +1 -1
  102. package/src/components/context-menu-input/context-menu-input.stories.ts +1 -1
  103. package/src/components/date-item/date-item.stories.ts +1 -1
  104. package/src/components/event-item/event-item.stories.ts +1 -1
  105. package/src/components/event-list/event-list.stories.ts +1 -1
  106. package/src/components/form-container/form-container.stories.ts +1 -0
  107. package/src/components/form-footer-container/form-footer-container.stories.ts +1 -0
  108. package/src/components/form-group/form-group.stories.ts +1 -0
  109. package/src/components/form-item/form-item.stories.ts +1 -1
  110. package/src/components/keyboard-full/keyboard-full.stories.ts +1 -1
  111. package/src/components/keyboard-numeric/keyboard-numeric.stories.ts +1 -1
  112. package/src/components/menu-button/menu-button.stories.ts +1 -1
  113. package/src/components/message-menu-item/message-menu-item.stories.ts +1 -1
  114. package/src/components/notification-badge-button/notification-badge-button.stories.ts +1 -1
  115. package/src/components/notification-floating-item/notification-floating-item.stories.ts +1 -1
  116. package/src/components/notification-menu-item/notification-menu-item.stories.ts +1 -1
  117. package/src/components/notification-message-item/notification-message-item.stories.ts +1 -1
  118. package/src/components/pivot-item-group/pivot-item-group.ts +1 -0
  119. package/src/components/rich-button/rich-button.stories.ts +1 -1
  120. package/src/components/sequence-card/sequence-card.stories.ts +1 -1
  121. package/src/components/sequence-connector/sequence-connector.stories.ts +1 -1
  122. package/src/components/sequence-item/sequence-item.stories.ts +1 -0
  123. package/src/components/sequence-loading-spinner/sequence-loading-spinner.stories.ts +1 -1
  124. package/src/components/sequence-modal/sequence-modal.stories.ts +1 -1
  125. package/src/components/sequence-step/sequence-step.stories.ts +1 -0
  126. package/src/components/sequence-toolbar/sequence-toolbar.stories.ts +1 -0
  127. package/src/components/slide-button/slide-button.stories.ts +1 -1
  128. package/src/components/split-button/split-button.stories.ts +1 -1
  129. package/src/components/status-indicator/status-indicator.stories.ts +1 -1
  130. package/src/components/table/table.stories.ts +1 -1
  131. package/src/components/table-header-item/table-header-item.stories.ts +1 -1
  132. package/src/components/textbox/textbox.stories.ts +1 -1
  133. package/src/components/title-container/title-container.stories.ts +1 -1
  134. package/src/components/toggle-button-three-state/toggle-button-three-state.stories.ts +1 -1
  135. package/src/components/toggletip/toggletip.stories.ts +1 -1
  136. package/src/components/tree-navigation/tree-navigation.stories.ts +1 -1
  137. package/src/components/tree-navigation-item/tree-navigation-item.stories.ts +1 -1
  138. package/src/integration-systems/integration-app-bar/integration-app-bar.stories.ts +1 -1
  139. package/src/integration-systems/integration-bar/integration-bar.stories.ts +1 -1
  140. package/src/integration-systems/integration-bar-dropdown/integration-bar-dropdown.stories.ts +1 -1
  141. package/src/integration-systems/integration-button/integration-button.stories.ts +1 -1
  142. package/src/integration-systems/integration-dropdown-button/integration-dropdown-button.stories.ts +1 -1
  143. package/src/integration-systems/integration-fleet-button/integration-fleet-button.stories.ts +1 -1
  144. package/src/integration-systems/integration-tabs/integration-tabs.stories.ts +1 -1
  145. package/src/integration-systems/integration-vessel-menu/integration-vessel-menu.stories.ts +1 -1
  146. package/src/integration-systems/integration-vessel-selector/integration-vessel-selector.stories.ts +1 -1
  147. package/src/navigation-instruments/azimuth-thruster-labeled/azimuth-thruster-labeled.stories.ts +1 -1
  148. package/src/navigation-instruments/current/current.stories.ts +1 -1
  149. package/src/navigation-instruments/draft-trim/draft-trim.stories.ts +1 -1
  150. package/src/navigation-instruments/gauge-radial-proportional/gauge-radial-proportional.stories.ts +1 -1
  151. package/src/navigation-instruments/graph-mini/graph-mini.stories.ts +1 -1
  152. package/src/navigation-instruments/indicator-graph/indicator-graph.stories.ts +1 -1
  153. package/src/navigation-instruments/instrument-field/instrument-field.stories.ts +1 -1
  154. package/src/navigation-instruments/pitch-roll-heave/pitch-roll-heave.stories.ts +1 -1
  155. package/src/navigation-instruments/pitch-roll-yaw/pitch-roll-yaw.stories.ts +1 -1
  156. package/src/navigation-instruments/position-deviation/position-deviation.stories.ts +1 -1
  157. package/src/navigation-instruments/readout/readout.stories.ts +1 -1
  158. package/src/navigation-instruments/readout-list/readout-list.stories.ts +1 -1
  159. package/src/navigation-instruments/readout-list-item/readout-list-item.stories.ts +1 -1
  160. package/src/navigation-instruments/speed-arrows/speed-arrows.stories.ts +1 -1
  161. package/src/navigation-instruments/speed-directions/speed-directions.stories.ts +1 -1
  162. package/src/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts +1 -1
  163. package/src/navigation-instruments/velocity-projection-plot/velocity-projection-plot.stories.ts +1 -1
  164. package/src/navigation-instruments/watch/watch.stories.ts +1 -1
  165. package/src/navigation-instruments/watch-flat/watch-flat.stories.ts +1 -1
  166. package/src/navigation-instruments/wind-propulsion/wind-propulsion.stories.ts +1 -1
  167. package/src/pages/alert-detail-page/alert-detail-page.stories.ts +1 -1
  168. package/src/pages/alert-list-page-small/alert-list-page-small.stories.ts +1 -1
  169. package/src/palettes/blinking.ts +46 -0
  170. package/src/palettes/manual.css +0 -42
  171. package/src/palettes/variables.css +0 -36
  172. package/vitest.browser.config.ts +4 -2
  173. package/vitest.config.ts +10 -0
@@ -43,7 +43,7 @@ const SUNBURST_DATA = [
43
43
  const meta: Meta = {
44
44
  title: 'Bars and Graphs/Pie Chart',
45
45
  component: 'obc-pie-chart',
46
- tags: ['autodocs', '6.0'],
46
+ tags: ['autodocs', '6.0', 'beta'],
47
47
  argTypes: {
48
48
  fixedHeight: {
49
49
  control: {type: 'range', min: 48, max: 512},
@@ -23,7 +23,7 @@ const SAMPLE_DATA = [
23
23
  const meta: Meta = {
24
24
  title: 'Bars and Graphs/Polar Chart',
25
25
  component: 'obc-polar-chart',
26
- tags: ['autodocs', '6.0'],
26
+ tags: ['autodocs', '6.0', 'beta'],
27
27
  argTypes: {
28
28
  fixedHeight: {
29
29
  control: {type: 'range', min: 48, max: 512, step: 8},
@@ -10,7 +10,7 @@ const SAMPLE_DATA = [70, 50, 30];
10
10
  const meta: Meta = {
11
11
  title: 'Bars and Graphs/Radial Bar Chart',
12
12
  component: 'obc-radial-bar-chart',
13
- tags: ['autodocs', '6.0'],
13
+ tags: ['autodocs', '6.0', 'beta'],
14
14
  argTypes: {
15
15
  fixedHeight: {
16
16
  control: {type: 'range', min: 48, max: 512, step: 8},
@@ -31,7 +31,7 @@ const SAMPLE_DATA = [
31
31
 
32
32
  const meta: Meta = {
33
33
  title: 'Bars and Graphs/Bar Horizontal',
34
- tags: ['autodocs', '6.0'],
34
+ tags: ['autodocs', '6.0', 'beta'],
35
35
  component: 'obc-bar-horizontal',
36
36
  argTypes: {
37
37
  minValue: {control: {type: 'range', min: -100, max: 100}},
@@ -32,7 +32,7 @@ const SAMPLE_DATA = [
32
32
 
33
33
  const meta: Meta = {
34
34
  title: 'Bars and Graphs/Bar Vertical',
35
- tags: ['autodocs', '6.0'],
35
+ tags: ['autodocs', '6.0', 'beta'],
36
36
  component: 'obc-bar-vertical',
37
37
  argTypes: {
38
38
  minValue: {control: {type: 'range', min: -100, max: 100}},
@@ -85,7 +85,7 @@ const SAMPLE_MULTI_DATASETS = [
85
85
  const meta: Meta = {
86
86
  title: 'Building Blocks/Line Area Chart Base',
87
87
  component: 'obc-area-graph',
88
- tags: ['autodocs', '6.0'],
88
+ tags: ['autodocs', '6.0', 'beta'],
89
89
  parameters: {
90
90
  docs: {
91
91
  description: {
@@ -23,7 +23,7 @@ type InstrumentRadialStoryArgs = Partial<ObcInstrumentRadial> & {
23
23
 
24
24
  const meta: Meta<InstrumentRadialStoryArgs> = {
25
25
  title: 'Building Blocks/Instrument Radial',
26
- tags: ['6.0'],
26
+ tags: ['6.0', 'experimental'],
27
27
  component: 'obc-instrument-radial',
28
28
  decorators: [widthDecorator],
29
29
  args: {
@@ -120,7 +120,7 @@ function renderShowcase(cards: ShowcaseCard[]) {
120
120
 
121
121
  const meta = {
122
122
  title: 'Building Blocks/Readout Block',
123
- tags: ['autodocs', '6.0', 'wip'],
123
+ tags: ['autodocs', '6.0', 'experimental'],
124
124
  component: 'obc-readout-block',
125
125
  decorators: [themedDecorator],
126
126
  parameters: {
@@ -13,7 +13,7 @@ import '../../icons/icon-ship.js';
13
13
  const meta: Meta<ObcAdviceFloatingItem> = {
14
14
  title: 'Application Components/Notifications/Advice Floating Item',
15
15
  component: 'obc-advice-floating-item',
16
- tags: ['6.0'],
16
+ tags: ['6.0', 'beta'],
17
17
  argTypes: {
18
18
  type: {
19
19
  control: 'select',
@@ -6,7 +6,7 @@ import {ObcMessageMenuItemSize} from '../message-menu-item/message-menu-item.js'
6
6
 
7
7
  const meta: Meta<typeof ObcAdviceMenuItem> = {
8
8
  title: 'Application Components/Notifications/Advice Menu Item',
9
- tags: ['autodocs', '6.0'],
9
+ tags: ['autodocs', '6.0', 'beta'],
10
10
  component: 'obc-advice-menu-item',
11
11
  args: {
12
12
  title: 'Advice title',
@@ -6,7 +6,7 @@ import {html} from 'lit';
6
6
 
7
7
  const meta: Meta<typeof ObcAdviceMessageItem> = {
8
8
  title: 'Application Components/Notifications/Advice Message Item',
9
- tags: ['6.0'],
9
+ tags: ['6.0', 'beta'],
10
10
  component: 'obc-advice-message-item',
11
11
  args: {
12
12
  title: 'Advice title',
@@ -0,0 +1,58 @@
1
+ import {describe, expect, it} from 'vitest';
2
+ import './alert-button.js';
3
+ import {ObcAlertButton} from './alert-button.js';
4
+ import {render} from 'vitest-browser-lit';
5
+ import {html} from 'lit';
6
+
7
+ describe('obc-alert-button blinking lifecycle', () => {
8
+ async function setup() {
9
+ const screen = render(html`<obc-alert-button></obc-alert-button>`);
10
+ const el = screen.baseElement.querySelector(
11
+ 'obc-alert-button'
12
+ ) as ObcAlertButton;
13
+ await el.updateComplete;
14
+ return el;
15
+ }
16
+
17
+ it('installs the blink animations on first render', async () => {
18
+ const el = await setup();
19
+
20
+ expect(el.getAnimations().length).toBeGreaterThan(0);
21
+ });
22
+
23
+ it('cancels the blink animations on disconnect', async () => {
24
+ const el = await setup();
25
+
26
+ el.parentElement!.removeChild(el);
27
+
28
+ expect(el.getAnimations()).toHaveLength(0);
29
+ });
30
+
31
+ it('resumes blinking after disconnect and reconnect', async () => {
32
+ const el = await setup();
33
+ const parent = el.parentElement!;
34
+ const initial = el.getAnimations().length;
35
+
36
+ parent.removeChild(el);
37
+ expect(el.getAnimations()).toHaveLength(0);
38
+
39
+ // Reconnect without touching any property. firstUpdated() will not run
40
+ // again, so this only passes if blinking is reinstalled on update.
41
+ parent.appendChild(el);
42
+ await el.updateComplete;
43
+
44
+ expect(el.getAnimations()).toHaveLength(initial);
45
+ });
46
+
47
+ it('does not accumulate animations across repeated updates', async () => {
48
+ const el = await setup();
49
+ const initial = el.getAnimations().length;
50
+
51
+ el.nAlerts = 3;
52
+ await el.updateComplete;
53
+ el.nAlerts = 5;
54
+ await el.updateComplete;
55
+
56
+ expect(el.getAnimations()).toHaveLength(initial);
57
+ });
58
+ });
@@ -20,6 +20,7 @@ import {
20
20
  } from '../../alert-severity.js';
21
21
  import {classMap} from 'lit/directives/class-map.js';
22
22
  import {customElement} from '../../decorator.js';
23
+ import {blinkingAll} from '../../palettes/blinking.js';
23
24
 
24
25
  /**
25
26
  * `ObcAlertButtonType` – Enum for alert button visual and behavioral variants.
@@ -202,10 +203,14 @@ export class ObcAlertButton extends LitElement {
202
203
  override connectedCallback() {
203
204
  super.connectedCallback();
204
205
  window.addEventListener('resize', this.resizeListener);
206
+ if (this.hasUpdated) {
207
+ this.installBlinking();
208
+ }
205
209
  }
206
210
 
207
211
  override disconnectedCallback() {
208
212
  window.removeEventListener('resize', this.resizeListener);
213
+ this._blinkAnimationCancel?.();
209
214
  super.disconnectedCallback();
210
215
  }
211
216
 
@@ -280,6 +285,17 @@ export class ObcAlertButton extends LitElement {
280
285
  );
281
286
  }
282
287
 
288
+ private _blinkAnimationCancel?: () => void;
289
+
290
+ private installBlinking() {
291
+ this._blinkAnimationCancel?.();
292
+ this._blinkAnimationCancel = blinkingAll(this);
293
+ }
294
+
295
+ override updated() {
296
+ this.installBlinking();
297
+ }
298
+
283
299
  override render() {
284
300
  const hasAlerts = this.nAlerts > 0;
285
301
  const showCounter =
@@ -78,6 +78,7 @@
78
78
 
79
79
  &.level-critical {
80
80
  --bg-color: var(--critical-enabled-background-color);
81
+ --blink-on: var(--critical-blink-on);
81
82
  color: var(--on-critical-active-color);
82
83
  }
83
84
 
@@ -0,0 +1,122 @@
1
+ import {describe, expect, it} from 'vitest';
2
+ import './alert-frame.js';
3
+ import {ObcAlertFrame, ObcAlertFrameMode} from './alert-frame.js';
4
+ import {render} from 'vitest-browser-lit';
5
+ import {html} from 'lit';
6
+
7
+ describe('obc-alert-frame blinking lifecycle', () => {
8
+ async function setup(mode: ObcAlertFrameMode) {
9
+ const screen = render(
10
+ html`<obc-alert-frame .mode=${mode}></obc-alert-frame>`
11
+ );
12
+ const el = screen.baseElement.querySelector(
13
+ 'obc-alert-frame'
14
+ ) as ObcAlertFrame;
15
+ await el.updateComplete;
16
+ return el;
17
+ }
18
+
19
+ it('blinks while mode is unacked-active', async () => {
20
+ const el = await setup(ObcAlertFrameMode.unackedActive);
21
+
22
+ expect(el.getAnimations().length).toBeGreaterThan(0);
23
+ });
24
+
25
+ it('does not blink in other modes', async () => {
26
+ const el = await setup(ObcAlertFrameMode.ackedActive);
27
+
28
+ expect(el.getAnimations()).toHaveLength(0);
29
+ });
30
+
31
+ describe('mode transitions', () => {
32
+ it('starts blinking when mode becomes unacked-active', async () => {
33
+ const el = await setup(ObcAlertFrameMode.ackedActive);
34
+ expect(el.getAnimations()).toHaveLength(0);
35
+
36
+ el.mode = ObcAlertFrameMode.unackedActive;
37
+ await el.updateComplete;
38
+
39
+ expect(el.getAnimations().length).toBeGreaterThan(0);
40
+ });
41
+
42
+ it('stops blinking when mode leaves unacked-active', async () => {
43
+ const el = await setup(ObcAlertFrameMode.unackedActive);
44
+ expect(el.getAnimations().length).toBeGreaterThan(0);
45
+
46
+ el.mode = ObcAlertFrameMode.ackedActive;
47
+ await el.updateComplete;
48
+
49
+ expect(el.getAnimations()).toHaveLength(0);
50
+ });
51
+
52
+ it('stops blinking when mode becomes unacked-rectified', async () => {
53
+ const el = await setup(ObcAlertFrameMode.unackedActive);
54
+
55
+ el.mode = ObcAlertFrameMode.unackedRectified;
56
+ await el.updateComplete;
57
+
58
+ expect(el.getAnimations()).toHaveLength(0);
59
+ });
60
+
61
+ it('does not accumulate animations across repeated updates', async () => {
62
+ const el = await setup(ObcAlertFrameMode.unackedActive);
63
+ const initial = el.getAnimations().length;
64
+
65
+ el.fullWidth = true;
66
+ await el.updateComplete;
67
+ el.showIcon = true;
68
+ await el.updateComplete;
69
+
70
+ expect(el.getAnimations()).toHaveLength(initial);
71
+ });
72
+ });
73
+
74
+ describe('reconnection', () => {
75
+ it('resumes blinking after disconnect and reconnect', async () => {
76
+ const el = await setup(ObcAlertFrameMode.unackedActive);
77
+ const parent = el.parentElement!;
78
+ expect(el.getAnimations().length).toBeGreaterThan(0);
79
+
80
+ parent.removeChild(el);
81
+ expect(el.getAnimations()).toHaveLength(0);
82
+
83
+ // Reconnect without touching any property. firstUpdated() will not run
84
+ // again, so this only passes if blinking is reinstalled on update.
85
+ parent.appendChild(el);
86
+ await el.updateComplete;
87
+
88
+ expect(el.getAnimations().length).toBeGreaterThan(0);
89
+ });
90
+
91
+ it('does not resume blinking on reconnect when mode is not unacked-active', async () => {
92
+ const el = await setup(ObcAlertFrameMode.ackedActive);
93
+ const parent = el.parentElement!;
94
+
95
+ parent.removeChild(el);
96
+ parent.appendChild(el);
97
+ await el.updateComplete;
98
+
99
+ expect(el.getAnimations()).toHaveLength(0);
100
+ });
101
+
102
+ it('does not blink after disconnection when mode became unacked-active while detached', async () => {
103
+ const el = await setup(ObcAlertFrameMode.ackedActive);
104
+ const parent = el.parentElement!;
105
+
106
+ parent.removeChild(el);
107
+ await el.updateComplete;
108
+
109
+ expect(el.getAnimations().length).toBe(0);
110
+
111
+ el.mode = ObcAlertFrameMode.unackedActive;
112
+ await el.updateComplete;
113
+
114
+ expect(el.getAnimations().length).toBe(0);
115
+
116
+ parent.appendChild(el);
117
+ await el.updateComplete;
118
+
119
+ expect(el.getAnimations().length).toBeGreaterThan(0);
120
+ });
121
+ });
122
+ });
@@ -13,7 +13,7 @@ import {html} from 'lit';
13
13
 
14
14
  const meta: Meta<typeof ObcAlertFrame> = {
15
15
  title: 'UI Components/Message and Alerts/Alert Frame',
16
- tags: ['autodocs', '6.0'],
16
+ tags: ['autodocs', '6.0', 'beta'],
17
17
  component: 'obc-alert-frame',
18
18
  args: {
19
19
  type: ObcAlertFrameType.SmallSideFlip,
@@ -261,3 +261,15 @@ export const RectifiedUnactive: Story = {
261
261
  mode: ObcAlertFrameMode.unackedRectified,
262
262
  },
263
263
  };
264
+
265
+ export const CriticalUnacked: Story = {
266
+ args: {
267
+ type: ObcAlertFrameType.SmallSideFlip,
268
+ thickness: ObcAlertFrameThickness.Small,
269
+ status: ObcAlertFrameStatus.LevelCritical,
270
+ mode: ObcAlertFrameMode.unackedActive,
271
+ demoWidth: 200,
272
+ showIcon: true,
273
+ showAlertCategoryIcon: true,
274
+ },
275
+ };
@@ -20,6 +20,7 @@ import {
20
20
  getAlertBadgeComponent,
21
21
  AlertBadgeComponent,
22
22
  } from '../../alert-severity.js';
23
+ import {blinkingAll} from '../../palettes/blinking.js';
23
24
 
24
25
  export {AlertType as ObcAlertFrameStatus} from '../../types.js';
25
26
 
@@ -256,6 +257,42 @@ export class ObcAlertFrame extends LitElement {
256
257
  `;
257
258
  }
258
259
 
260
+ private _blinkAnimationCancel?: () => void;
261
+
262
+ private syncBlinking() {
263
+ if (
264
+ this.mode !== ObcAlertFrameMode.unackedActive &&
265
+ this._blinkAnimationCancel
266
+ ) {
267
+ this._blinkAnimationCancel();
268
+ this._blinkAnimationCancel = undefined;
269
+ }
270
+
271
+ if (
272
+ this.mode === ObcAlertFrameMode.unackedActive &&
273
+ !this._blinkAnimationCancel
274
+ ) {
275
+ this._blinkAnimationCancel = blinkingAll(this);
276
+ }
277
+ }
278
+
279
+ override connectedCallback() {
280
+ super.connectedCallback();
281
+ if (this.hasUpdated) {
282
+ this.syncBlinking();
283
+ }
284
+ }
285
+
286
+ override updated() {
287
+ this.syncBlinking();
288
+ }
289
+
290
+ override disconnectedCallback() {
291
+ super.disconnectedCallback();
292
+ this._blinkAnimationCancel?.();
293
+ this._blinkAnimationCancel = undefined;
294
+ }
295
+
259
296
  private flap() {
260
297
  if (this.type === ObcAlertFrameType.Regular) {
261
298
  return nothing;
@@ -0,0 +1,76 @@
1
+ import {describe, expect, it} from 'vitest';
2
+ import './alert-icon.js';
3
+ import {ObcAlertIcon} from './alert-icon.js';
4
+ import {render} from 'vitest-browser-lit';
5
+ import {html} from 'lit';
6
+ import {AlertType} from '../../types.js';
7
+
8
+ describe('obc-alert-icon blinking lifecycle', () => {
9
+ async function setup(acknowledged = false) {
10
+ const screen = render(
11
+ html`<obc-alert-icon
12
+ .alertType=${AlertType.Alarm}
13
+ .acknowledged=${acknowledged}
14
+ ></obc-alert-icon>`
15
+ );
16
+ const el = screen.baseElement.querySelector(
17
+ 'obc-alert-icon'
18
+ ) as ObcAlertIcon;
19
+ await el.updateComplete;
20
+ return el;
21
+ }
22
+
23
+ function wrapperAnimations(el: ObcAlertIcon) {
24
+ return el.getAnimations();
25
+ }
26
+
27
+ it('blinks for an unacknowledged blinking alert type', async () => {
28
+ const el = await setup();
29
+
30
+ expect(wrapperAnimations(el).length).toBeGreaterThan(0);
31
+ });
32
+
33
+ it('does not blink once acknowledged', async () => {
34
+ const el = await setup(true);
35
+
36
+ expect(wrapperAnimations(el)).toHaveLength(0);
37
+ });
38
+
39
+ it('stops blinking when the alert is acknowledged', async () => {
40
+ const el = await setup();
41
+ expect(wrapperAnimations(el).length).toBeGreaterThan(0);
42
+
43
+ el.acknowledged = true;
44
+ await el.updateComplete;
45
+
46
+ expect(wrapperAnimations(el)).toHaveLength(0);
47
+ });
48
+
49
+ it('resumes blinking after disconnect and reconnect', async () => {
50
+ const el = await setup();
51
+ const parent = el.parentElement!;
52
+ const initial = wrapperAnimations(el).length;
53
+ expect(initial).toBeGreaterThan(0);
54
+
55
+ parent.removeChild(el);
56
+ expect(wrapperAnimations(el)).toHaveLength(0);
57
+
58
+ // Reconnect without touching any property, so no Lit update is scheduled.
59
+ parent.appendChild(el);
60
+ await el.updateComplete;
61
+
62
+ expect(wrapperAnimations(el)).toHaveLength(initial);
63
+ });
64
+
65
+ it('does not accumulate animations across repeated updates', async () => {
66
+ const el = await setup();
67
+ const initial = wrapperAnimations(el).length;
68
+
69
+ el.active = true;
70
+ await el.updateComplete;
71
+ el.silenced = true;
72
+ await el.updateComplete;
73
+
74
+ expect(wrapperAnimations(el)).toHaveLength(initial);
75
+ });
76
+ });
@@ -50,6 +50,7 @@ import {
50
50
  import {lowSilencedA, lowSilencedB} from './icons/icon-low-silenced.js';
51
51
  import {lowRectifiedA, lowRectifiedB} from './icons/icon-low-rectified.js';
52
52
  import {lowAcknowledged} from './icons/icon-low-acknowledged.js';
53
+ import {blinkingAll} from '../../palettes/blinking.js';
53
54
 
54
55
  enum AlertIconState {
55
56
  Silenced = 'silenced',
@@ -343,6 +344,43 @@ export class ObcAlertIcon extends LitElement {
343
344
  return html`<div class="wrapper">${this.renderStaticIcon()}</div>`;
344
345
  }
345
346
 
347
+ private _blinkAnimationCancel?: () => void;
348
+
349
+ private syncBlinking(): void {
350
+ if (
351
+ this._blinkAnimationCancel &&
352
+ !supportsBlinking(this._effectiveType, this.acknowledged ?? false)
353
+ ) {
354
+ this._blinkAnimationCancel();
355
+ this._blinkAnimationCancel = undefined;
356
+ }
357
+ if (
358
+ !this._blinkAnimationCancel &&
359
+ supportsBlinking(this._effectiveType, this.acknowledged ?? false)
360
+ ) {
361
+ this._blinkAnimationCancel = blinkingAll(this);
362
+ }
363
+ }
364
+
365
+ override connectedCallback(): void {
366
+ super.connectedCallback();
367
+ if (this.hasUpdated) {
368
+ this.syncBlinking();
369
+ }
370
+ }
371
+
372
+ override updated(): void {
373
+ this.syncBlinking();
374
+ }
375
+
376
+ override disconnectedCallback(): void {
377
+ super.disconnectedCallback();
378
+ if (this._blinkAnimationCancel) {
379
+ this._blinkAnimationCancel();
380
+ this._blinkAnimationCancel = undefined;
381
+ }
382
+ }
383
+
346
384
  static override styles = css`
347
385
  .wrapper {
348
386
  height: 100%;
@@ -8,7 +8,7 @@ import {html} from 'lit';
8
8
 
9
9
  const meta: Meta<ObcAttachmentListItem> = {
10
10
  title: 'UI Components/Tables and Lists/Attachment List Item',
11
- tags: ['autodocs', '6.1'],
11
+ tags: ['autodocs', '6.1', 'beta'],
12
12
  component: 'obc-attachment-list-item',
13
13
  args: {
14
14
  label: 'Document.pdf',
@@ -4,7 +4,7 @@ import './audio-output.js';
4
4
 
5
5
  const meta: Meta<ObcAudioOutput> = {
6
6
  title: 'UI Components/Media/Audio Output',
7
- tags: ['6.0'],
7
+ tags: ['6.0', 'beta'],
8
8
  component: 'obc-audio-output',
9
9
  args: {},
10
10
  argTypes: {
@@ -9,7 +9,7 @@ import '../button/button.js';
9
9
 
10
10
  const meta = {
11
11
  title: 'UI Components/Media/Audio Recording Item',
12
- tags: ['autodocs', '6.0'],
12
+ tags: ['autodocs', '6.0', 'beta'],
13
13
  component: 'obc-audio-recording-item',
14
14
  args: {},
15
15
  argTypes: {
@@ -9,7 +9,7 @@ import {html} from 'lit';
9
9
 
10
10
  const meta: Meta = {
11
11
  title: 'Building Blocks/Automation Button Readout Stack',
12
- tags: ['6.0'],
12
+ tags: ['6.0', 'experimental'],
13
13
  component: 'obc-automation-button-readout-stack',
14
14
  args: {
15
15
  tag: '#0000',
@@ -8,7 +8,7 @@ import '../../icons/icon-alarm-badge.js';
8
8
 
9
9
  const meta: Meta<typeof ObcBadge> = {
10
10
  title: 'UI Components/Message and Alerts/Badge',
11
- tags: ['autodocs'],
11
+ tags: ['autodocs', 'beta'],
12
12
  component: 'obc-badge',
13
13
  args: {
14
14
  number: 9,
@@ -338,7 +338,7 @@ function renderCalendar(args: CalendarStoryArgs) {
338
338
 
339
339
  const meta: Meta<CalendarStoryArgs> = {
340
340
  title: 'Application Components/Calendar/Calendar',
341
- tags: ['autodocs', '6.0'],
341
+ tags: ['autodocs', '6.0', 'beta'],
342
342
  component: 'obc-calendar',
343
343
  render: renderCalendar,
344
344
  argTypes: {
@@ -4,7 +4,7 @@ import './command-button.js';
4
4
 
5
5
  const meta: Meta<typeof ObcCommandButton> = {
6
6
  title: 'Application Components/Menus/Command Button',
7
- tags: ['6.0'],
7
+ tags: ['6.0', 'beta'],
8
8
  component: 'obc-command-button',
9
9
  args: {},
10
10
  } satisfies Meta<ObcCommandButton>;
@@ -72,7 +72,7 @@ customElements.define('command-menu-story-wrapper', CommandMenuStoryWrapper);
72
72
 
73
73
  const meta: Meta<typeof ObcCommandMenu> = {
74
74
  title: 'Application Components/Menus/Command Menu',
75
- tags: ['6.0'],
75
+ tags: ['6.0', 'beta'],
76
76
  component: 'obc-command-menu',
77
77
  args: {
78
78
  showLocation: true,
@@ -8,7 +8,7 @@ import '../user-button/user-button.js';
8
8
 
9
9
  const meta: Meta<typeof ObcCommunicationTable> = {
10
10
  title: 'UI Components/Communication/Communication Table',
11
- tags: ['6.0'],
11
+ tags: ['6.0', 'beta'],
12
12
  component: 'obc-communication-table',
13
13
  args: {
14
14
  data: [
@@ -6,7 +6,7 @@ import '../../icons/icon-placeholder.js';
6
6
 
7
7
  const meta: Meta<typeof ObcContextMenuInput> = {
8
8
  title: 'UI Components/Menus and Navigation/Context Menu Input',
9
- tags: ['6.0'],
9
+ tags: ['6.0', 'beta'],
10
10
  component: 'obc-context-menu-input',
11
11
  argTypes: {
12
12
  type: {
@@ -10,7 +10,7 @@ interface DateItemStoryArgs extends Partial<ObcDateItem> {
10
10
 
11
11
  const meta: Meta<DateItemStoryArgs> = {
12
12
  title: 'Application Components/Calendar/Date Item',
13
- tags: ['6.0'],
13
+ tags: ['6.0', 'beta'],
14
14
  component: 'obc-date-item',
15
15
  argTypes: {
16
16
  width: {
@@ -9,7 +9,7 @@ interface EventItemStoryArgs extends Partial<ObcEventItem> {
9
9
 
10
10
  const meta: Meta<EventItemStoryArgs> = {
11
11
  title: 'Application Components/Calendar/Event Item',
12
- tags: ['6.0'],
12
+ tags: ['6.0', 'beta'],
13
13
  component: 'obc-event-item',
14
14
  decorators: [widthDecorator],
15
15
  argTypes: {