@lion/ui 0.9.0 → 0.9.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 (65) hide show
  1. package/components/combobox/src/LionCombobox.js +6 -2
  2. package/components/combobox/test/lion-combobox.test.js +56 -3
  3. package/components/form-integrations/test/form-integrations.test.js +2 -2
  4. package/components/input-datepicker/translations/es.js +1 -1
  5. package/components/input-stepper/src/LionInputStepper.js +70 -42
  6. package/components/input-stepper/test/lion-input-stepper.test.js +48 -12
  7. package/components/input-tel-dropdown/src/LionInputTelDropdown.js +7 -6
  8. package/components/input-tel-dropdown/test/LionInputTelDropdown.test.js +50 -0
  9. package/custom-elements.json +35 -39
  10. package/dist-types/components/combobox/src/LionCombobox.d.ts.map +1 -1
  11. package/dist-types/components/input-stepper/src/LionInputStepper.d.ts +22 -24
  12. package/dist-types/components/input-stepper/src/LionInputStepper.d.ts.map +1 -1
  13. package/dist-types/components/input-tel-dropdown/src/LionInputTelDropdown.d.ts.map +1 -1
  14. package/dist-types/components/input-tel-dropdown/test/LionInputTelDropdown.test.d.ts.map +1 -1
  15. package/dist-types/tsconfig.tsbuildinfo +1 -1
  16. package/docs/components/checkbox-group/overview.md +2 -2
  17. package/docs/components/collapsible/overview.md +1 -1
  18. package/docs/components/combobox/overview.md +1 -1
  19. package/docs/components/combobox/use-cases.md +1 -1
  20. package/docs/components/dialog/overview.md +1 -1
  21. package/docs/components/fieldset/overview.md +5 -5
  22. package/docs/components/form/overview.md +3 -3
  23. package/docs/components/form/use-cases.md +2 -2
  24. package/docs/components/icon/use-cases.md +1 -1
  25. package/docs/components/input/overview.md +1 -1
  26. package/docs/components/input-amount/overview.md +3 -3
  27. package/docs/components/input-date/overview.md +3 -3
  28. package/docs/components/input-datepicker/overview.md +5 -5
  29. package/docs/components/input-email/overview.md +2 -2
  30. package/docs/components/input-file/overview.md +1 -1
  31. package/docs/components/input-iban/overview.md +2 -2
  32. package/docs/components/input-range/overview.md +2 -2
  33. package/docs/components/input-stepper/api-table.md +3 -3
  34. package/docs/components/input-stepper/overview.md +1 -1
  35. package/docs/components/input-tel/overview.md +1 -1
  36. package/docs/components/input-tel/use-cases.md +6 -6
  37. package/docs/components/input-tel-dropdown/overview.md +1 -1
  38. package/docs/components/listbox/use-cases.md +1 -1
  39. package/docs/components/radio-group/overview.md +3 -3
  40. package/docs/components/select/use-cases.md +1 -1
  41. package/docs/components/select-rich/use-cases.md +1 -1
  42. package/docs/components/tabs/examples.md +1 -1
  43. package/docs/fundamentals/index.md +4 -4
  44. package/docs/fundamentals/node-tools/publish-docs/overview.md +3 -3
  45. package/docs/fundamentals/node-tools/rocket-preset-extend-lion-docs/overview.md +2 -2
  46. package/docs/fundamentals/rationales/accessibility.md +1 -1
  47. package/docs/fundamentals/systems/core/SlotMixin.md +1 -1
  48. package/docs/fundamentals/systems/core/overview.md +1 -1
  49. package/docs/fundamentals/systems/form/formatting-and-parsing.md +4 -4
  50. package/docs/fundamentals/systems/form/model-value.md +1 -1
  51. package/docs/fundamentals/systems/form/overview.md +28 -28
  52. package/docs/fundamentals/systems/form/validate.md +2 -2
  53. package/docs/fundamentals/systems/localize/overview.md +4 -4
  54. package/docs/fundamentals/systems/overlays/configuration.md +2 -2
  55. package/docs/fundamentals/systems/overlays/overview.md +5 -5
  56. package/docs/fundamentals/systems/overlays/use-cases.md +2 -2
  57. package/docs/fundamentals/tools/helpers/overview.md +1 -1
  58. package/docs/fundamentals/tools/singleton-manager/overview.md +4 -4
  59. package/docs/guides/how-to/create-a-custom-field.md +5 -5
  60. package/docs/guides/how-to/create-a-form.md +4 -4
  61. package/docs/guides/how-to/extend-a-native-input.md +2 -2
  62. package/docs/guides/index.md +8 -8
  63. package/docs/guides/principles/index.md +5 -5
  64. package/docs/guides/principles/styling.md +1 -1
  65. package/package.json +1 -1
