@lion/ui 0.7.8 → 0.8.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 (95) hide show
  1. package/components/accordion/src/LionAccordion.js +20 -14
  2. package/components/accordion/test/lion-accordion.test.js +84 -28
  3. package/components/calendar/src/LionCalendar.js +3 -1
  4. package/components/combobox/test/lion-combobox.test.js +124 -120
  5. package/components/combobox/test/validators.test.js +2 -2
  6. package/components/combobox/test-helpers/combobox-helpers.js +8 -9
  7. package/components/core/src/browserDetection.js +9 -1
  8. package/components/form-core/test-suites/NativeTextFieldMixin.suite.js +9 -10
  9. package/components/validate-messages/translations/cs.js +4 -4
  10. package/components/validate-messages/translations/es.js +2 -2
  11. package/components/validate-messages/translations/hu.js +2 -2
  12. package/components/validate-messages/translations/it.js +2 -2
  13. package/components/validate-messages/translations/nl.js +2 -2
  14. package/components/validate-messages/translations/pl.js +2 -2
  15. package/components/validate-messages/translations/ru.js +2 -2
  16. package/components/validate-messages/translations/sk.js +2 -2
  17. package/components/validate-messages/translations/uk.js +2 -2
  18. package/custom-elements.json +735 -2528
  19. package/dist-types/components/accordion/src/LionAccordion.d.ts +11 -1
  20. package/dist-types/components/accordion/src/LionAccordion.d.ts.map +1 -1
  21. package/dist-types/components/accordion/test/lion-accordion.test.d.ts.map +1 -1
  22. package/dist-types/components/calendar/src/LionCalendar.d.ts +0 -1
  23. package/dist-types/components/calendar/src/LionCalendar.d.ts.map +1 -1
  24. package/dist-types/components/combobox/test-helpers/combobox-helpers.d.ts +2 -2
  25. package/dist-types/components/combobox/test-helpers/combobox-helpers.d.ts.map +1 -1
  26. package/dist-types/components/form-core/test-suites/NativeTextFieldMixin.suite.d.ts.map +1 -1
  27. package/dist-types/components/icon/src/LionIcon.d.ts +2 -2
  28. package/dist-types/components/icon/src/LionIcon.d.ts.map +1 -1
  29. package/dist-types/tsconfig.tsbuildinfo +1 -1
  30. package/docs/components/accordion/api-table.md +6 -4
  31. package/docs/components/accordion/use-cases.md +43 -4
  32. package/docs/components/checkbox-group/overview.md +2 -2
  33. package/docs/components/checkbox-group/use-cases.md +20 -59
  34. package/docs/components/collapsible/overview.md +1 -1
  35. package/docs/components/combobox/overview.md +1 -1
  36. package/docs/components/combobox/use-cases.md +3 -4
  37. package/docs/components/dialog/overview.md +1 -1
  38. package/docs/components/fieldset/overview.md +5 -5
  39. package/docs/components/fieldset/use-cases.md +9 -2
  40. package/docs/components/form/overview.md +3 -3
  41. package/docs/components/form/use-cases.md +2 -1
  42. package/docs/components/icon/use-cases.md +1 -1
  43. package/docs/components/input/overview.md +1 -1
  44. package/docs/components/input-amount/overview.md +3 -3
  45. package/docs/components/input-amount/use-cases.md +2 -2
  46. package/docs/components/input-date/overview.md +3 -3
  47. package/docs/components/input-date/use-cases.md +5 -4
  48. package/docs/components/input-datepicker/overview.md +5 -5
  49. package/docs/components/input-datepicker/use-cases.md +2 -3
  50. package/docs/components/input-email/overview.md +2 -2
  51. package/docs/components/input-file/overview.md +1 -1
  52. package/docs/components/input-iban/overview.md +2 -2
  53. package/docs/components/input-range/overview.md +2 -2
  54. package/docs/components/input-stepper/overview.md +1 -1
  55. package/docs/components/input-tel/overview.md +1 -1
  56. package/docs/components/input-tel/use-cases.md +6 -6
  57. package/docs/components/input-tel-dropdown/overview.md +1 -1
  58. package/docs/components/listbox/use-cases.md +1 -1
  59. package/docs/components/pagination/use-cases.md +3 -1
  60. package/docs/components/radio-group/overview.md +3 -3
  61. package/docs/components/select/use-cases.md +1 -1
  62. package/docs/components/select-rich/use-cases.md +1 -1
  63. package/docs/components/steps/overview.md +6 -2
  64. package/docs/components/steps/use-cases.md +9 -3
  65. package/docs/components/tabs/examples.md +1 -1
  66. package/docs/fundamentals/index.md +4 -4
  67. package/docs/fundamentals/node-tools/providence-analytics/LocalConfiguration.md +1 -1
  68. package/docs/fundamentals/node-tools/providence-analytics/QueryResult.md +1 -1
  69. package/docs/fundamentals/node-tools/providence-analytics/analyzer.md +1 -1
  70. package/docs/fundamentals/node-tools/providence-analytics/dashboard.md +1 -1
  71. package/docs/fundamentals/node-tools/providence-analytics/overview.md +3 -3
  72. package/docs/fundamentals/node-tools/publish-docs/overview.md +3 -3
  73. package/docs/fundamentals/node-tools/rocket-preset-extend-lion-docs/overview.md +2 -2
  74. package/docs/fundamentals/rationales/accessibility.md +1 -1
  75. package/docs/fundamentals/systems/core/SlotMixin.md +1 -1
  76. package/docs/fundamentals/systems/core/overview.md +1 -1
  77. package/docs/fundamentals/systems/form/formatting-and-parsing.md +4 -4
  78. package/docs/fundamentals/systems/form/model-value.md +1 -1
  79. package/docs/fundamentals/systems/form/overview.md +28 -28
  80. package/docs/fundamentals/systems/form/use-cases.md +2 -1
  81. package/docs/fundamentals/systems/form/validate.md +2 -2
  82. package/docs/fundamentals/systems/localize/overview.md +4 -4
  83. package/docs/fundamentals/systems/localize/use-cases.md +3 -1
  84. package/docs/fundamentals/systems/overlays/configuration.md +2 -2
  85. package/docs/fundamentals/systems/overlays/overview.md +5 -5
  86. package/docs/fundamentals/systems/overlays/use-cases.md +5 -3
  87. package/docs/fundamentals/tools/helpers/overview.md +1 -1
  88. package/docs/fundamentals/tools/singleton-manager/overview.md +4 -4
  89. package/docs/guides/how-to/create-a-custom-field.md +5 -5
  90. package/docs/guides/how-to/create-a-form.md +4 -4
  91. package/docs/guides/how-to/extend-a-native-input.md +2 -2
  92. package/docs/guides/index.md +8 -8
  93. package/docs/guides/principles/index.md +5 -5
  94. package/docs/guides/principles/styling.md +1 -1
  95. package/package.json +1 -1
