@lion/ui 0.11.0 → 0.11.1

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 (100) hide show
  1. package/README.md +2 -2
  2. package/components/checkbox-group/src/LionCheckboxIndeterminate.js +39 -16
  3. package/components/checkbox-group/test-suites/CheckboxIndeterminate.suite.js +189 -1
  4. package/components/form-core/src/FocusMixin.js +4 -4
  5. package/components/form-core/src/LionField.js +1 -1
  6. package/components/localize/types/LocalizeMixinTypes.ts +0 -5
  7. package/components/select-rich/src/LionSelectRich.js +1 -1
  8. package/components/select-rich/test/lion-select-rich.test.js +13 -1
  9. package/custom-elements.json +47661 -47626
  10. package/dist-types/components/checkbox-group/src/LionCheckboxIndeterminate.d.ts +10 -0
  11. package/dist-types/components/checkbox-group/src/LionCheckboxIndeterminate.d.ts.map +1 -1
  12. package/dist-types/components/checkbox-group/test-suites/CheckboxIndeterminate.suite.d.ts.map +1 -1
  13. package/dist-types/components/localize/types/LocalizeMixinTypes.d.ts +0 -4
  14. package/dist-types/components/localize/types/LocalizeMixinTypes.d.ts.map +1 -1
  15. package/dist-types/tsconfig.tsbuildinfo +1 -1
  16. package/docs/components/accordion/api-table.md +6 -6
  17. package/docs/components/button/api-table.md +27 -30
  18. package/docs/components/calendar/api-table.md +13 -13
  19. package/docs/components/checkbox-group/api-table.md +305 -329
  20. package/docs/components/checkbox-group/overview.md +2 -2
  21. package/docs/components/collapsible/api-table.md +5 -5
  22. package/docs/components/collapsible/overview.md +1 -1
  23. package/docs/components/combobox/api-table.md +150 -154
  24. package/docs/components/combobox/overview.md +1 -1
  25. package/docs/components/combobox/use-cases.md +1 -1
  26. package/docs/components/dialog/api-table.md +12 -12
  27. package/docs/components/dialog/overview.md +1 -1
  28. package/docs/components/drawer/api-table.md +9 -10
  29. package/docs/components/fieldset/api-table.md +104 -118
  30. package/docs/components/fieldset/overview.md +5 -5
  31. package/docs/components/form/overview.md +3 -3
  32. package/docs/components/form/use-cases.md +2 -2
  33. package/docs/components/icon/api-table.md +3 -3
  34. package/docs/components/icon/use-cases.md +1 -1
  35. package/docs/components/input/api-table.md +110 -120
  36. package/docs/components/input/overview.md +1 -1
  37. package/docs/components/input-amount/api-table.md +129 -142
  38. package/docs/components/input-amount/overview.md +3 -3
  39. package/docs/components/input-date/api-table.md +110 -120
  40. package/docs/components/input-date/overview.md +3 -3
  41. package/docs/components/input-datepicker/api-table.md +148 -160
  42. package/docs/components/input-datepicker/overview.md +5 -5
  43. package/docs/components/input-email/api-table.md +110 -120
  44. package/docs/components/input-email/overview.md +2 -2
  45. package/docs/components/input-file/api-table.md +132 -143
  46. package/docs/components/input-file/overview.md +1 -1
  47. package/docs/components/input-iban/api-table.md +110 -120
  48. package/docs/components/input-iban/overview.md +2 -2
  49. package/docs/components/input-range/api-table.md +116 -126
  50. package/docs/components/input-range/overview.md +2 -2
  51. package/docs/components/input-stepper/api-table.md +123 -133
  52. package/docs/components/input-stepper/overview.md +1 -1
  53. package/docs/components/input-tel/api-table.md +118 -128
  54. package/docs/components/input-tel/overview.md +1 -1
  55. package/docs/components/input-tel/use-cases.md +6 -6
  56. package/docs/components/input-tel-dropdown/api-table.md +125 -135
  57. package/docs/components/input-tel-dropdown/overview.md +1 -1
  58. package/docs/components/listbox/api-table.md +126 -131
  59. package/docs/components/listbox/use-cases.md +1 -1
  60. package/docs/components/pagination/api-table.md +5 -5
  61. package/docs/components/progress-indicator/api-table.md +9 -10
  62. package/docs/components/radio-group/api-table.md +234 -258
  63. package/docs/components/radio-group/overview.md +3 -3
  64. package/docs/components/select/api-table.md +106 -116
  65. package/docs/components/select/use-cases.md +1 -1
  66. package/docs/components/select-rich/api-table.md +169 -178
  67. package/docs/components/select-rich/use-cases.md +1 -1
  68. package/docs/components/steps/api-table.md +6 -6
  69. package/docs/components/switch/api-table.md +117 -128
  70. package/docs/components/tabs/api-table.md +1 -1
  71. package/docs/components/tabs/examples.md +1 -1
  72. package/docs/components/textarea/api-table.md +114 -124
  73. package/docs/components/tooltip/api-table.md +13 -13
  74. package/docs/fundamentals/index.md +4 -4
  75. package/docs/fundamentals/node-tools/publish-docs/overview.md +3 -3
  76. package/docs/fundamentals/node-tools/rocket-preset-extend-lion-docs/overview.md +2 -2
  77. package/docs/fundamentals/rationales/accessibility.md +1 -1
  78. package/docs/fundamentals/systems/core/SlotMixin.md +1 -1
  79. package/docs/fundamentals/systems/core/api-table.md +8 -11
  80. package/docs/fundamentals/systems/core/overview.md +1 -1
  81. package/docs/fundamentals/systems/form/api-table.md +77 -82
  82. package/docs/fundamentals/systems/form/formatting-and-parsing.md +4 -4
  83. package/docs/fundamentals/systems/form/model-value.md +1 -1
  84. package/docs/fundamentals/systems/form/overview.md +28 -28
  85. package/docs/fundamentals/systems/form/validate.md +2 -2
  86. package/docs/fundamentals/systems/localize/api-table.md +19 -19
  87. package/docs/fundamentals/systems/localize/overview.md +4 -4
  88. package/docs/fundamentals/systems/overlays/api-table.md +45 -46
  89. package/docs/fundamentals/systems/overlays/configuration.md +2 -2
  90. package/docs/fundamentals/systems/overlays/overview.md +5 -5
  91. package/docs/fundamentals/systems/overlays/use-cases.md +2 -2
  92. package/docs/fundamentals/tools/helpers/overview.md +1 -1
  93. package/docs/fundamentals/tools/singleton-manager/overview.md +4 -4
  94. package/docs/guides/how-to/create-a-custom-field.md +5 -5
  95. package/docs/guides/how-to/create-a-form.md +4 -4
  96. package/docs/guides/how-to/extend-a-native-input.md +2 -2
  97. package/docs/guides/index.md +8 -8
  98. package/docs/guides/principles/index.md +5 -5
  99. package/docs/guides/principles/styling.md +1 -1
  100. package/package.json +1 -1