@@ -663,7 +663,11 @@ export class LionCombobox extends LocalizeMixin(OverlayMixin(CustomChoiceGroupMi
663
663
  ) {
664
664
  return false;
665
665
  }
666
- if (this.filled || this.showAllOnEmpty) {
666
+ if (
667
+ this.filled ||
668
+ this.showAllOnEmpty ||
669
+ (!this.filled && this.multipleChoice && this.__prevCboxValueNonSelected)
670
+ ) {
667
671
  return true;
668
672
  }
669
673
  // when no keyboard action involved (on focused change), return current opened state
@@ -705,7 +709,7 @@ export class LionCombobox extends LocalizeMixin(OverlayMixin(CustomChoiceGroupMi
705
709
  // eslint-disable-next-line no-unused-vars
706
710
  _textboxOnInput(ev) {
707
711
  this.__shouldAutocompleteNextUpdate = true;
708
- this.opened = true;
712
+ this.opened = this._showOverlayCondition({});
709
713
  }
710
714
 
711
715
  /**
@@ -931,6 +931,50 @@ describe('lion-combobox', () => {
931
931
  expect(el.opened).to.equal(false);
932
932
  });
933
933
 
934
+ it('does not flash the menu when _showOverlayCondition returns "false"', async () => {
935
+ class ComplexCombobox extends LionCombobox {
936
+ _showOverlayCondition() {
937
+ return false;
938
+ }
939
+ }
940
+
941
+ const tagName = defineCE(ComplexCombobox);
942
+ const tag = unsafeStatic(tagName);
943
+
944
+ const el = /** @type {LionCombobox} */ (
945
+ await fixture(html`
946
+ <${tag} name="combo" label="Display only the label once selected">
947
+ <lion-option .choiceValue="${'Artichoke'}">Artichoke</lion-option>
948
+ <lion-option .choiceValue="${'Chard'}">Chard</lion-option>
949
+ <lion-option .choiceValue="${'Chicory'}">Chicory</lion-option>
950
+ <lion-option .choiceValue="${'Victoria Plum'}">Victoria Plum</lion-option>
951
+ </${tag}>
952
+ `)
953
+ );
954
+
955
+ const dialog = el.shadowRoot?.querySelector('dialog');
956
+ /**
957
+ * hasDropdownFlashed is `true` if the menu was shown for a short period of time and then got closed
958
+ */
959
+ let hasDropdownFlashed = false;
960
+ const observer = new MutationObserver(mutationList => {
961
+ // eslint-disable-next-line no-unused-vars
962
+ for (const mutation of mutationList) {
963
+ if (dialog?.style.display === '') {
964
+ hasDropdownFlashed = true;
965
+ }
966
+ }
967
+ });
968
+ observer.observe(/** @type {Node} */ (dialog), { attributeFilter: ['style'] });
969
+
970
+ const { _inputNode } = getComboboxMembers(el);
971
+ _inputNode.focus();
972
+ await sendKeys({
973
+ type: 'art',
974
+ });
975
+ expect(hasDropdownFlashed).to.be.false;
976
+ });
977
+
934
978
  it('shows overlay on click when filled', async () => {
935
979
  const el = /** @type {LionCombobox} */ (
936
980
  await fixture(html`
@@ -1157,7 +1201,10 @@ describe('lion-combobox', () => {
1157
1201
  class ShowOverlayConditionCombobox extends LionCombobox {
1158
1202
  /** @param {{ currentValue: string, lastKey:string }} options */
1159
1203
  _showOverlayCondition(options) {
1160
- return options.currentValue.length > 3 && super._showOverlayCondition(options);
1204
+ return (
1205
+ // @ts-ignore
1206
+ this.__prevCboxValueNonSelected.length > 3 && super._showOverlayCondition(options)
1207
+ );
1161
1208
  }
1162
1209
  }
1163
1210
  const tagName = defineCE(ShowOverlayConditionCombobox);
@@ -1182,7 +1229,10 @@ describe('lion-combobox', () => {
1182
1229
  class ShowOverlayConditionCombobox extends LionCombobox {
1183
1230
  /** @param {{ currentValue: string, lastKey:string }} options */
1184
1231
  _showOverlayCondition(options) {
1185
- return options.currentValue.length > 3 && super._showOverlayCondition(options);
1232
+ return (
1233
+ // @ts-ignore
1234
+ this.__prevCboxValueNonSelected.length > 3 && super._showOverlayCondition(options)
1235
+ );
1186
1236
  }
1187
1237
  }
1188
1238
  const tagName = defineCE(ShowOverlayConditionCombobox);
@@ -1207,7 +1257,10 @@ describe('lion-combobox', () => {
1207
1257
  class ShowOverlayConditionCombobox extends LionCombobox {
1208
1258
  /** @param {{ currentValue: string, lastKey:string }} options */
1209
1259
  _showOverlayCondition(options) {
1210
- return options.currentValue.length > 3 && super._showOverlayCondition(options);
1260
+ return (
1261
+ // @ts-ignore
1262
+ this.__prevCboxValueNonSelected.length > 3 && super._showOverlayCondition(options)
1263
+ );
1211
1264
  }
1212
1265
  }
1213
1266
  const tagName = defineCE(ShowOverlayConditionCombobox);
@@ -48,7 +48,7 @@ describe('Form Integrations', () => {
48
48
  notifications: { value: '', checked: false },
49
49
  rsvp: '',
50
50
  tel: '',
51
- 'tel-dropdown': '+44',
51
+ 'tel-dropdown': '',
52
52
  comments: '',
53
53
  });
54
54
  });
@@ -82,7 +82,7 @@ describe('Form Integrations', () => {
82
82
  notifications: '',
83
83
  rsvp: '',
84
84
  tel: '',
85
- 'tel-dropdown': '+44',
85
+ 'tel-dropdown': '',
86
86
  comments: '',
87
87
  });
88
88
  });
@@ -1,3 +1,3 @@
1
1
  export default {
2
- openDatepickerLabel: 'Selector de fecha abierta',
2
+ openDatepickerLabel: 'Abrir selector de fecha',
3
3
  };
@@ -21,6 +21,19 @@ export class LionInputStepper extends LocalizeMixin(LionInput) {
21
21
  .input-group__container > .input-group__input ::slotted(.form-control) {
22
22
  text-align: center;
23
23
  }
24
+
25
+ .input-stepper__value {
26
+ position: absolute;
27
+ width: 1px;
28
+ height: 1px;
29
+ overflow: hidden;
30
+ clip-path: inset(100%);
31
+ clip: rect(1px, 1px, 1px, 1px);
32
+ white-space: nowrap;
33
+ border: 0;
34
+ margin: 0;
35
+ padding: 0;
36
+ }
24
37
  `,
25
38
  ];
26
39
  }
@@ -83,7 +96,8 @@ export class LionInputStepper extends LocalizeMixin(LionInput) {
83
96
 
84
97
  this.__increment = this.__increment.bind(this);
85
98
  this.__decrement = this.__decrement.bind(this);
86
- this.__boundOnLeaveButton = this._onLeaveButton.bind(this);
99
+ this._onEnterButton = this._onEnterButton.bind(this);
100
+ this._onLeaveButton = this._onLeaveButton.bind(this);
87
101
  }
88
102
 
89
103
  connectedCallback() {
@@ -93,11 +107,12 @@ export class LionInputStepper extends LocalizeMixin(LionInput) {
93
107
  min: this.min,
94
108
  step: this.step,
95
109
  };
96
-
97
- this.role = 'spinbutton';
110
+ if (this._inputNode) {
111
+ this._inputNode.role = 'spinbutton';
112
+ this._inputNode.setAttribute('inputmode', 'decimal');
113
+ this._inputNode.setAttribute('autocomplete', 'off');
114
+ }
98
115
  this.addEventListener('keydown', this.__keyDownHandler);
99
- this._inputNode.setAttribute('inputmode', 'decimal');
100
- this._inputNode.setAttribute('autocomplete', 'off');
101
116
  this.__setDefaultValidators();
102
117
  this.__toggleSpinnerButtonsState();
103
118
  }
@@ -119,9 +134,9 @@ export class LionInputStepper extends LocalizeMixin(LionInput) {
119
134
  this._inputNode.min = `${this.min}`;
120
135
  this.values.min = this.min;
121
136
  if (this.min !== Infinity) {
122
- this.setAttribute('aria-valuemin', `${this.min}`);
137
+ this._inputNode.setAttribute('aria-valuemin', `${this.min}`);
123
138
  } else {
124
- this.removeAttribute('aria-valuemin');
139
+ this._inputNode.removeAttribute('aria-valuemin');
125
140
  }
126
141
  this.__toggleSpinnerButtonsState();
127
142
  }
@@ -130,9 +145,9 @@ export class LionInputStepper extends LocalizeMixin(LionInput) {
130
145
  this._inputNode.max = `${this.max}`;
131
146
  this.values.max = this.max;
132
147
  if (this.max !== Infinity) {
133
- this.setAttribute('aria-valuemax', `${this.max}`);
148
+ this._inputNode.setAttribute('aria-valuemax', `${this.max}`);
134
149
  } else {
135
- this.removeAttribute('aria-valuemax');
150
+ this._inputNode.removeAttribute('aria-valuemax');
136
151
  }
137
152
  this.__toggleSpinnerButtonsState();
138
153
  }
@@ -145,14 +160,6 @@ export class LionInputStepper extends LocalizeMixin(LionInput) {
145
160
  this._inputNode.step = `${this.step}`;
146
161
  this.values.step = this.step;
147
162
  }
148
-
149
- if (changedProperties.has('_ariaLabelledNodes')) {
150
- this.__reflectAriaAttrToSpinButton('aria-labelledby', this._ariaLabelledNodes);
151
- }
152
-
153
- if (changedProperties.has('_ariaDescribedNodes')) {
154
- this.__reflectAriaAttrToSpinButton('aria-describedby', this._ariaDescribedNodes);
155
- }
156
163
  }
157
164
 
158
165
  get slots() {
@@ -163,22 +170,6 @@ export class LionInputStepper extends LocalizeMixin(LionInput) {
163
170
  };
164
171
  }
165
172
 
166
- /**
167
- * Based on FormControlMixin __reflectAriaAttr()
168
- *
169
- * Will handle help text, validation feedback and character counter,
170
- * prefix/suffix/before/after (if they contain data-description flag attr).
171
- * Also, contents of id references that will be put in the <lion-field>._ariaDescribedby property
172
- * from an external context, will be read by a screen reader.
173
- * @param {string} attrName
174
- * @param {Element[]} nodes
175
- * @private
176
- */
177
- __reflectAriaAttrToSpinButton(attrName, nodes) {
178
- const string = nodes.map(n => n.id).join(' ');
179
- this.setAttribute(attrName, string);
180
- }
181
-
182
173
  /**
183
174
  * Set aria labels and apply validators
184
175
  * @private
@@ -227,7 +218,6 @@ export class LionInputStepper extends LocalizeMixin(LionInput) {
227
218
  }
228
219
  decrementButton[disableDecrementor ? 'setAttribute' : 'removeAttribute']('disabled', 'true');
229
220
  incrementButton[disableIncrementor ? 'setAttribute' : 'removeAttribute']('disabled', 'true');
230
-
231
221
  this._updateAriaAttributes();
232
222
  }
233
223
 
@@ -237,21 +227,22 @@ export class LionInputStepper extends LocalizeMixin(LionInput) {
237
227
  _updateAriaAttributes() {
238
228
  const displayValue = this._inputNode.value;
239
229
  if (displayValue) {
240
- this.setAttribute('aria-valuenow', `${displayValue}`);
230
+ this._inputNode.setAttribute('aria-valuenow', `${displayValue}`);
241
231
  if (
242
232
  Object.keys(this.valueTextMapping).length !== 0 &&
243
233
  Object.keys(this.valueTextMapping).find(key => Number(key) === this.currentValue)
244
234
  ) {
245
- this.setAttribute('aria-valuetext', `${this.valueTextMapping[this.currentValue]}`);
235
+ this.__valueText = this.valueTextMapping[this.currentValue];
246
236
  } else {
247
237
  // VoiceOver announces percentages once the valuemin or valuemax are used.
248
238
  // This can be fixed by setting valuetext to the same value as valuenow
249
239
  // https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-valuenow
250
- this.setAttribute('aria-valuetext', `${displayValue}`);
240
+ this.__valueText = displayValue;
251
241
  }
242
+ this._inputNode.setAttribute('aria-valuetext', `${this.__valueText}`);
252
243
  } else {
253
- this.removeAttribute('aria-valuenow');
254
- this.removeAttribute('aria-valuetext');
244
+ this._inputNode.removeAttribute('aria-valuenow');
245
+ this._inputNode.removeAttribute('aria-valuetext');
255
246
  }
256
247
  }
257
248
 
@@ -373,7 +364,8 @@ export class LionInputStepper extends LocalizeMixin(LionInput) {
373
364
  <button
374
365
  ?disabled=${this.disabled || this.readOnly}
375
366
  @click=${this.__decrement}
376
- @blur=${this.__boundOnLeaveButton}
367
+ @focus=${this._onEnterButton}
368
+ @blur=${this._onLeaveButton}
377
369
  type="button"
378
370
  aria-label="${this.msgLit('lion-input-stepper:decrease')}"
379
371
  >
@@ -392,7 +384,8 @@ export class LionInputStepper extends LocalizeMixin(LionInput) {
392
384
  <button
393
385
  ?disabled=${this.disabled || this.readOnly}
394
386
  @click=${this.__increment}
395
- @blur=${this.__boundOnLeaveButton}
387
+ @focus=${this._onEnterButton}
388
+ @blur=${this._onLeaveButton}
396
389
  type="button"
397
390
  aria-label="${this.msgLit('lion-input-stepper:increase')}"
398
391
  >
@@ -401,6 +394,33 @@ export class LionInputStepper extends LocalizeMixin(LionInput) {
401
394
  `;
402
395
  }
403
396
 
397
+ /** @protected */
398
+ _inputGroupTemplate() {
399
+ return html`
400
+ <div class="input-stepper__value">${this.__valueText}</div>
401
+ <div class="input-group">
402
+ ${this._inputGroupBeforeTemplate()}
403
+ <div class="input-group__container">
404
+ ${this._inputGroupPrefixTemplate()} ${this._inputGroupInputTemplate()}
405
+ ${this._inputGroupSuffixTemplate()}
406
+ </div>
407
+ ${this._inputGroupAfterTemplate()}
408
+ </div>
409
+ `;
410
+ }
411
+
412
+ /**
413
+ * @protected
414
+ * @param {Event} ev
415
+ */
416
+ // eslint-disable-next-line no-unused-vars
417
+ _onEnterButton(ev) {
418
+ const valueNode = /** @type {HTMLElement} */ (
419
+ this.shadowRoot?.querySelector('.input-stepper__value')
420
+ );
421
+ valueNode.setAttribute('aria-live', 'assertive');
422
+ }
423
+
404
424
  /**
405
425
  * Redispatch leave event on host when catching leave event
406
426
  * on the incrementor and decrementor button.
@@ -410,8 +430,16 @@ export class LionInputStepper extends LocalizeMixin(LionInput) {
410
430
  *
411
431
  * Interacting with the buttons is "user interactions"
412
432
  * the same way as focusing + blurring the field (native input)
433
+ *
434
+ * @protected
435
+ * @param {Event} ev
413
436
  */
414
- _onLeaveButton() {
437
+ // eslint-disable-next-line no-unused-vars
438
+ _onLeaveButton(ev) {
439
+ const valueNode = /** @type {HTMLElement} */ (
440
+ this.shadowRoot?.querySelector('.input-stepper__value')
441
+ );
442
+ valueNode.removeAttribute('aria-live');
415
443
  this.dispatchEvent(new Event(this._leaveEvent));
416
444
  }
417
445
  }
@@ -278,17 +278,23 @@ describe('<lion-input-stepper>', () => {
278
278
  await expect(el).to.be.accessible();
279
279
  });
280
280
 
281
+ it('has role="spinbutton"', async () => {
282
+ const el = await fixture(defaultInputStepper);
283
+ expect(el._inputNode.hasAttribute('role')).to.be.true;
284
+ expect(el._inputNode.getAttribute('role')).to.equal('spinbutton');
285
+ });
286
+
281
287
  it('updates aria-valuenow when stepper is changed', async () => {
282
288
  const el = await fixture(defaultInputStepper);
283
289
  el.modelValue = 1;
284
290
 
285
291
  await el.updateComplete;
286
- expect(el.hasAttribute('aria-valuenow')).to.be.true;
287
- expect(el.getAttribute('aria-valuenow')).to.equal('1');
292
+ expect(el._inputNode.hasAttribute('aria-valuenow')).to.be.true;
293
+ expect(el._inputNode.getAttribute('aria-valuenow')).to.equal('1');
288
294
 
289
295
  el.modelValue = '';
290
296
  await el.updateComplete;
291
- expect(el.hasAttribute('aria-valuenow')).to.be.false;
297
+ expect(el._inputNode.hasAttribute('aria-valuenow')).to.be.false;
292
298
  });
293
299
 
294
300
  it('updates aria-valuetext when stepper is changed', async () => {
@@ -299,12 +305,12 @@ describe('<lion-input-stepper>', () => {
299
305
  el.modelValue = 1;
300
306
  await el.updateComplete;
301
307
 
302
- expect(el.hasAttribute('aria-valuetext')).to.be.true;
303
- expect(el.getAttribute('aria-valuetext')).to.equal('1');
308
+ expect(el._inputNode.hasAttribute('aria-valuetext')).to.be.true;
309
+ expect(el._inputNode.getAttribute('aria-valuetext')).to.equal('1');
304
310
 
305
311
  el.modelValue = '';
306
312
  await el.updateComplete;
307
- expect(el.hasAttribute('aria-valuetext')).to.be.false;
313
+ expect(el._inputNode.hasAttribute('aria-valuetext')).to.be.false;
308
314
  });
309
315
 
310
316
  it('can give aria-valuetext to override default value as a human-readable text alternative', async () => {
@@ -318,30 +324,60 @@ describe('<lion-input-stepper>', () => {
318
324
  `);
319
325
  el.modelValue = 1;
320
326
  await el.updateComplete;
321
- expect(el.hasAttribute('aria-valuetext')).to.be.true;
322
- expect(el.getAttribute('aria-valuetext')).to.equal('first');
327
+ expect(el._inputNode.hasAttribute('aria-valuetext')).to.be.true;
328
+ expect(el._inputNode.getAttribute('aria-valuetext')).to.equal('first');
323
329
  });
324
330
 
325
331
  it('updates aria-valuemin when stepper is changed', async () => {
326
332
  const el = await fixture(inputStepperWithAttrs);
327
333
  const incrementButton = el.querySelector('[slot=suffix]');
328
334
  incrementButton?.dispatchEvent(new Event('click'));
329
- expect(el).to.have.attribute('aria-valuemin', '100');
335
+ expect(el._inputNode.hasAttribute('aria-valuemin')).to.be.true;
336
+ expect(el._inputNode.getAttribute('aria-valuemin')).to.equal('100');
330
337
 
331
338
  el.min = 0;
332
339
  await el.updateComplete;
333
- expect(el).to.have.attribute('aria-valuemin', '0');
340
+ expect(el._inputNode.hasAttribute('aria-valuemin')).to.be.true;
341
+ expect(el._inputNode.getAttribute('aria-valuemin')).to.equal('0');
334
342
  });
335
343
 
336
344
  it('updates aria-valuemax when stepper is changed', async () => {
337
345
  const el = await fixture(inputStepperWithAttrs);
338
346
  const incrementButton = el.querySelector('[slot=suffix]');
339
347
  incrementButton?.dispatchEvent(new Event('click'));
340
- expect(el).to.have.attribute('aria-valuemax', '200');
348
+ expect(el._inputNode.hasAttribute('aria-valuemax')).to.be.true;
349
+ expect(el._inputNode.getAttribute('aria-valuemax')).to.equal('200');
341
350
 
342
351
  el.max = 1000;
343
352
  await el.updateComplete;
344
- expect(el).to.have.attribute('aria-valuemax', '1000');
353
+ expect(el._inputNode.hasAttribute('aria-valuemax')).to.be.true;
354
+ expect(el._inputNode.getAttribute('aria-valuemax')).to.equal('1000');
355
+ });
356
+
357
+ it('when decrease button gets focus, it sets aria-live to input-stepper__value', async () => {
358
+ const el = await fixture(inputStepperWithAttrs);
359
+ const stepperValue = el.shadowRoot?.querySelector('.input-stepper__value');
360
+ const decrementButton = el.querySelector('[slot=prefix]');
361
+
362
+ decrementButton?.dispatchEvent(new Event('focus'));
363
+ expect(stepperValue?.hasAttribute('aria-live')).to.be.true;
364
+ expect(stepperValue?.getAttribute('aria-live')).to.equal('assertive');
365
+
366
+ decrementButton?.dispatchEvent(new Event('blur'));
367
+ expect(stepperValue?.hasAttribute('aria-live')).to.be.false;
368
+ });
369
+
370
+ it('when increase button gets focus, it sets aria-live to input-stepper__value', async () => {
371
+ const el = await fixture(inputStepperWithAttrs);
372
+ const stepperValue = el.shadowRoot?.querySelector('.input-stepper__value');
373
+ const incrementButton = el.querySelector('[slot=suffix]');
374
+
375
+ incrementButton?.dispatchEvent(new Event('focus'));
376
+ expect(stepperValue?.hasAttribute('aria-live')).to.be.true;
377
+ expect(stepperValue?.getAttribute('aria-live')).to.equal('assertive');
378
+
379
+ incrementButton?.dispatchEvent(new Event('blur'));
380
+ expect(stepperValue?.hasAttribute('aria-live')).to.be.false;
345
381
  });
346
382
  });
347
383
  });
@@ -158,11 +158,11 @@ export class LionInputTelDropdown extends LionInputTel {
158
158
  super.styles,
159
159
  css`
160
160
  /**
161
- * We need to align the height of the dropdown with the height of the text field.
162
- * We target the HTMLDivElement (render wrapper from SlotMixin) here. Its child,
163
- * [data-ref=dropdown], recieves a 100% height as well via inline styles (since we
164
- * can't target from shadow styles).
165
- */
161
+ * We need to align the height of the dropdown with the height of the text field.
162
+ * We target the HTMLDivElement (render wrapper from SlotMixin) here. Its child,
163
+ * [data-ref=dropdown], receives a 100% height as well via inline styles (since we
164
+ * can't target from shadow styles).
165
+ */
166
166
  ::slotted([slot='prefix']) {
167
167
  height: 100%;
168
168
  }
@@ -301,7 +301,8 @@ export class LionInputTelDropdown extends LionInputTel {
301
301
  } else {
302
302
  this.__initializedRegionCode = `+${countryCode}`;
303
303
  }
304
- this.modelValue = this.__initializedRegionCode;
304
+ // on init we set the value to the _inputNode and not the modelValue to prevent validation
305
+ this._inputNode.value = this.__initializedRegionCode;
305
306
  this._initialModelValue = this.__initializedRegionCode;
306
307
  this.initInteractionState();
307
308
  }
@@ -9,8 +9,10 @@ import { LionOption } from '@lion/ui/listbox.js';
9
9
  import { ref } from 'lit/directives/ref.js';
10
10
  import { html } from 'lit';
11
11
 
12
+ import { mockPhoneUtilManager, restorePhoneUtilManager } from '@lion/ui/input-tel-test-helpers.js';
12
13
  import { isActiveElement } from '../../core/test-helpers/isActiveElement.js';
13
14
  import { ScopedElementsMixin } from '../../core/src/ScopedElementsMixin.js';
15
+ import '@lion/ui/define/lion-input-tel-dropdown.js';
14
16
 
15
17
  /**
16
18
  * @typedef {import('../types/index.js').TemplateDataForDropdownInputTel} TemplateDataForDropdownInputTel
@@ -67,6 +69,18 @@ describe('WithFormControlInputTelDropdown', () => {
67
69
  // Runs it for LionSelectRich, which uses .modelValue/@model-value-changed instead of .value/@change
68
70
  runInputTelDropdownSuite({ klass: WithFormControlInputTelDropdown });
69
71
 
72
+ it("it doesn't set the country as modelValue, only as viewValue", async () => {
73
+ const el = /** @type {LionInputTelDropdown} */ (
74
+ await fixture(html`
75
+ <lion-input-tel-dropdown .allowedRegions="${['NL']}"></lion-input-tel-dropdown>
76
+ `)
77
+ );
78
+
79
+ // @ts-expect-error [allow-protected-in-tests]
80
+ expect(el._inputNode.value).to.equal('+31');
81
+ expect(el.modelValue).to.equal('');
82
+ });
83
+
70
84
  it('focuses the textbox right after selection if selected via opened dropdown if interaction-mode is mac', async () => {
71
85
  class InputTelDropdownMac extends LionInputTelDropdown {
72
86
  static templates = {
@@ -172,4 +186,40 @@ describe('WithFormControlInputTelDropdown', () => {
172
186
  expect(isActiveElement(el._inputNode)).to.be.false;
173
187
  }
174
188
  });
189
+
190
+ describe('defaultValidators', () => {
191
+ /** @type {(value:any) => void} */
192
+ let resolveLoaded;
193
+ beforeEach(() => {
194
+ ({ resolveLoaded } = mockPhoneUtilManager());
195
+ });
196
+
197
+ afterEach(() => {
198
+ restorePhoneUtilManager();
199
+ });
200
+
201
+ it('without interaction are not called', async () => {
202
+ const el = /** @type {LionInputTelDropdown} */ (
203
+ await fixture(html`
204
+ <lion-input-tel-dropdown .allowedRegions="${['NL']}"></lion-input-tel-dropdown>
205
+ `)
206
+ );
207
+ resolveLoaded(undefined);
208
+ await aTimeout(0);
209
+ expect(el.hasFeedbackFor).to.deep.equal([]);
210
+ });
211
+
212
+ it('with interaction are called', async () => {
213
+ const el = /** @type {LionInputTelDropdown} */ (
214
+ await fixture(html`
215
+ <lion-input-tel-dropdown .allowedRegions="${['NL']}"></lion-input-tel-dropdown>
216
+ `)
217
+ );
218
+ el.modelValue = '+31 6';
219
+
220
+ resolveLoaded(undefined);
221
+ await aTimeout(0);
222
+ expect(el.hasFeedbackFor).to.deep.equal(['error']);
223
+ });
224
+ });
175
225
  });
@@ -92050,26 +92050,6 @@
92050
92050
  "module": "components/form-core/src/LionField.js"
92051
92051
  }
92052
92052
  },
92053
- {
92054
- "kind": "method",
92055
- "name": "__reflectAriaAttrToSpinButton",
92056
- "parameters": [
92057
- {
92058
- "name": "attrName",
92059
- "type": {
92060
- "text": "string"
92061
- }
92062
- },
92063
- {
92064
- "name": "nodes",
92065
- "type": {
92066
- "text": "Element[]"
92067
- }
92068
- }
92069
- ],
92070
- "description": "Based on FormControlMixin __reflectAriaAttr()\n\nWill handle help text, validation feedback and character counter,\nprefix/suffix/before/after (if they contain data-description flag attr).\nAlso, contents of id references that will be put in the <lion-field>._ariaDescribedby property\nfrom an external context, will be read by a screen reader.",
92071
- "privacy": "private"
92072
- },
92073
92053
  {
92074
92054
  "kind": "method",
92075
92055
  "name": "__setDefaultValidators",
@@ -92218,9 +92198,44 @@
92218
92198
  },
92219
92199
  "privacy": "protected"
92220
92200
  },
92201
+ {
92202
+ "kind": "method",
92203
+ "name": "_inputGroupTemplate",
92204
+ "return": {
92205
+ "type": {
92206
+ "text": "TemplateResult"
92207
+ }
92208
+ },
92209
+ "privacy": "protected",
92210
+ "inheritedFrom": {
92211
+ "name": "LionField",
92212
+ "module": "components/form-core/src/LionField.js"
92213
+ }
92214
+ },
92215
+ {
92216
+ "kind": "method",
92217
+ "name": "_onEnterButton",
92218
+ "parameters": [
92219
+ {
92220
+ "name": "ev",
92221
+ "type": {
92222
+ "text": "Event"
92223
+ }
92224
+ }
92225
+ ],
92226
+ "privacy": "protected"
92227
+ },
92221
92228
  {
92222
92229
  "kind": "method",
92223
92230
  "name": "_onLeaveButton",
92231
+ "parameters": [
92232
+ {
92233
+ "name": "ev",
92234
+ "type": {
92235
+ "text": "Event"
92236
+ }
92237
+ }
92238
+ ],
92224
92239
  "description": "Redispatch leave event on host when catching leave event\non the incrementor and decrementor button.\n\nThis redispatched leave event will be caught by\nInteractionStateMixin to set \"touched\" state to true.\n\nInteracting with the buttons is \"user interactions\"\nthe same way as focusing + blurring the field (native input)",
92225
92240
  "privacy": "protected"
92226
92241
  },
@@ -92332,11 +92347,6 @@
92332
92347
  "default": "{ max: this.max, min: this.min, step: this.step, }",
92333
92348
  "privacy": "public"
92334
92349
  },
92335
- {
92336
- "kind": "field",
92337
- "name": "__boundOnLeaveButton",
92338
- "privacy": "protected"
92339
- },
92340
92350
  {
92341
92351
  "kind": "field",
92342
92352
  "name": "properties",
@@ -93170,20 +93180,6 @@
93170
93180
  "module": "components/form-core/src/LionField.js"
93171
93181
  }
93172
93182
  },
93173
- {
93174
- "kind": "method",
93175
- "name": "_inputGroupTemplate",
93176
- "return": {
93177
- "type": {
93178
- "text": "TemplateResult"
93179
- }
93180
- },
93181
- "privacy": "protected",
93182
- "inheritedFrom": {
93183
- "name": "LionField",
93184
- "module": "components/form-core/src/LionField.js"
93185
- }
93186
- },
93187
93183
  {
93188
93184
  "kind": "method",
93189
93185
  "name": "_inputGroupBeforeTemplate",
@@ -1 +1 @@
1
- {"version":3,"file":"LionCombobox.d.ts","sourceRoot":"","sources":["../../../../components/combobox/src/LionCombobox.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"LionCombobox.d.ts","sourceRoot":"","sources":["../../../../components/combobox/src/LionCombobox.js"],"names":[],"mappings":"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"}