@lion/ui 0.1.5 → 0.2.0

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 (146) hide show
  1. package/components/accordion/src/LionAccordion.js +2 -2
  2. package/components/accordion/test/lion-accordion.test.js +31 -0
  3. package/components/combobox/src/LionCombobox.js +106 -14
  4. package/components/combobox/src/validators.js +18 -0
  5. package/components/combobox/test/lion-combobox.test.js +261 -184
  6. package/components/combobox/test/validators.test.js +62 -0
  7. package/components/combobox/test-helpers/combobox-helpers.js +125 -0
  8. package/components/form-core/types/choice-group/ChoiceGroupMixinTypes.ts +4 -3
  9. package/components/input-datepicker/src/LionInputDatepicker.js +9 -1
  10. package/components/input-iban/translations/de.js +1 -1
  11. package/components/listbox/src/ListboxMixin.js +6 -0
  12. package/components/listbox/test-suites/ListboxMixin.suite.js +13 -7
  13. package/components/overlays/src/OverlayController.js +2 -1
  14. package/components/overlays/test/OverlayController.test.js +1 -1
  15. package/components/switch/src/LionSwitch.js +0 -3
  16. package/components/switch/src/LionSwitchButton.js +14 -1
  17. package/components/switch/test/lion-switch-button.test.js +15 -1
  18. package/components/switch/test/lion-switch.test.js +21 -6
  19. package/components/validate-messages/src/loadDefaultFeedbackMessagesNoSideEffects.js +11 -8
  20. package/components/validate-messages/translations/bg.js +4 -0
  21. package/components/validate-messages/translations/cs.js +2 -0
  22. package/components/validate-messages/translations/de.js +4 -0
  23. package/components/validate-messages/translations/en.js +2 -0
  24. package/components/validate-messages/translations/es.js +4 -0
  25. package/components/validate-messages/translations/fr.js +4 -0
  26. package/components/validate-messages/translations/hu.js +2 -0
  27. package/components/validate-messages/translations/it.js +4 -0
  28. package/components/validate-messages/translations/nl.js +4 -0
  29. package/components/validate-messages/translations/pl.js +2 -0
  30. package/components/validate-messages/translations/ro.js +4 -0
  31. package/components/validate-messages/translations/ru.js +4 -0
  32. package/components/validate-messages/translations/sk.js +2 -0
  33. package/components/validate-messages/translations/uk.js +4 -0
  34. package/components/validate-messages/translations/zh.js +2 -0
  35. package/custom-elements.json +1346 -55
  36. package/dist-types/components/combobox/src/LionCombobox.d.ts +37 -13
  37. package/dist-types/components/combobox/src/LionCombobox.d.ts.map +1 -1
  38. package/dist-types/components/combobox/src/validators.d.ts +13 -0
  39. package/dist-types/components/combobox/src/validators.d.ts.map +1 -0
  40. package/dist-types/components/combobox/test/lion-combobox.test.d.ts +0 -2
  41. package/dist-types/components/combobox/test/lion-combobox.test.d.ts.map +1 -1
  42. package/dist-types/components/combobox/test/validators.test.d.ts +2 -0
  43. package/dist-types/components/combobox/test/validators.test.d.ts.map +1 -0
  44. package/dist-types/components/combobox/test-helpers/combobox-helpers.d.ts +41 -0
  45. package/dist-types/components/combobox/test-helpers/combobox-helpers.d.ts.map +1 -0
  46. package/dist-types/components/form-core/types/choice-group/ChoiceGroupMixinTypes.d.ts +4 -3
  47. package/dist-types/components/form-core/types/choice-group/ChoiceGroupMixinTypes.d.ts.map +1 -1
  48. package/dist-types/components/input-datepicker/src/LionInputDatepicker.d.ts +4 -0
  49. package/dist-types/components/input-datepicker/src/LionInputDatepicker.d.ts.map +1 -1
  50. package/dist-types/components/listbox/src/ListboxMixin.d.ts.map +1 -1
  51. package/dist-types/components/listbox/test-suites/ListboxMixin.suite.d.ts.map +1 -1
  52. package/dist-types/components/overlays/src/OverlayController.d.ts.map +1 -1
  53. package/dist-types/components/switch/src/LionSwitch.d.ts +0 -1
  54. package/dist-types/components/switch/src/LionSwitch.d.ts.map +1 -1
  55. package/dist-types/components/switch/src/LionSwitchButton.d.ts +3 -0
  56. package/dist-types/components/switch/src/LionSwitchButton.d.ts.map +1 -1
  57. package/dist-types/components/switch/test/lion-switch.test.d.ts +1 -1
  58. package/dist-types/components/switch/test/lion-switch.test.d.ts.map +1 -1
  59. package/dist-types/components/validate-messages/src/loadDefaultFeedbackMessagesNoSideEffects.d.ts.map +1 -1
  60. package/dist-types/components/validate-messages/translations/bg-BG.d.ts +2 -0
  61. package/dist-types/components/validate-messages/translations/bg.d.ts +3 -0
  62. package/dist-types/components/validate-messages/translations/cs-CZ.d.ts +2 -0
  63. package/dist-types/components/validate-messages/translations/cs.d.ts +3 -0
  64. package/dist-types/components/validate-messages/translations/de-DE.d.ts +2 -0
  65. package/dist-types/components/validate-messages/translations/de.d.ts +3 -0
  66. package/dist-types/components/validate-messages/translations/en-AU.d.ts +2 -0
  67. package/dist-types/components/validate-messages/translations/en-GB.d.ts +2 -0
  68. package/dist-types/components/validate-messages/translations/en-PH.d.ts +2 -0
  69. package/dist-types/components/validate-messages/translations/en-US.d.ts +2 -0
  70. package/dist-types/components/validate-messages/translations/en.d.ts +3 -0
  71. package/dist-types/components/validate-messages/translations/es-ES.d.ts +2 -0
  72. package/dist-types/components/validate-messages/translations/es.d.ts +3 -0
  73. package/dist-types/components/validate-messages/translations/fr-BE.d.ts +2 -0
  74. package/dist-types/components/validate-messages/translations/fr-FR.d.ts +2 -0
  75. package/dist-types/components/validate-messages/translations/fr.d.ts +3 -0
  76. package/dist-types/components/validate-messages/translations/hu-HU.d.ts +2 -0
  77. package/dist-types/components/validate-messages/translations/hu.d.ts +3 -0
  78. package/dist-types/components/validate-messages/translations/it-IT.d.ts +2 -0
  79. package/dist-types/components/validate-messages/translations/it.d.ts +3 -0
  80. package/dist-types/components/validate-messages/translations/nl-BE.d.ts +2 -0
  81. package/dist-types/components/validate-messages/translations/nl-NL.d.ts +2 -0
  82. package/dist-types/components/validate-messages/translations/nl.d.ts +3 -0
  83. package/dist-types/components/validate-messages/translations/pl-PL.d.ts +2 -0
  84. package/dist-types/components/validate-messages/translations/pl.d.ts +3 -0
  85. package/dist-types/components/validate-messages/translations/ro-RO.d.ts +2 -0
  86. package/dist-types/components/validate-messages/translations/ro.d.ts +3 -0
  87. package/dist-types/components/validate-messages/translations/ru-RU.d.ts +2 -0
  88. package/dist-types/components/validate-messages/translations/ru.d.ts +3 -0
  89. package/dist-types/components/validate-messages/translations/sk-SK.d.ts +2 -0
  90. package/dist-types/components/validate-messages/translations/sk.d.ts +3 -0
  91. package/dist-types/components/validate-messages/translations/uk-UA.d.ts +2 -0
  92. package/dist-types/components/validate-messages/translations/uk.d.ts +3 -0
  93. package/dist-types/components/validate-messages/translations/zh.d.ts +3 -0
  94. package/dist-types/exports/combobox-test-helpers.d.ts +2 -0
  95. package/dist-types/exports/combobox-test-helpers.d.ts.map +1 -0
  96. package/dist-types/exports/combobox.d.ts +1 -0
  97. package/dist-types/tsconfig.tsbuildinfo +1 -1
  98. package/docs/components/checkbox-group/overview.md +2 -2
  99. package/docs/components/collapsible/overview.md +1 -1
  100. package/docs/components/combobox/overview.md +12 -2
  101. package/docs/components/combobox/use-cases.md +36 -1
  102. package/docs/components/dialog/overview.md +1 -1
  103. package/docs/components/fieldset/overview.md +5 -5
  104. package/docs/components/form/overview.md +3 -3
  105. package/docs/components/icon/use-cases.md +1 -1
  106. package/docs/components/input/overview.md +1 -1
  107. package/docs/components/input-amount/overview.md +3 -3
  108. package/docs/components/input-date/overview.md +3 -3
  109. package/docs/components/input-datepicker/overview.md +5 -5
  110. package/docs/components/input-email/overview.md +2 -2
  111. package/docs/components/input-iban/overview.md +2 -2
  112. package/docs/components/input-range/overview.md +2 -2
  113. package/docs/components/input-stepper/overview.md +1 -1
  114. package/docs/components/input-tel/overview.md +1 -1
  115. package/docs/components/input-tel/use-cases.md +6 -6
  116. package/docs/components/input-tel-dropdown/overview.md +1 -1
  117. package/docs/components/radio-group/overview.md +3 -3
  118. package/docs/components/select-rich/use-cases.md +1 -1
  119. package/docs/components/tabs/examples.md +1 -1
  120. package/docs/fundamentals/index.md +4 -4
  121. package/docs/fundamentals/node-tools/providence-analytics/LocalConfiguration.md +1 -1
  122. package/docs/fundamentals/node-tools/providence-analytics/QueryResult.md +1 -1
  123. package/docs/fundamentals/node-tools/providence-analytics/analyzer.md +1 -1
  124. package/docs/fundamentals/node-tools/providence-analytics/dashboard.md +1 -1
  125. package/docs/fundamentals/node-tools/providence-analytics/overview.md +3 -3
  126. package/docs/fundamentals/node-tools/publish-docs/overview.md +3 -3
  127. package/docs/fundamentals/node-tools/rocket-preset-extend-lion-docs/overview.md +2 -2
  128. package/docs/fundamentals/systems/core/overview.md +1 -1
  129. package/docs/fundamentals/systems/form/formatting-and-parsing.md +4 -4
  130. package/docs/fundamentals/systems/form/model-value.md +1 -1
  131. package/docs/fundamentals/systems/form/overview.md +28 -28
  132. package/docs/fundamentals/systems/form/validate.md +1 -1
  133. package/docs/fundamentals/systems/localize/overview.md +4 -4
  134. package/docs/fundamentals/systems/overlays/configuration.md +2 -2
  135. package/docs/fundamentals/systems/overlays/overview.md +5 -5
  136. package/docs/fundamentals/systems/overlays/use-cases.md +2 -2
  137. package/docs/fundamentals/tools/helpers/overview.md +1 -1
  138. package/docs/fundamentals/tools/singleton-manager/overview.md +4 -4
  139. package/docs/guides/how-to/create-a-custom-field.md +5 -5
  140. package/docs/guides/how-to/extend-a-native-input.md +2 -2
  141. package/docs/guides/index.md +8 -8
  142. package/docs/guides/principles/index.md +5 -5
  143. package/docs/guides/principles/styling.md +1 -1
  144. package/exports/combobox-test-helpers.js +1 -0
  145. package/exports/combobox.js +1 -0
  146. package/package.json +1 -1