package/README.md CHANGED
@@ -45,7 +45,7 @@ They provide an unopinionated, white-label layer that can be extended to your ow
45
45
  - **Accessibility:** Aimed at compliance with the WCAG 2.2 AA standard to create components that are accessible for everybody.
46
46
  - **Flexibility:** Provides solutions through Web Components and JavaScript classes which can be used, adopted and extended to fit all needs.
47
47
  - **Modern Code:** Lion is distributes as pure es modules.
48
- - **Exposes functions/classes and Web Components:** Ships a functionality in it's most appropriate form.
48
+ - **Exposes functions/classes and Web Components:** Ships a functionality in its most appropriate form.
49
49
 
50
50
  > Note: Our demo examples might look simple and not very stylish. This is on purpose. They are designed to be basic so you can easily add your own styles to them to match your intended design, without dealing with styles that are already there.
51
51
 
@@ -113,7 +113,7 @@ You can also use the lion elements directly, although this is likely not a commo
113
113
 
114
114
  ## Issues
115
115
 
116
- If you encounter an issue with any of the packages we are offering please open a [new bug issue](https://github.com/ing-bank/lion/issues/new?assignees=&labels=&template=bug_report.md&title=). Be sure to include a description of the expected and the current behavior - additional adding a [reproduction](https://webcomponents.dev/edit/kpZmz1CJN580OaXsk56f?pm=1) always helps.
116
+ If you encounter an issue with any of the packages we are offering please open a [new bug issue](https://github.com/ing-bank/lion/issues/new?assignees=&labels=&template=bug_report.md&title=). Be sure to include a description of the expected and the current behavior - additionally adding a [reproduction](https://webcomponents.dev/edit/kpZmz1CJN580OaXsk56f?pm=1) always helps.
117
117
 
118
118
  ## Feature requests
119
119
 
@@ -49,17 +49,7 @@ export class LionCheckboxIndeterminate extends LionCheckbox {
49
49
  * @protected
50
50
  */
51
51
  get _subCheckboxes() {
52
- let checkboxes = [];
53
- if (
54
- this._checkboxGroupNode &&
55
- this._checkboxGroupNode.formElements &&
56
- this._checkboxGroupNode.formElements.length > 0
57
- ) {
58
- checkboxes = this._checkboxGroupNode.formElements.filter(
59
- checkbox => checkbox !== this && this.contains(checkbox),
60
- );
61
- }
62
- return /** @type LionCheckbox[] */ (checkboxes);
52
+ return /** @type LionCheckbox[] */ (this.__subCheckboxes);
63
53
  }
64
54
 
65
55
  _storeIndeterminateState() {
@@ -97,9 +87,14 @@ export class LionCheckboxIndeterminate extends LionCheckbox {
97
87
  this.indeterminate = false;
98
88
  this.checked = false;
99
89
  break;
100
- default:
90
+ default: {
101
91
  this.indeterminate = true;
102
- this.checked = false;
92
+ const disabledUncheckedElements = subCheckboxes.filter(
93
+ checkbox => checkbox.disabled && checkbox.checked === false,
94
+ );
95
+ this.checked =
96
+ subCheckboxes.length - checkedElements.length - disabledUncheckedElements.length === 0;
97
+ }
103
98
  }
104
99
  this.updateComplete.then(() => {
105
100
  this.__settingOwnChecked = false;
@@ -155,13 +150,12 @@ export class LionCheckboxIndeterminate extends LionCheckbox {
155
150
  subCheckboxes.length > 0 && subCheckboxes.length === checkedElements.length;
156
151
  const allDisabled =
157
152
  subCheckboxes.length > 0 && subCheckboxes.length === disabledElements.length;
158
- const hasDisabledElements = disabledElements.length > 0;
159
153
 
160
154
  if (allDisabled) {
161
155
  this.checked = allChecked;
162
156
  }
163
157
 
164
- if (this.indeterminate && (this.mixedState || hasDisabledElements)) {
158
+ if (this.indeterminate && this.mixedState) {
165
159
  this._subCheckboxes.forEach((checkbox, i) => {
166
160
  // eslint-disable-next-line no-param-reassign
167
161
  checkbox.checked = this._indeterminateSubStates[i];
@@ -211,6 +205,7 @@ export class LionCheckboxIndeterminate extends LionCheckbox {
211
205
  if (!(/** @type {HTMLElement} */ (ev.target).hasAttribute('role'))) {
212
206
  /** @type {HTMLElement} */ (ev.target)?.setAttribute('role', 'listitem');
213
207
  }
208
+ this.__addToSubCheckboxes(/** @type {CustomEvent} */ (ev).detail.element);
214
209
  this._setOwnCheckedState();
215
210
  }
216
211
 
@@ -223,6 +218,26 @@ export class LionCheckboxIndeterminate extends LionCheckbox {
223
218
  if (/** @type {HTMLElement} */ (ev.target).getAttribute('role') === 'listitem') {
224
219
  /** @type {HTMLElement} */ (ev.target)?.removeAttribute('role');
225
220
  }
221
+ this.__removeFromSubCheckboxes(/** @type {CustomEvent} */ (ev).detail.element);
222
+ }
223
+
224
+ /**
225
+ * @param {HTMLElement} element
226
+ */
227
+ __addToSubCheckboxes(element) {
228
+ if (element !== this && this.contains(element)) {
229
+ this.__subCheckboxes.push(element);
230
+ }
231
+ }
232
+
233
+ /**
234
+ * @param {HTMLElement} element
235
+ */
236
+ __removeFromSubCheckboxes(element) {
237
+ const index = this.__subCheckboxes.indexOf(element);
238
+ if (index !== -1) {
239
+ this.__subCheckboxes.splice(index, 1);
240
+ }
226
241
  }
227
242
 
228
243
  constructor() {
@@ -230,6 +245,8 @@ export class LionCheckboxIndeterminate extends LionCheckbox {
230
245
  this.indeterminate = false;
231
246
  this._onRequestToAddFormElement = this._onRequestToAddFormElement.bind(this);
232
247
  this.__onModelValueChanged = this.__onModelValueChanged.bind(this);
248
+ /** @type {HTMLElement[]} */
249
+ this.__subCheckboxes = [];
233
250
  /** @type {boolean[]} */
234
251
  this._indeterminateSubStates = [];
235
252
  this.mixedState = false;
@@ -259,7 +276,13 @@ export class LionCheckboxIndeterminate extends LionCheckbox {
259
276
  /** @param {import('lit-element').PropertyValues } changedProperties */
260
277
  updated(changedProperties) {
261
278
  super.updated(changedProperties);
262
- if (changedProperties.has('indeterminate')) {
279
+
280
+ // When 1. sub checkboxes have disabled elements and 2. some elements are checked while the others are unchecked
281
+ // both this._inputNode.indeterminate and this.indeterminate are already true.
282
+ // If user clicks the input node, this._inputNode.indeterminate is turned to false by the browser
283
+ // while this.indeterminate is still true and the 'indeterminate' is not in the changedProperties
284
+ // because it hasn't been updated (true -> true) but checked would have been updated (false -> true).
285
+ if (changedProperties.has('indeterminate') || changedProperties.has('checked')) {
263
286
  this._inputNode.indeterminate = this.indeterminate;
264
287
  }
265
288
  }
@@ -205,7 +205,84 @@ export function runCheckboxIndeterminateSuite(customConfig) {
205
205
 
206
206
  // Assert
207
207
  expect(elIndeterminate?.hasAttribute('indeterminate')).to.be.true;
208
- expect(elIndeterminate?.checked).to.be.false;
208
+ expect(elIndeterminate?.checked).to.be.true;
209
+ });
210
+
211
+ it('should be checked when all children are prechecked', async () => {
212
+ // Arrange
213
+ const el = /** @type {LionCheckboxGroup} */ await fixture(html`
214
+ <${groupTag} name="scientists[]">
215
+ <${tag} label="Favorite scientists">
216
+ <${childTag} checked label="Archimedes"></${childTag}>
217
+ <${childTag} checked label="Francis Bacon"></${childTag}>
218
+ <${childTag} checked label="Marie Curie"></${childTag}>
219
+ </${tag}>
220
+ </${groupTag}>
221
+ `);
222
+
223
+ const elIndeterminate = /** @type {LionCheckboxIndeterminate} */ (
224
+ el.querySelector(`${cfg.tagString}`)
225
+ );
226
+
227
+ // Assert
228
+ expect(elIndeterminate?.hasAttribute('checked')).to.be.true;
229
+ });
230
+
231
+ it('should be checked when it has one prechecked child', async () => {
232
+ // Arrange
233
+ const el = /** @type {LionCheckboxGroup} */ await fixture(html`
234
+ <${groupTag} name="scientists[]">
235
+ <${tag} label="Favorite scientists">
236
+ <${childTag} checked label="Archimedes"></${childTag}>
237
+ </${tag}>
238
+ </${groupTag}>
239
+ `);
240
+
241
+ const elIndeterminate = /** @type {LionCheckboxIndeterminate} */ (
242
+ el.querySelector(`${cfg.tagString}`)
243
+ );
244
+
245
+ // Assert
246
+ expect(elIndeterminate?.hasAttribute('checked')).to.be.true;
247
+ });
248
+
249
+ it('should be unchecked when it has an disabled checked child and an unchecked child', async () => {
250
+ // Arrange
251
+ const el = /** @type {LionCheckboxGroup} */ await fixture(html`
252
+ <${groupTag} name="scientists[]">
253
+ <${tag} label="Favorite scientists">
254
+ <${childTag} disabled checked label="Archimedes"></${childTag}>
255
+ <${childTag} label="Francis Bacon"></${childTag}>
256
+ </${tag}>
257
+ </${groupTag}>
258
+ `);
259
+
260
+ const elIndeterminate = /** @type {LionCheckboxIndeterminate} */ (
261
+ el.querySelector(`${cfg.tagString}`)
262
+ );
263
+
264
+ // Assert
265
+ expect(elIndeterminate?.hasAttribute('checked')).to.be.false;
266
+ });
267
+
268
+ it('should be indeterminated when some of the children are prechecked', async () => {
269
+ // Arrange
270
+ const el = /** @type {LionCheckboxGroup} */ await fixture(html`
271
+ <${groupTag} name="scientists[]">
272
+ <${tag} label="Favorite scientists">
273
+ <${childTag} checked label="Archimedes"></${childTag}>
274
+ <${childTag} checked label="Francis Bacon"></${childTag}>
275
+ <${childTag} label="Marie Curie"></${childTag}>
276
+ </${tag}>
277
+ </${groupTag}>
278
+ `);
279
+
280
+ const elIndeterminate = /** @type {LionCheckboxIndeterminate} */ (
281
+ el.querySelector(`${cfg.tagString}`)
282
+ );
283
+
284
+ // Assert
285
+ expect(elIndeterminate.hasAttribute('indeterminate')).to.be.true;
209
286
  });
210
287
 
211
288
  it('should sync all children when parent is checked (from indeterminate to checked)', async () => {
@@ -384,6 +461,65 @@ export function runCheckboxIndeterminateSuite(customConfig) {
384
461
  expect(_subCheckboxes[2].hasAttribute('checked')).to.be.false;
385
462
  });
386
463
 
464
+ it('should sync all prechecked children when parent is indeterminate and some of the children are disabled (from checked to unchecked)', async () => {
465
+ // Arrange
466
+ const el = /** @type {LionCheckboxGroup} */ (
467
+ await fixture(html`
468
+ <${groupTag} name="scientists[]">
469
+ <${tag} label="Favorite scientists">
470
+ <${childTag} checked label="Archimedes"></${childTag}>
471
+ <${childTag} disabled label="Francis Bacon"></${childTag}>
472
+ <${childTag} checked label="Marie Curie"></${childTag}>
473
+ </${tag}>
474
+ </${groupTag}>
475
+ `)
476
+ );
477
+ const elIndeterminate = /** @type {LionCheckboxIndeterminate} */ (
478
+ el.querySelector(`${cfg.tagString}`)
479
+ );
480
+ const { _subCheckboxes, _inputNode } = getCheckboxIndeterminateMembers(elIndeterminate);
481
+
482
+ // Act
483
+ _inputNode.click();
484
+ await elIndeterminate.updateComplete;
485
+
486
+ // Assert
487
+ expect(elIndeterminate?.hasAttribute('indeterminate')).to.be.false;
488
+ expect(_inputNode?.hasAttribute('indeterminate')).to.be.false;
489
+ expect(_subCheckboxes[0].hasAttribute('checked')).to.be.false;
490
+ expect(_subCheckboxes[1].hasAttribute('checked')).to.be.false;
491
+ expect(_subCheckboxes[2].hasAttribute('checked')).to.be.false;
492
+ });
493
+
494
+ it('should stay as indeterminated after it is clicked, when it is interminated already and some children are disabled', async () => {
495
+ // Arrange
496
+ const el = /** @type {LionCheckboxGroup} */ (
497
+ await fixture(html`
498
+ <${groupTag} name="scientists[]">
499
+ <${tag} label="Favorite scientists">
500
+ <${childTag} checked label="Archimedes"></${childTag}>
501
+ <${childTag} disabled label="Francis Bacon"></${childTag}>
502
+ <${childTag} label="Marie Curie"></${childTag}>
503
+ </${tag}>
504
+ </${groupTag}>
505
+ `)
506
+ );
507
+ const elIndeterminate = /** @type {LionCheckboxIndeterminate} */ (
508
+ el.querySelector(`${cfg.tagString}`)
509
+ );
510
+ const { _subCheckboxes, _inputNode } = getCheckboxIndeterminateMembers(elIndeterminate);
511
+
512
+ // Act
513
+ _inputNode.click();
514
+ await elIndeterminate.updateComplete;
515
+
516
+ // Assert
517
+ expect(elIndeterminate.hasAttribute('indeterminate')).to.be.true;
518
+ expect(_inputNode.indeterminate).to.be.true;
519
+ expect(_subCheckboxes[0].hasAttribute('checked')).to.be.true;
520
+ expect(_subCheckboxes[2].hasAttribute('checked')).to.be.true;
521
+ });
522
+
387
523
  it('should work as expected with siblings checkbox-indeterminate', async () => {
388
524
  // Arrange
389
525
  const el = /** @type {LionCheckboxGroup} */ (
@@ -450,6 +586,58 @@ export function runCheckboxIndeterminateSuite(customConfig) {
450
586
  expect(elSecondSubCheckboxes._subCheckboxes[1].hasAttribute('checked')).to.be.false;
451
587
  });
452
588
 
589
+ it('should work as expected when new checkbox was added', async () => {
590
+ // Arrange
591
+ const el = /** @type {LionCheckboxGroup} */ await fixture(html`
592
+ <${groupTag} name="scientists[]">
593
+ <${tag} label="Favorite scientists">
594
+ <${childTag} checked label="Archimedes"></${childTag}>
595
+ <${childTag} checked label="Francis Bacon" checked></${childTag}>
596
+ <${childTag} checked label="Marie Curie"></${childTag}>
597
+ </${tag}>
598
+ </${groupTag}>
599
+ `);
600
+
601
+ const elIndeterminate = /** @type {LionCheckboxIndeterminate} */ (
602
+ el.querySelector(`${cfg.tagString}`)
603
+ );
604
+ expect(elIndeterminate.hasAttribute('indeterminate')).to.be.false;
605
+
606
+ // Act
607
+ const newChild = document.createElement(/** @type {string} */ (cfg.childTagString));
608
+ elIndeterminate.appendChild(newChild);
609
+ await elIndeterminate.updateComplete;
610
+
611
+ // Assert
612
+ expect(elIndeterminate.hasAttribute('indeterminate')).to.be.true;
613
+ });
614
+
615
+ it('should work as expected when an existing checkbox was removed', async () => {
616
+ // Arrange
617
+ const el = /** @type {LionCheckboxGroup} */ await fixture(html`
618
+ <${groupTag} name="scientists[]">
619
+ <${tag} label="Favorite scientists">
620
+ <${childTag} checked label="Archimedes"></${childTag}>
621
+ <${childTag} checked label="Francis Bacon" checked></${childTag}>
622
+ <${childTag} label="Marie Curie"></${childTag}>
623
+ </${tag}>
624
+ </${groupTag}>
625
+ `);
626
+
627
+ const elIndeterminate = /** @type {LionCheckboxIndeterminate} */ (
628
+ el.querySelector(`${cfg.tagString}`)
629
+ );
630
+ expect(elIndeterminate.hasAttribute('indeterminate')).to.be.true;
631
+ expect(elIndeterminate.checked).to.be.false;
632
+
633
+ // Act
634
+ elIndeterminate.removeChild(/** @type {ChildNode} */ (elIndeterminate.lastChild));
635
+ await elIndeterminate.updateComplete;
636
+
637
+ // Assert
638
+ expect(elIndeterminate?.hasAttribute('indeterminate')).to.be.true;
639
+ });
640
+
453
641
  it('should work as expected with nested indeterminate checkboxes', async () => {
454
642
  // Arrange
455
643
  const el = /** @type {LionCheckboxGroup} */ (
@@ -198,19 +198,19 @@ const FocusMixinImplementation = superclass =>
198
198
  * @private
199
199
  */
200
200
  __teardownEventsForFocusMixin() {
201
- this._focusableNode.removeEventListener(
201
+ this._focusableNode?.removeEventListener(
202
202
  'focus',
203
203
  /** @type {EventListenerOrEventListenerObject} */ (this.__redispatchFocus),
204
204
  );
205
- this._focusableNode.removeEventListener(
205
+ this._focusableNode?.removeEventListener(
206
206
  'blur',
207
207
  /** @type {EventListenerOrEventListenerObject} */ (this.__redispatchBlur),
208
208
  );
209
- this._focusableNode.removeEventListener(
209
+ this._focusableNode?.removeEventListener(
210
210
  'focusin',
211
211
  /** @type {EventListenerOrEventListenerObject} */ (this.__redispatchFocusin),
212
212
  );
213
- this._focusableNode.removeEventListener(
213
+ this._focusableNode?.removeEventListener(
214
214
  'focusout',
215
215
  /** @type {EventListenerOrEventListenerObject} */ (this.__redispatchFocusout),
216
216
  );
@@ -44,7 +44,7 @@ export class LionField extends FormControlMixin(
44
44
 
45
45
  disconnectedCallback() {
46
46
  super.disconnectedCallback();
47
- this._inputNode.removeEventListener('change', this._onChange);
47
+ this._inputNode?.removeEventListener('change', this._onChange);
48
48
  }
49
49
 
50
50
  resetInteractionState() {
@@ -67,11 +67,6 @@ export declare class LocalizeMixinHost {
67
67
 
68
68
  public localizeNamespacesLoaded: Promise<Object> | undefined;
69
69
 
70
- /**
71
- * Hook into LitElement to only render once all translations are loaded
72
- */
73
- public performUpdate(): Promise<void>;
74
-
75
70
  public onLocaleReady(): void;
76
71
  public onLocaleChanged(newLocale: string, oldLocale: string): void;
77
72
  public onLocaleUpdated(): void;
@@ -491,7 +491,7 @@ export class LionSelectRich extends SlotMixin(ScopedElementsMixin(OverlayMixin(L
491
491
  */
492
492
  // TODO: rename to #invokerOnKeyUp() (and move event listener to the invoker) in v1
493
493
  __onKeyUp(ev) {
494
- if (this.disabled || this.readOnly) {
494
+ if (this.disabled || this.readOnly || this.singleOption) {
495
495
  return;
496
496
  }
497
497
 
@@ -342,7 +342,7 @@ describe('lion-select-rich', () => {
342
342
  expect(elSingleoption.opened).to.be.false;
343
343
  });
344
344
 
345
- it('stays closed with [ArrowUp] or [ArrowDown] key in readonly mode', async () => {
345
+ it('stays closed with [ArrowUp] or [ArrowDown] key in readonly mode or has a single option', async () => {
346
346
  const elReadOnly = await fixture(html`
347
347
  <lion-select-rich readonly>
348
348
  <lion-option .choiceValue=${10}>Item 1</lion-option>
@@ -350,11 +350,23 @@ describe('lion-select-rich', () => {
350
350
  </lion-select-rich>
351
351
  `);
352
352
 
353
+ const elSingleOption = await fixture(html`
354
+ <lion-select-rich>
355
+ <lion-option .choiceValue=${10}>Item 1</lion-option>
356
+ </lion-select-rich>
357
+ `);
358
+
353
359
  elReadOnly.dispatchEvent(new KeyboardEvent('keyup', { key: 'ArrowDown' }));
354
360
  expect(elReadOnly.opened).to.be.false;
355
361
 
356
362
  elReadOnly.dispatchEvent(new KeyboardEvent('keyup', { key: 'ArrowUp' }));
357
363
  expect(elReadOnly.opened).to.be.false;
364
+
365
+ elSingleOption.dispatchEvent(new KeyboardEvent('keyup', { key: 'ArrowDown' }));
366
+ expect(elSingleOption.opened).to.be.false;
367
+
368
+ elSingleOption.dispatchEvent(new KeyboardEvent('keyup', { key: 'ArrowUp' }));
369
+ expect(elSingleOption.opened).to.be.false;
358
370
  });
359
371
 
360
372
  it('sets inheritsReferenceWidth to min by default', async () => {