@@ -25,15 +25,15 @@ export class LionAccordion extends LitElement {
25
25
  /**
26
26
  * index number of the focused accordion
27
27
  */
28
- focusedIndex: {
29
- type: Number,
30
- },
28
+ focusedIndex: { type: Number },
31
29
  /**
32
30
  * array of indices of the expanded accordions
33
31
  */
34
- expanded: {
35
- type: Array,
36
- },
32
+ expanded: { type: Array },
33
+ /**
34
+ * exclusive property allows only one accordion slot to be open at a time
35
+ */
36
+ exclusive: { type: Boolean },
37
37
  };
38
38
  }
39
39
 
@@ -101,6 +101,11 @@ export class LionAccordion extends LitElement {
101
101
  super();
102
102
  this.styles = {};
103
103
 
104
+ /**
105
+ * @type {boolean}
106
+ */
107
+ this.exclusive = false;
108
+
104
109
  /**
105
110
  * @type {StoreEntry[]}
106
111
  * @private
@@ -437,20 +442,21 @@ export class LionAccordion extends LitElement {
437
442
  }
438
443
 
439
444
  /**
440
- * @param {number} value
445
+ * @param {number} indexClicked
441
446
  * @private
442
447
  */
443
- __toggleExpanded(value) {
444
- const expanded = [...this.expanded];
445
- const index = expanded.indexOf(value);
448
+ __toggleExpanded(indexClicked) {
449
+ const indexFound = this.expanded.indexOf(indexClicked);
450
+ const expandedNewValues = this.exclusive ? [] : [...this.expanded];
446
451
 
447
- if (index === -1) {
448
- expanded.push(value);
452
+ if (indexFound === -1) {
453
+ expandedNewValues.push(indexClicked);
449
454
  } else {
450
- expanded.splice(index, 1);
455
+ expandedNewValues.splice(indexFound, 1);
451
456
  }
452
457
 
453
- this.expanded = expanded;
458
+ // trigger a render
459
+ this.expanded = expandedNewValues;
454
460
  }
455
461
 
456
462
  /**
@@ -1,5 +1,6 @@
1
1
  import { expect, fixture } from '@open-wc/testing';
2
2
  import { html } from 'lit/static-html.js';
3
+ import { sendKeys } from '@web/test-runner-commands';
3
4
  import sinon from 'sinon';
4
5
 
5
6
  import '@lion/ui/define/lion-accordion.js';
@@ -33,14 +34,14 @@ function getAccordionChildren(el) {
33
34
  }
34
35
 
35
36
  /**
36
- * @param {Element} el
37
+ * @param {LionAccordion} el
37
38
  */
38
39
  function getInvokers(el) {
39
40
  return getAccordionChildren(el).filter(child => child.classList.contains('invoker'));
40
41
  }
41
42
 
42
43
  /**
43
- * @param {Element} el
44
+ * @param {LionAccordion} el
44
45
  */
45
46
  function getContents(el) {
46
47
  return getAccordionChildren(el).filter(child => child.classList.contains('content'));
@@ -112,6 +113,51 @@ describe('<lion-accordion>', () => {
112
113
  expect(invokers[1].firstElementChild).to.have.attribute('expanded');
113
114
  });
114
115
 
116
+ it('supports [exclusive] attribute, allowing one collapsible to be open at a time', async () => {
117
+ const el = /** @type {LionAccordion} */ (
118
+ await fixture(html`
119
+ <lion-accordion exclusive>
120
+ <h2 slot="invoker"><button>invoker 1</button></h2>
121
+ <div slot="content">content 1</div>
122
+ <h2 slot="invoker"><button>invoker 2</button></h2>
123
+ <div slot="content">content 2</div>
124
+ <h2 slot="invoker"><button>invoker 3</button></h2>
125
+ <div slot="content">content 3</div>
126
+ </lion-accordion>
127
+ `)
128
+ );
129
+
130
+ const invokerButtons = Array.from(getInvokers(el)).map(
131
+ invokerHeadingEl => /** @type {HTMLButtonElement} */ (invokerHeadingEl.firstElementChild),
132
+ );
133
+
134
+ // We open the first... (nothing different from not [exclusive] so far)
135
+ invokerButtons[0].click();
136
+ expect(invokerButtons[0]).to.have.attribute('expanded');
137
+ expect(invokerButtons[1]).to.not.have.attribute('expanded');
138
+ expect(invokerButtons[2]).to.not.have.attribute('expanded');
139
+
140
+ // We click the second...
141
+ invokerButtons[1].click();
142
+ expect(invokerButtons[0]).to.not.have.attribute('expanded');
143
+ expect(invokerButtons[1]).to.have.attribute('expanded');
144
+ expect(invokerButtons[2]).to.not.have.attribute('expanded');
145
+
146
+ // We click the third...
147
+ invokerButtons[2].click();
148
+ expect(invokerButtons[0]).to.not.have.attribute('expanded');
149
+ expect(invokerButtons[1]).to.not.have.attribute('expanded');
150
+ expect(invokerButtons[2]).to.have.attribute('expanded');
151
+
152
+ el.exclusive = false;
153
+
154
+ // We open the first... (behaving as default (not [exclusive]) again)
155
+ invokerButtons[0].click();
156
+ expect(invokerButtons[0]).to.have.attribute('expanded');
157
+ expect(invokerButtons[1]).to.not.have.attribute('expanded');
158
+ expect(invokerButtons[2]).to.have.attribute('expanded');
159
+ });
160
+
115
161
  it('sends event "expanded-changed" for every expanded state change', async () => {
116
162
  const el = /** @type {LionAccordion} */ (await fixture(basicAccordion));
117
163
  const spy = sinon.spy();
@@ -264,11 +310,14 @@ describe('<lion-accordion>', () => {
264
310
  * > content content to be preloaded.
265
311
  */
266
312
  describe('User interaction', () => {
267
- it('opens a invoker on click', async () => {
313
+ it('opens/closes an invoker on click', async () => {
268
314
  const el = /** @type {LionAccordion} */ (await fixture(basicAccordion));
269
315
  const invokers = getInvokers(el);
270
316
  invokers[1].firstElementChild?.dispatchEvent(new Event('click'));
271
317
  expect(el.expanded).to.deep.equal([1]);
318
+
319
+ invokers[1].firstElementChild?.dispatchEvent(new Event('click'));
320
+ expect(el.expanded).to.deep.equal([]);
272
321
  });
273
322
 
274
323
  it('selects a invoker on click', async () => {
@@ -278,12 +327,13 @@ describe('<lion-accordion>', () => {
278
327
  expect(el.focusedIndex).to.equal(1);
279
328
  });
280
329
 
281
- it.skip('opens/close invoker on [enter] and [space]', async () => {
330
+ it('opens/closes invoker on [enter] and [space]', async () => {
282
331
  const el = /** @type {LionAccordion} */ (await fixture(basicAccordion));
283
332
  const invokers = getInvokers(el);
284
- invokers[0].firstElementChild?.dispatchEvent(new KeyboardEvent('keyup', { key: 'Enter' }));
333
+ invokers[0].getElementsByTagName('button')[0].focus();
334
+ await sendKeys({ press: 'Enter' });
285
335
  expect(el.expanded).to.deep.equal([0]);
286
- invokers[0].firstElementChild?.dispatchEvent(new KeyboardEvent('keyup', { key: ' ' }));
336
+ await sendKeys({ press: 'Space' });
287
337
  expect(el.expanded).to.deep.equal([]);
288
338
  });
289
339
 
@@ -467,14 +517,16 @@ describe('<lion-accordion>', () => {
467
517
 
468
518
  describe('Invokers', () => {
469
519
  it('links ids of content items to invoker first child via [aria-controls]', async () => {
470
- const el = await fixture(html`
471
- <lion-accordion>
472
- <h2 id="h1" slot="invoker"><button>invoker 1</button></h2>
473
- <div id="p1" slot="content">content 1</div>
474
- <h2 id="h2" slot="invoker"><button>invoker 2</button></h2>
475
- <div id="p2" slot="content">content 2</div>
476
- </lion-accordion>
477
- `);
520
+ const el = /** @type {LionAccordion} */ (
521
+ await fixture(html`
522
+ <lion-accordion>
523
+ <h2 id="h1" slot="invoker"><button>invoker 1</button></h2>
524
+ <div id="p1" slot="content">content 1</div>
525
+ <h2 id="h2" slot="invoker"><button>invoker 2</button></h2>
526
+ <div id="p2" slot="content">content 2</div>
527
+ </lion-accordion>
528
+ `)
529
+ );
478
530
  const invokers = getInvokers(el);
479
531
  const contents = getContents(el);
480
532
  expect(invokers[0].firstElementChild?.getAttribute('aria-controls')).to.equal(
@@ -486,12 +538,14 @@ describe('<lion-accordion>', () => {
486
538
  });
487
539
 
488
540
  it('adds aria-expanded="false" to invoker when its content is not expanded', async () => {
489
- const el = await fixture(html`
490
- <lion-accordion>
491
- <h2 slot="invoker"><button>invoker</button></h2>
492
- <div slot="content">content</div>
493
- </lion-accordion>
494
- `);
541
+ const el = /** @type {LionAccordion} */ (
542
+ await fixture(html`
543
+ <lion-accordion>
544
+ <h2 slot="invoker"><button>invoker</button></h2>
545
+ <div slot="content">content</div>
546
+ </lion-accordion>
547
+ `)
548
+ );
495
549
  expect(Array.from(getInvokers(el))[0]?.firstElementChild).to.have.attribute(
496
550
  'aria-expanded',
497
551
  'false',
@@ -517,14 +571,16 @@ describe('<lion-accordion>', () => {
517
571
 
518
572
  describe('Contents', () => {
519
573
  it('adds aria-labelledby referring to invoker ids', async () => {
520
- const el = await fixture(html`
521
- <lion-accordion>
522
- <h2 slot="invoker"><button>invoker 1</button></h2>
523
- <div slot="content">content 1</div>
524
- <h2 slot="invoker"><button>invoker 2</button></h2>
525
- <div slot="content">content 2</div>
526
- </lion-accordion>
527
- `);
574
+ const el = /** @type {LionAccordion} */ (
575
+ await fixture(html`
576
+ <lion-accordion>
577
+ <h2 slot="invoker"><button>invoker 1</button></h2>
578
+ <div slot="content">content 1</div>
579
+ <h2 slot="invoker"><button>invoker 2</button></h2>
580
+ <div slot="content">content 2</div>
581
+ </lion-accordion>
582
+ `)
583
+ );
528
584
  const contents = getContents(el);
529
585
  const invokers = getInvokers(el);
530
586
  expect(contents[0]).to.have.attribute('aria-labelledby', invokers[0].firstElementChild?.id);
@@ -300,7 +300,9 @@ export class LionCalendar extends LocalizeMixin(LitElement) {
300
300
  }
301
301
  }
302
302
 
303
- firstUpdated() {
303
+ /** @param {import('lit').PropertyValues } changedProperties */
304
+ firstUpdated(changedProperties) {
305
+ super.firstUpdated(changedProperties);
304
306
  this.__calculateInitialCentralDate();
305
307
 
306
308
  // setup data for initial render