@@ -0,0 +1,125 @@
1
+ import { getListboxMembers } from '@lion/ui/listbox-test-helpers.js';
2
+
3
+ /**
4
+ * @typedef {import('@lion/ui/combobox.js').LionCombobox} LionCombobox
5
+ */
6
+
7
+ /**
8
+ * @param { LionCombobox } el
9
+ */
10
+ export function getComboboxMembers(el) {
11
+ const obj = getListboxMembers(el);
12
+ return {
13
+ ...obj,
14
+ ...{
15
+ // @ts-ignore [allow-protected] in test
16
+ _invokerNode: el._invokerNode,
17
+ // @ts-ignore [allow-protected] in test
18
+ _overlayCtrl: el._overlayCtrl,
19
+ // @ts-ignore [allow-protected] in test
20
+ _comboboxNode: el._comboboxNode,
21
+ // @ts-ignore [allow-protected] in test
22
+ _inputNode: el._inputNode,
23
+ // @ts-ignore [allow-protected] in test
24
+ _listboxNode: el._listboxNode,
25
+ // @ts-ignore [allow-protected] in test
26
+ _selectionDisplayNode: el._selectionDisplayNode,
27
+ // @ts-ignore [allow-protected] in test
28
+ _activeDescendantOwnerNode: el._activeDescendantOwnerNode,
29
+ // @ts-ignore [allow-protected] in test
30
+ _ariaVersion: el._ariaVersion,
31
+ },
32
+ };
33
+ }
34
+
35
+ /**
36
+ * @param {LionCombobox} el
37
+ * @param {string} value
38
+ */
39
+ // TODO: add keys that actually make sense...
40
+ export function mimicUserTyping(el, value) {
41
+ const { _inputNode } = getComboboxMembers(el);
42
+ _inputNode.dispatchEvent(new Event('focusin', { bubbles: true }));
43
+ // eslint-disable-next-line no-param-reassign
44
+ _inputNode.value = value;
45
+ _inputNode.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
46
+ _inputNode.dispatchEvent(new KeyboardEvent('keyup', { key: value }));
47
+ _inputNode.dispatchEvent(new KeyboardEvent('keydown', { key: value }));
48
+ }
49
+
50
+ /**
51
+ * @param {HTMLElement} el
52
+ * @param {string} key
53
+ */
54
+ export function mimicKeyPress(el, key) {
55
+ el.dispatchEvent(new KeyboardEvent('keydown', { key }));
56
+ el.dispatchEvent(new KeyboardEvent('keyup', { key }));
57
+ }
58
+
59
+ /**
60
+ * @param {LionCombobox} el
61
+ * @param {string[]} values
62
+ */
63
+ export async function mimicUserTypingAdvanced(el, values) {
64
+ const { _inputNode } = getComboboxMembers(el);
65
+ _inputNode.dispatchEvent(new Event('focusin', { bubbles: true }));
66
+
67
+ for (const key of values) {
68
+ // eslint-disable-next-line no-await-in-loop, no-loop-func
69
+ await new Promise(resolve => {
70
+ const hasSelection = _inputNode.selectionStart !== _inputNode.selectionEnd;
71
+
72
+ if (key === 'Backspace') {
73
+ if (hasSelection) {
74
+ _inputNode.value =
75
+ _inputNode.value.slice(
76
+ 0,
77
+ _inputNode.selectionStart ? _inputNode.selectionStart : undefined,
78
+ ) +
79
+ _inputNode.value.slice(
80
+ _inputNode.selectionEnd ? _inputNode.selectionEnd : undefined,
81
+ _inputNode.value.length,
82
+ );
83
+ } else {
84
+ _inputNode.value = _inputNode.value.slice(0, -1);
85
+ }
86
+ } else if (hasSelection) {
87
+ _inputNode.value =
88
+ _inputNode.value.slice(
89
+ 0,
90
+ _inputNode.selectionStart ? _inputNode.selectionStart : undefined,
91
+ ) +
92
+ key +
93
+ _inputNode.value.slice(
94
+ _inputNode.selectionEnd ? _inputNode.selectionEnd : undefined,
95
+ _inputNode.value.length,
96
+ );
97
+ } else {
98
+ _inputNode.value += key;
99
+ }
100
+
101
+ mimicKeyPress(_inputNode, key);
102
+ _inputNode.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
103
+
104
+ el.updateComplete.then(() => {
105
+ // @ts-ignore
106
+ resolve();
107
+ });
108
+ });
109
+ }
110
+ }
111
+
112
+ /**
113
+ * @param {LionCombobox} el
114
+ */
115
+ export function getFilteredOptionValues(el) {
116
+ const options = el.formElements;
117
+ /**
118
+ * @param {{ style: { display: string; }; }} option
119
+ */
120
+ const filtered = options.filter(option => option.getAttribute('aria-hidden') !== 'true');
121
+ /**
122
+ * @param {{ value: any; }} option
123
+ */
124
+ return filtered.map(option => option.value);
125
+ }
@@ -1,9 +1,10 @@
1
1
  import { Constructor } from '@open-wc/dedupe-mixin';
2
2
  import { LitElement } from 'lit';
3
- import { FormControlHost } from '../FormControlMixinTypes.js';
4
3
  import { FormControl } from '../form-group/FormGroupMixinTypes.js';
5
- import { FormRegistrarHost } from '../registration/FormRegistrarMixinTypes.js';
4
+ import { FormControlHost } from '../FormControlMixinTypes.js';
6
5
  import { InteractionStateHost } from '../InteractionStateMixinTypes.js';
6
+ import { FormRegistrarHost } from '../registration/FormRegistrarMixinTypes.js';
7
+ import { ChoiceInputHost } from './ChoiceInputMixinTypes.js';
7
8
 
8
9
  export declare class ChoiceGroupHost {
9
10
  multipleChoice: boolean;
@@ -26,7 +27,7 @@ export declare class ChoiceGroupHost {
26
27
  protected _throwWhenInvalidChildModelValue(child: FormControlHost): void;
27
28
  protected _isEmpty(): void;
28
29
  protected _checkSingleChoiceElements(ev: Event): void;
29
- protected _getCheckedElements(): void;
30
+ protected _getCheckedElements(): ChoiceInputHost[];
30
31
  protected _setCheckedElements(value: any, check: boolean): void;
31
32
  protected _onBeforeRepropagateChildrenValues(ev: Event): void;
32
33
 
@@ -279,11 +279,19 @@ export class LionInputDatepicker extends ScopedElementsMixin(
279
279
  aria-label="${this.msgLit('lion-input-datepicker:openDatepickerLabel')}"
280
280
  title="${this.msgLit('lion-input-datepicker:openDatepickerLabel')}"
281
281
  >
282
- 📅
282
+ ${this._invokerIconTemplate()}
283
283
  </button>
284
284
  `;
285
285
  }
286
286
 
287
+ /**
288
+ * Subclassers can replace this with their custom extension invoker icon
289
+ */
290
+ // eslint-disable-next-line class-methods-use-this
291
+ _invokerIconTemplate() {
292
+ return html`📅`;
293
+ }
294
+
287
295
  _setupOverlayCtrl() {
288
296
  super._setupOverlayCtrl();
289
297
 
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  error: {
3
- IsIBAN: 'Geben Sie ein gültiges {fieldName} ein.',
3
+ IsIBAN: 'Geben Sie eine gültige {fieldName} ein.',
4
4
  IsCountryIBAN:
5
5
  'Geben Sie eine gültige {params, select,\n' +
6
6
  'AT {Österreichisch}\n' +
@@ -635,6 +635,9 @@ const ListboxMixinImplementation = superclass =>
635
635
  }
636
636
  break;
637
637
  case 'ArrowLeft':
638
+ if (this._listboxReceivesNoFocus) {
639
+ return;
640
+ }
638
641
  ev.preventDefault();
639
642
  if (this.orientation === 'horizontal') {
640
643
  this.activeIndex = this._getPreviousEnabledOption(this.activeIndex);
@@ -647,6 +650,9 @@ const ListboxMixinImplementation = superclass =>
647
650
  }
648
651
  break;
649
652
  case 'ArrowRight':
653
+ if (this._listboxReceivesNoFocus) {
654
+ return;
655
+ }
650
656
  ev.preventDefault();
651
657
  if (this.orientation === 'horizontal') {
652
658
  this.activeIndex = this._getNextEnabledOption(this.activeIndex);
@@ -861,6 +861,7 @@ export function runListboxMixinSuite(customConfig = {}) {
861
861
  mimicKeyPress(_listboxNode, 'End');
862
862
  expect(el.activeIndex).to.equal(3);
863
863
  });
864
+
864
865
  it('navigates through open lists with [ArrowDown] [ArrowUp] keys activates the option', async () => {
865
866
  const el = /** @type {LionListbox} */ (
866
867
  await fixture(html`
@@ -936,7 +937,7 @@ export function runListboxMixinSuite(customConfig = {}) {
936
937
  it('uses [ArrowLeft] and [ArrowRight] keys when "horizontal"', async () => {
937
938
  const el = /** @type {LionListbox} */ (
938
939
  await fixture(html`
939
- <${tag} opened name="foo" orientation="horizontal" autocomplete="none" show-all-on-empty>
940
+ <${tag} ._listboxReceivesNoFocus="${false}" opened name="foo" orientation="horizontal" autocomplete="none" show-all-on-empty>
940
941
  <${optionTag} .choiceValue="${'Artichoke'}">Artichoke</${optionTag}>
941
942
  <${optionTag} .choiceValue="${'Chard'}">Chard</${optionTag}>
942
943
  </${tag}>
@@ -948,15 +949,12 @@ export function runListboxMixinSuite(customConfig = {}) {
948
949
 
949
950
  // Normalize for suite tests
950
951
  el.activeIndex = 0;
951
-
952
952
  await el.updateComplete;
953
953
 
954
954
  mimicKeyPress(_listboxNode, 'ArrowRight');
955
-
956
955
  expect(el.activeIndex).to.equal(1);
957
956
 
958
957
  mimicKeyPress(_listboxNode, 'ArrowLeft');
959
-
960
958
  expect(el.activeIndex).to.equal(0);
961
959
 
962
960
  // No response to vertical arrows...
@@ -965,7 +963,14 @@ export function runListboxMixinSuite(customConfig = {}) {
965
963
 
966
964
  el.activeIndex = 1;
967
965
  mimicKeyPress(_listboxNode, 'ArrowUp');
966
+ expect(el.activeIndex).to.equal(1);
967
+
968
+ // @ts-ignore allow protected member access in test
969
+ el._listboxReceivesNoFocus = true;
970
+ mimicKeyPress(_listboxNode, 'ArrowLeft');
971
+ expect(el.activeIndex).to.equal(1);
968
972
 
973
+ mimicKeyPress(_listboxNode, 'ArrowRight');
969
974
  expect(el.activeIndex).to.equal(1);
970
975
  });
971
976
 
@@ -1141,6 +1146,7 @@ export function runListboxMixinSuite(customConfig = {}) {
1141
1146
  expect(el.checkedIndex).to.equal(0);
1142
1147
  expectOnlyGivenOneOptionToBeChecked(options, 0);
1143
1148
  });
1149
+
1144
1150
  it('navigates through list with [ArrowLeft] [ArrowRight] keys when horizontal: activates and checks the option', async () => {
1145
1151
  /**
1146
1152
  * @param {LionOption[]} options
@@ -1157,7 +1163,7 @@ export function runListboxMixinSuite(customConfig = {}) {
1157
1163
  }
1158
1164
  const el = /** @type {LionListbox} */ (
1159
1165
  await fixture(html`
1160
- <${tag} opened selection-follows-focus orientation="horizontal" autocomplete="none" show-all-on-empty>
1166
+ <${tag} ._listboxReceivesNoFocus="${false}" opened selection-follows-focus orientation="horizontal" autocomplete="none" show-all-on-empty>
1161
1167
  <${optionTag} .choiceValue=${10}>Item 1</${optionTag}>
1162
1168
  <${optionTag} .choiceValue=${20}>Item 2</${optionTag}>
1163
1169
  <${optionTag} .choiceValue=${30}>Item 3</${optionTag}>
@@ -1453,7 +1459,7 @@ export function runListboxMixinSuite(customConfig = {}) {
1453
1459
  )}
1454
1460
  </${tag}>
1455
1461
  `);
1456
- el.checkedIndex = 0;
1462
+ el.setCheckedIndex(0);
1457
1463
  expect(el.modelValue).to.deep.equal({
1458
1464
  type: 'mastercard',
1459
1465
  label: 'Master Card',
@@ -1461,7 +1467,7 @@ export function runListboxMixinSuite(customConfig = {}) {
1461
1467
  active: true,
1462
1468
  });
1463
1469
 
1464
- el.checkedIndex = 1;
1470
+ el.setCheckedIndex(1);
1465
1471
  expect(el.modelValue).to.deep.equal({
1466
1472
  type: 'visacard',
1467
1473
  label: 'Visa Card',
@@ -575,7 +575,8 @@ export class OverlayController extends EventTarget {
575
575
  // N.B. position: fixed is needed to escape out of 'overflow: hidden'
576
576
  // We give a high z-index for non-modal dialogs, so that we at least win from all siblings of our
577
577
  // parent stacking context
578
- wrappingDialogElement.style.cssText = `display:none; z-index: ${this.config.zIndex};`;
578
+ // padding reset so we don't get a weird dialog visual square showing up
579
+ wrappingDialogElement.style.cssText = `display:none; z-index: ${this.config.zIndex}; padding: 0;`;
579
580
  this.__wrappingDialogNode = wrappingDialogElement;
580
581
 
581
582
  /**
@@ -21,7 +21,7 @@ import { createShadowHost } from '../test-helpers/createShadowHost.js';
21
21
  * @typedef {import('../types/OverlayConfig.js').ViewportPlacement} ViewportPlacement
22
22
  */
23
23
 
24
- const wrappingDialogNodeStyle = 'display: none; z-index: 9999;';
24
+ const wrappingDialogNodeStyle = 'display: none; z-index: 9999; padding: 0px;';
25
25
 
26
26
  /**
27
27
  * Make sure that all browsers serialize html in a similar way
@@ -80,9 +80,6 @@ export class LionSwitch extends ScopedElementsMixin(ChoiceInputMixin(LionField))
80
80
 
81
81
  connectedCallback() {
82
82
  super.connectedCallback();
83
- if (!this.role) {
84
- this.role = 'switch';
85
- }
86
83
  this.addEventListener('checked-changed', this.__handleButtonSwitchCheckedChanged);
87
84
  if (this._labelNode) {
88
85
  this._labelNode.addEventListener('click', this._toggleChecked);
@@ -78,6 +78,7 @@ export class LionSwitchButton extends DisabledWithTabIndexMixin(LitElement) {
78
78
 
79
79
  this.role = 'switch';
80
80
  this.checked = false;
81
+ this.__initialized = false;
81
82
  /** @protected */
82
83
  this._toggleChecked = this._toggleChecked.bind(this);
83
84
  /** @private */
@@ -158,8 +159,20 @@ export class LionSwitchButton extends DisabledWithTabIndexMixin(LitElement) {
158
159
  */
159
160
  requestUpdate(name, oldValue, options) {
160
161
  super.requestUpdate(name, oldValue, options);
161
- if (this.isConnected && name === 'checked' && this.checked !== oldValue && !this.disabled) {
162
+ if (
163
+ this.__initialized &&
164
+ this.isConnected &&
165
+ name === 'checked' &&
166
+ this.checked !== oldValue &&
167
+ !this.disabled
168
+ ) {
162
169
  this.__checkedStateChange();
163
170
  }
164
171
  }
172
+
173
+ /** @param {import('lit').PropertyValues } changedProperties */
174
+ firstUpdated(changedProperties) {
175
+ super.firstUpdated(changedProperties);
176
+ this.__initialized = true;
177
+ }
165
178
  }
@@ -1,4 +1,4 @@
1
- import { expect, fixture as _fixture } from '@open-wc/testing';
1
+ import { expect, fixture as _fixture, fixtureSync, elementUpdated } from '@open-wc/testing';
2
2
  import { html } from 'lit/static-html.js';
3
3
  import sinon from 'sinon';
4
4
  import '@lion/ui/define/lion-switch-button.js';
@@ -126,6 +126,20 @@ describe('lion-switch-button', () => {
126
126
  expect(handlerSpy.called).to.be.false;
127
127
  });
128
128
 
129
+ it('should not dispatch "checked-changed" event if not initialized on update', async () => {
130
+ const handlerSpy = sinon.spy();
131
+ const elSync = /** @type {LionSwitchButton} */ (
132
+ fixtureSync(html`<lion-switch-button @checked-changed="${handlerSpy}" .checked=${true} />`)
133
+ );
134
+ expect(elSync.__initialized).to.be.false;
135
+ await elementUpdated(elSync);
136
+ expect(elSync.__initialized).to.be.true;
137
+ expect(handlerSpy.called).to.be.false;
138
+ elSync.checked = !elSync.checked;
139
+ await elementUpdated(elSync);
140
+ expect(handlerSpy.called).to.be.true;
141
+ });
142
+
129
143
  describe('a11y', () => {
130
144
  it('should manage "aria-checked"', async () => {
131
145
  expect(el.hasAttribute('aria-checked')).to.be.true;
@@ -10,7 +10,7 @@ import '@lion/ui/define/lion-switch.js';
10
10
  /**
11
11
  * @typedef {import('../src/LionSwitchButton.js').LionSwitchButton} LionSwitchButton
12
12
  * @typedef {import('lit').TemplateResult} TemplateResult
13
- * @typedef {import('../../form-core/types/FormControlMixinTypes.js').FormControlHost} FormControlHost
13
+ * @typedef {import('@lion/ui/types/form-core.js').FormControlHost} FormControlHost
14
14
  */
15
15
 
16
16
  const IsTrue = class extends Validator {
@@ -215,10 +215,25 @@ describe('lion-switch', () => {
215
215
  expect(el.showsFeedbackFor).to.eql(['info']);
216
216
  });
217
217
 
218
- it('should not cause error by setting an attribute in the constructor', async () => {
219
- const div = await fixture(html`<div></div>`);
220
- const el = /** @type {LionSwitch} */ (document.createElement('lion-switch'));
221
- div.appendChild(el);
222
- expect(el.role).to.equal('switch');
218
+ describe('Accessibility', () => {
219
+ it('passes axe a11y audit', async () => {
220
+ const el = await fixture(html`<lion-switch name="hi" label="My label"></lion-switch>`);
221
+ await expect(el).to.be.accessible();
222
+
223
+ el.checked = true;
224
+ await el.updateComplete;
225
+ await expect(el).to.be.accessible();
226
+ });
227
+
228
+ it('passes axe a11y audit when disabled', async () => {
229
+ const el = await fixture(
230
+ html`<lion-switch name="hi" label="My label" disabled></lion-switch>`,
231
+ );
232
+ await expect(el).to.be.accessible();
233
+
234
+ el.checked = true;
235
+ await el.updateComplete;
236
+ await expect(el).to.be.accessible();
237
+ });
223
238
  });
224
239
  });
@@ -1,22 +1,23 @@
1
1
  /* eslint-disable import/no-extraneous-dependencies */
2
+ import { MatchesOption } from '@lion/ui/combobox.js';
2
3
  import {
3
4
  DefaultSuccess,
5
+ EqualsLength,
4
6
  IsDate,
5
7
  IsDateDisabled,
8
+ IsEmail,
9
+ IsNumber,
6
10
  MaxDate,
11
+ MaxLength,
12
+ MaxNumber,
7
13
  MinDate,
14
+ MinLength,
8
15
  MinMaxDate,
9
- IsNumber,
10
- MaxNumber,
16
+ MinMaxLength,
11
17
  MinMaxNumber,
12
18
  MinNumber,
13
- Required,
14
- EqualsLength,
15
- IsEmail,
16
- MaxLength,
17
- MinLength,
18
- MinMaxLength,
19
19
  Pattern,
20
+ Required,
20
21
  } from '@lion/ui/form-core.js';
21
22
  import { PhoneNumber } from '@lion/ui/input-tel.js';
22
23
 
@@ -162,6 +163,8 @@ export function loadDefaultFeedbackMessagesNoSideEffects({ localize }) {
162
163
  MinMaxDate.getMessage = async data => getLocalizedMessage(data);
163
164
  /** @param {FeedbackMessageData} data */
164
165
  IsDateDisabled.getMessage = async data => getLocalizedMessage(data);
166
+ /** @param {FeedbackMessageData} data */
167
+ MatchesOption.getMessage = async data => getLocalizedMessage(data);
165
168
 
166
169
  DefaultSuccess.getMessage = async data => {
167
170
  await forMessagesToBeReady();
@@ -17,6 +17,8 @@ export default {
17
17
  'Моля, въведете {fieldName} между {params.min, date, YYYYMMDD} и {params.max, date, YYYYMMDD}.',
18
18
  IsDateDisabled: 'Тази дата не е на разположение, моля, изберете друга.',
19
19
  IsEmail: 'Моля, въведете валиден {fieldName} с формат "name@example.com".',
20
+ MatchesOption:
21
+ 'Не са открити съответстващи резултати. Моля, опитайте с друга ключова дума или категория.',
20
22
  },
21
23
  warning: {
22
24
  Required: 'Моля, въведете също {fieldName}.',
@@ -35,6 +37,8 @@ export default {
35
37
  'Моля, въведете {fieldName} между {params.min, date, YYYYMMDD} и {params.max, date, YYYYMMDD}.',
36
38
  IsDateDisabled: 'Тази дата не е на разположение, моля, изберете друга.',
37
39
  IsEmail: 'Моля, въведете валиден {fieldName} с формат "name@example.com".',
40
+ MatchesOption:
41
+ 'Не са открити съответстващи резултати. Моля, опитайте с друга ключова дума или категория.',
38
42
  },
39
43
  success: {
40
44
  DefaultOk: 'Добре',
@@ -17,6 +17,7 @@ export default {
17
17
  'Zadejte {fieldName} od {params.min, date, YYYYMMDD} do {params.max, date, YYYYMMDD}.',
18
18
  IsDateDisabled: 'Toto datum je nedostupné, vyberte jiné.',
19
19
  IsEmail: 'Zadejte platný {fieldName} ve formátu "name@example.com".',
20
+ MatchesOption: 'Žádné odpovídající výsledky. Zkuste jiné klíčové slovo nebo kategorii.',
20
21
  },
21
22
  warning: {
22
23
  Required: 'Zadejte rovněž {fieldName}.',
@@ -35,6 +36,7 @@ export default {
35
36
  'Zadejte {fieldName} od {params.min, date, YYYYMMDD} do {params.max, date, YYYYMMDD}.',
36
37
  IsDateDisabled: 'Toto datum je nedostupné, vyberte jiné.',
37
38
  IsEmail: 'Zadejte platný {fieldName} ve formátu "name@example.com".',
39
+ MatchesOption: 'Žádné odpovídající výsledky. Zkuste jiné klíčové slovo nebo kategorii.',
38
40
  },
39
41
  success: {
40
42
  DefaultOk: 'Dobře',
@@ -18,6 +18,8 @@ export default {
18
18
  'Geben Sie für {fieldName} einen Wert zwischen {params.min, date, YYYYMMDD} und {params.max, date, YYYYMMDD} ein.',
19
19
  IsDateDisabled: 'Dieses Datum ist nicht verfügbar, bitte wählen Sie ein anderes Datum.',
20
20
  IsEmail: 'Geben Sie einen gültige {fieldName} im Format „name@example.com“ ein.',
21
+ MatchesOption:
22
+ 'Keine übereinstimmenden Ergebnisse. Bitte versuchen Sie es mit einem anderen Schlüsselbegriff oder einer anderen Kategorie.',
21
23
  },
22
24
  warning: {
23
25
  Required: '{fieldName} sollte ausgefüllt werden.',
@@ -37,6 +39,8 @@ export default {
37
39
  'Geben Sie für {fieldName} einen Wert zwischen {params.min, date, YYYYMMDD} und {params.max, date, YYYYMMDD} ein.',
38
40
  IsDateDisabled: 'Dieses Datum ist nicht verfügbar, bitte wählen Sie ein anderes Datum.',
39
41
  IsEmail: 'Geben Sie einen gültige {fieldName} im Format „name@example.com“ ein.',
42
+ MatchesOption:
43
+ 'Keine übereinstimmenden Ergebnisse. Bitte versuchen Sie es mit einem anderen Schlüsselbegriff oder einer anderen Kategorie.',
40
44
  },
41
45
  success: {
42
46
  DefaultOk: 'OK',
@@ -18,6 +18,7 @@ export default {
18
18
  'Please enter a {fieldName} between {params.min, date, YYYYMMDD} and {params.max, date, YYYYMMDD}.',
19
19
  IsDateDisabled: 'This date is unavailable, please choose another one.',
20
20
  IsEmail: 'Please enter a valid {fieldName} in the format "name@example.com".',
21
+ MatchesOption: 'No matching results. Please try a different keyword or category.',
21
22
  },
22
23
  warning: {
23
24
  Required: 'Please enter a(n) {fieldName}.',
@@ -37,6 +38,7 @@ export default {
37
38
  'Please enter a {fieldName} between {params.min, date, YYYYMMDD} and {params.max, date, YYYYMMDD}.',
38
39
  IsDateDisabled: 'This date is unavailable, please choose another one.',
39
40
  IsEmail: 'Please enter a valid {fieldName} in the format "name@example.com".',
41
+ MatchesOption: 'No matching results. Please try a different keyword or category.',
40
42
  },
41
43
  success: {
42
44
  DefaultOk: 'Okay',
@@ -18,6 +18,8 @@ export default {
18
18
  'Introduzca un/a {fieldName} entre {params.min, date, YYYYMMDD} y {params.max, date, YYYYMMDD}.',
19
19
  IsDateDisabled: 'Esta fecha no está disponible. Elija otra.',
20
20
  IsEmail: 'Introduzca un/a {fieldName} válido/a con el formato "nombre@ejemplo.com".',
21
+ MatchesOption:
22
+ 'No hay resultados que coincidan. Pruebe con una palabra clave o categoría diferente.',
21
23
  },
22
24
  warning: {
23
25
  Required: 'Introduzca también un/a {fieldName}.',
@@ -37,6 +39,8 @@ export default {
37
39
  'Introduzca un/a {fieldName} entre {params.min, date, YYYYMMDD} y {params.max, date, YYYYMMDD}.',
38
40
  IsDateDisabled: 'Esta fecha no está disponible. Elija otra.',
39
41
  IsEmail: 'Introduzca un/a {fieldName} válido/a con el formato "nombre@ejemplo.com".',
42
+ MatchesOption:
43
+ 'No hay resultados que coincidan. Pruebe con una palabra clave o categoría diferente.',
40
44
  },
41
45
  success: {
42
46
  DefaultOk: 'Vale',
@@ -19,6 +19,8 @@ export default {
19
19
  'Veuillez indiquer un(e) {fieldName} entre {params.min, date, YYYYMMDD} et {params.max, date, YYYYMMDD}.',
20
20
  IsDateDisabled: "Cette date n'est pas disponible, veuillez en choisir une autre.",
21
21
  IsEmail: 'Veuillez indiquer un(e) {fieldName} au format "nom@exemple.com".',
22
+ MatchesOption:
23
+ 'Aucun résultat correspondant. Veuillez essayer un autre mot-clé ou une autre catégorie.',
22
24
  },
23
25
  warning: {
24
26
  Required: 'Veuillez également indiquer un(e) {fieldName}.',
@@ -39,6 +41,8 @@ export default {
39
41
  'Veuillez indiquer un(e) {fieldName} entre {params.min, date, YYYYMMDD} et {params.max, date, YYYYMMDD}.',
40
42
  IsDateDisabled: "Cette date n'est pas disponible, veuillez en choisir une autre.",
41
43
  IsEmail: 'Veuillez indiquer un(e) {fieldName} au format "nom@exemple.com".',
44
+ MatchesOption:
45
+ 'Aucun résultat correspondant. Veuillez essayer un autre mot-clé ou une autre catégorie.',
42
46
  },
43
47
  success: {
44
48
  DefaultOk: 'Ok',
@@ -19,6 +19,7 @@ export default {
19
19
  IsDateDisabled: 'Ez a dátum nem áll rendelkezésre, válasszon egy másikat.',
20
20
  IsEmail:
21
21
  'Adjon meg egy érvényes {fieldName} értéket, a következő formátumban: „név@példa.com”.',
22
+ MatchesOption: 'Nincs egyező találat. Próbálkozzon másik kulcsszóval vagy kategóriával.',
22
23
  },
23
24
  warning: {
24
25
  Required: 'Továbbá adjon meg egy {fieldName} értéket.',
@@ -39,6 +40,7 @@ export default {
39
40
  IsDateDisabled: 'Ez a dátum nem áll rendelkezésre, válasszon egy másikat.',
40
41
  IsEmail:
41
42
  'Adjon meg egy érvényes {fieldName} értéket, a következő formátumban: „név@példa.com”.',
43
+ MatchesOption: 'Nincs egyező találat. Próbálkozzon másik kulcsszóval vagy kategóriával.',
42
44
  },
43
45
  success: {
44
46
  DefaultOk: 'Rendben',
@@ -18,6 +18,8 @@ export default {
18
18
  'Inserire un(a) {fieldName} tra {params.min, date, YYYYMMDD} e {params.max, date, YYYYMMDD}.',
19
19
  IsDateDisabled: "ТQuesta data non è disponibile, sceglierne un'altra.",
20
20
  IsEmail: 'Inserire un valore valido per {fieldName} nel formato "name@example.com".',
21
+ MatchesOption:
22
+ 'Nessun risultato corrispondente. Provare con una parola chiave o una categoria diversa.',
21
23
  },
22
24
  warning: {
23
25
  Required: 'Inserire anche un(a) {fieldName}.',
@@ -37,6 +39,8 @@ export default {
37
39
  'Inserire un(a) {fieldName} tra {params.min, date, YYYYMMDD} e {params.max, date, YYYYMMDD}.',
38
40
  IsDateDisabled: "ТQuesta data non è disponibile, sceglierne un'altra.",
39
41
  IsEmail: 'Inserire un valore valido per {fieldName} nel formato "name@example.com".',
42
+ MatchesOption:
43
+ 'Nessun risultato corrispondente. Provare con una parola chiave o una categoria diversa.',
40
44
  },
41
45
  success: {
42
46
  DefaultOk: 'OK',
@@ -17,6 +17,8 @@ export default {
17
17
  'Vul een {fieldName} in tussen {params.min, date, YYYYMMDD} en {params.max, date, YYYYMMDD}.',
18
18
  IsDateDisabled: 'Deze datum is niet mogelijk, kies een andere.',
19
19
  IsEmail: 'Vul een {fieldName} in formaat "name@example.com".',
20
+ MatchesOption:
21
+ 'Geen overeenkomende resultaten. Probeer een ander trefwoord of een andere categorie.',
20
22
  },
21
23
  warning: {
22
24
  Required: 'Vul een {fieldName} in.',
@@ -35,6 +37,8 @@ export default {
35
37
  'Vul een {fieldName} in tussen {params.min, date, YYYYMMDD} en {params.max, date, YYYYMMDD}.',
36
38
  IsDateDisabled: 'Deze datum is niet mogelijk, kies een andere.',
37
39
  IsEmail: 'Vul een {fieldName} in formaat "name@example.com".',
40
+ MatchesOption:
41
+ 'Geen overeenkomende resultaten. Probeer een ander trefwoord of een andere categorie.',
38
42
  },
39
43
  success: {
40
44
  DefaultOk: 'Okee',
@@ -18,6 +18,7 @@ export default {
18
18
  'Proszę podać wartość {fieldName} między {params.min, date, YYYYMMDD} a {params.max, date, YYYYMMDD}.',
19
19
  IsDateDisabled: 'Ta data jest niedostępna, wybierz inną.',
20
20
  IsEmail: 'Proszę podać prawidłowy {fieldName} w formacie „nazwa@example.com”.',
21
+ MatchesOption: 'Brak pasujących wyników. Spróbuj użyć innego słowa kluczowego lub kategorii.',
21
22
  },
22
23
  warning: {
23
24
  Required: 'Proszę również podać wartość {fieldName}.',
@@ -37,6 +38,7 @@ export default {
37
38
  'Proszę podać wartość {fieldName} między {params.min, date, YYYYMMDD} a {params.max, date, YYYYMMDD}.',
38
39
  IsDateDisabled: 'Ta data jest niedostępna, wybierz inną.',
39
40
  IsEmail: 'Proszę podać prawidłowy {fieldName} w formacie „nazwa@example.com”.',
41
+ MatchesOption: 'Brak pasujących wyników. Spróbuj użyć innego słowa kluczowego lub kategorii.',
40
42
  },
41
43
  success: {
42
44
  DefaultOk: 'Ok',
@@ -18,6 +18,8 @@ export default {
18
18
  'Introduceți un/o {fieldName} cuprins(ă) între {params.min, date, YYYYMMDD} și {params.max, date, YYYYMMDD}.',
19
19
  IsDateDisabled: 'Această dată nu este disponibilă, alegeți alta.',
20
20
  IsEmail: 'Introduceți un/o {fieldName} valid(ă) în formatul „nume@exemplu.com”.',
21
+ MatchesOption:
22
+ 'Niciun rezultat corespunzător. Încercaţi un cuvânt cheie sau o categorie diferită.',
21
23
  },
22
24
  warning: {
23
25
  Required: 'Introduceți un/o {fieldName}.',
@@ -37,6 +39,8 @@ export default {
37
39
  'Introduceți un/o {fieldName} cuprins(ă) între {params.min, date, YYYYMMDD} și {params.max, date, YYYYMMDD}.',
38
40
  IsDateDisabled: 'Această dată nu este disponibilă, alegeți alta.',
39
41
  IsEmail: 'Introduceți un/o {fieldName} valid(ă) în formatul „nume@exemplu.com”.',
42
+ MatchesOption:
43
+ 'Niciun rezultat corespunzător. Încercaţi un cuvânt cheie sau o categorie diferită.',
40
44
  },
41
45
  success: {
42
46
  DefaultOk: 'În regulă',