@lion/ui 0.3.3 → 0.3.4

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 (82) hide show
  1. package/components/calendar/src/LionCalendar.js +121 -65
  2. package/components/calendar/src/calendarStyle.js +25 -1
  3. package/components/calendar/src/utils/createDay.js +2 -0
  4. package/components/calendar/src/utils/dayTemplate.js +19 -32
  5. package/components/calendar/src/utils/getDayMonthYear.js +28 -0
  6. package/components/calendar/test/lion-calendar.test.js +118 -108
  7. package/components/calendar/test/utils/dayTemplate.test.js +8 -4
  8. package/components/calendar/test/utils/snapshots/monthTemplate_en-GB_Sunday_2018-12.js +210 -126
  9. package/components/calendar/test-helpers/DayObject.js +2 -2
  10. package/components/calendar/types/day.ts +1 -0
  11. package/components/input-datepicker/src/LionInputDatepicker.js +34 -2
  12. package/components/input-file/src/LionInputFile.js +5 -7
  13. package/components/input-file/test/lion-input-file.test.js +4 -0
  14. package/custom-elements.json +323 -31
  15. package/dist-types/components/calendar/src/LionCalendar.d.ts +22 -15
  16. package/dist-types/components/calendar/src/LionCalendar.d.ts.map +1 -1
  17. package/dist-types/components/calendar/src/calendarStyle.d.ts.map +1 -1
  18. package/dist-types/components/calendar/src/utils/createDay.d.ts +2 -1
  19. package/dist-types/components/calendar/src/utils/createDay.d.ts.map +1 -1
  20. package/dist-types/components/calendar/src/utils/dayTemplate.d.ts.map +1 -1
  21. package/dist-types/components/calendar/src/utils/getDayMonthYear.d.ts +13 -0
  22. package/dist-types/components/calendar/src/utils/getDayMonthYear.d.ts.map +1 -0
  23. package/dist-types/components/calendar/types/day.d.ts +1 -0
  24. package/dist-types/components/calendar/types/day.d.ts.map +1 -1
  25. package/dist-types/components/input-datepicker/src/LionInputDatepicker.d.ts +6 -0
  26. package/dist-types/components/input-datepicker/src/LionInputDatepicker.d.ts.map +1 -1
  27. package/dist-types/components/input-file/src/LionInputFile.d.ts +6 -0
  28. package/dist-types/components/input-file/src/LionInputFile.d.ts.map +1 -1
  29. package/dist-types/tsconfig.tsbuildinfo +1 -1
  30. package/docs/components/calendar/use-cases.md +39 -0
  31. package/docs/components/checkbox-group/overview.md +2 -2
  32. package/docs/components/collapsible/overview.md +1 -1
  33. package/docs/components/combobox/overview.md +1 -1
  34. package/docs/components/combobox/use-cases.md +1 -1
  35. package/docs/components/dialog/overview.md +1 -1
  36. package/docs/components/fieldset/overview.md +5 -5
  37. package/docs/components/form/overview.md +3 -3
  38. package/docs/components/icon/use-cases.md +1 -1
  39. package/docs/components/input/overview.md +1 -1
  40. package/docs/components/input-amount/overview.md +3 -3
  41. package/docs/components/input-date/overview.md +3 -3
  42. package/docs/components/input-datepicker/overview.md +5 -5
  43. package/docs/components/input-datepicker/use-cases.md +2 -0
  44. package/docs/components/input-email/overview.md +2 -2
  45. package/docs/components/input-file/overview.md +1 -1
  46. package/docs/components/input-iban/overview.md +2 -2
  47. package/docs/components/input-range/overview.md +2 -2
  48. package/docs/components/input-stepper/overview.md +1 -1
  49. package/docs/components/input-tel/overview.md +1 -1
  50. package/docs/components/input-tel/use-cases.md +6 -6
  51. package/docs/components/input-tel-dropdown/overview.md +1 -1
  52. package/docs/components/radio-group/overview.md +3 -3
  53. package/docs/components/select-rich/use-cases.md +1 -1
  54. package/docs/components/tabs/examples.md +1 -1
  55. package/docs/fundamentals/index.md +4 -4
  56. package/docs/fundamentals/node-tools/providence-analytics/LocalConfiguration.md +1 -1
  57. package/docs/fundamentals/node-tools/providence-analytics/QueryResult.md +1 -1
  58. package/docs/fundamentals/node-tools/providence-analytics/analyzer.md +1 -1
  59. package/docs/fundamentals/node-tools/providence-analytics/dashboard.md +1 -1
  60. package/docs/fundamentals/node-tools/providence-analytics/overview.md +3 -3
  61. package/docs/fundamentals/node-tools/publish-docs/overview.md +3 -3
  62. package/docs/fundamentals/node-tools/rocket-preset-extend-lion-docs/overview.md +2 -2
  63. package/docs/fundamentals/rationales/accessibility.md +1 -1
  64. package/docs/fundamentals/systems/core/SlotMixin.md +1 -1
  65. package/docs/fundamentals/systems/core/overview.md +1 -1
  66. package/docs/fundamentals/systems/form/formatting-and-parsing.md +4 -4
  67. package/docs/fundamentals/systems/form/model-value.md +1 -1
  68. package/docs/fundamentals/systems/form/overview.md +28 -28
  69. package/docs/fundamentals/systems/form/validate.md +1 -1
  70. package/docs/fundamentals/systems/localize/overview.md +4 -4
  71. package/docs/fundamentals/systems/overlays/configuration.md +2 -2
  72. package/docs/fundamentals/systems/overlays/overview.md +5 -5
  73. package/docs/fundamentals/systems/overlays/use-cases.md +2 -2
  74. package/docs/fundamentals/tools/helpers/overview.md +1 -1
  75. package/docs/fundamentals/tools/singleton-manager/overview.md +4 -4
  76. package/docs/guides/how-to/create-a-custom-field.md +5 -5
  77. package/docs/guides/how-to/create-a-form.md +4 -4
  78. package/docs/guides/how-to/extend-a-native-input.md +2 -2
  79. package/docs/guides/index.md +8 -8
  80. package/docs/guides/principles/index.md +5 -5
  81. package/docs/guides/principles/styling.md +1 -1
  82. package/package.json +1 -1
@@ -396,7 +396,7 @@ describe('<lion-calendar>', () => {
396
396
  clock.restore();
397
397
  });
398
398
 
399
- it('should set centralDate to the unique valid value when minDate and maxDate are equal', async () => {
399
+ it('requires the user to set an appropriate centralDate even when minDate and maxDate are equal', async () => {
400
400
  const clock = sinon.useFakeTimers({ now: new Date('2019/06/03').getTime() });
401
401
 
402
402
  const el = await fixture(html`
@@ -405,9 +405,18 @@ describe('<lion-calendar>', () => {
405
405
  .maxDate="${new Date('2019/07/03')}"
406
406
  ></lion-calendar>
407
407
  `);
408
- expect(isSameDate(el.centralDate, new Date('2019/07/03')), 'central date').to.be.true;
408
+ const elSetting = await fixture(html`
409
+ <lion-calendar
410
+ .centralDate="${new Date('2019/07/03')}"
411
+ .minDate="${new Date('2019/07/03')}"
412
+ .maxDate="${new Date('2019/07/03')}"
413
+ ></lion-calendar>
414
+ `);
409
415
 
410
416
  clock.restore();
417
+ expect(isSameDate(el.centralDate, new Date('2019/06/03')), 'central date').to.be.true;
418
+ expect(isSameDate(elSetting.centralDate, new Date('2019/07/03')), 'central date').to.be
419
+ .true;
411
420
  });
412
421
 
413
422
  describe('Normalization', () => {
@@ -482,6 +491,98 @@ describe('<lion-calendar>', () => {
482
491
  });
483
492
 
484
493
  describe('Navigation', () => {
494
+ describe('finding enabled dates', () => {
495
+ it('has helper for `findNextEnabledDate()`, `findPreviousEnabledDate()`, `findNearestEnabledDate()`', async () => {
496
+ const el = await fixture(html`
497
+ <lion-calendar
498
+ .selectedDate="${new Date('2001/01/02')}"
499
+ .disableDates=${
500
+ /** @param {Date} date */ date => date.getDate() === 3 || date.getDate() === 4
501
+ }
502
+ ></lion-calendar>
503
+ `);
504
+ const elObj = new CalendarObject(el);
505
+
506
+ el.focusDate(el.findNextEnabledDate());
507
+ await el.updateComplete;
508
+ expect(elObj.focusedDayObj?.monthday).to.equal(5);
509
+
510
+ el.focusDate(el.findPreviousEnabledDate());
511
+ await el.updateComplete;
512
+ expect(elObj.focusedDayObj?.monthday).to.equal(2);
513
+
514
+ el.focusDate(el.findNearestEnabledDate());
515
+ await el.updateComplete;
516
+ expect(elObj.focusedDayObj?.monthday).to.equal(1);
517
+ });
518
+
519
+ it('future dates take precedence over past dates when "distance" between dates is equal', async () => {
520
+ const clock = sinon.useFakeTimers({ now: new Date('2000/12/15').getTime() });
521
+
522
+ const el = await fixture(html`
523
+ <lion-calendar
524
+ .disableDates="${/** @param {Date} d */ d => d.getDate() === 15}"
525
+ ></lion-calendar>
526
+ `);
527
+ el.focusDate(el.findNearestEnabledDate());
528
+ await el.updateComplete;
529
+
530
+ const elObj = new CalendarObject(el);
531
+ expect(elObj.centralDayObj?.monthday).to.equal(16);
532
+
533
+ clock.restore();
534
+ });
535
+
536
+ it('will search 750 days in the past', async () => {
537
+ const clock = sinon.useFakeTimers({ now: new Date('2000/12/15').getTime() });
538
+
539
+ const el = await fixture(html`
540
+ <lion-calendar
541
+ .disableDates="${/** @param {Date} d */ d => d.getFullYear() > 1998}"
542
+ ></lion-calendar>
543
+ `);
544
+ el.focusDate(el.findNearestEnabledDate());
545
+ await el.updateComplete;
546
+
547
+ expect(el.centralDate.getFullYear()).to.equal(1998);
548
+ expect(el.centralDate.getMonth()).to.equal(11);
549
+ expect(el.centralDate.getDate()).to.equal(31);
550
+
551
+ clock.restore();
552
+ });
553
+
554
+ it('will search 750 days in the future', async () => {
555
+ const clock = sinon.useFakeTimers({ now: new Date('2000/12/15').getTime() });
556
+
557
+ const el = await fixture(html`
558
+ <lion-calendar
559
+ .disableDates="${/** @param {Date} d */ d => d.getFullYear() < 2002}"
560
+ ></lion-calendar>
561
+ `);
562
+
563
+ el.focusDate(el.findNearestEnabledDate());
564
+ await el.updateComplete;
565
+
566
+ expect(el.centralDate.getFullYear()).to.equal(2002);
567
+ expect(el.centralDate.getMonth()).to.equal(0);
568
+ expect(el.centralDate.getDate()).to.equal(1);
569
+
570
+ clock.restore();
571
+ });
572
+
573
+ it('throws if no available date can be found within +/- 750 days', async () => {
574
+ const el = await fixture(html`
575
+ <lion-calendar
576
+ .disableDates="${/** @param {Date} d */ d => d.getFullYear() < 2002}"
577
+ ></lion-calendar>
578
+ `);
579
+
580
+ expect(() => {
581
+ el.findNextEnabledDate(new Date('1900/01/01'));
582
+ }).to.throw(Error, 'Could not find a selectable date within +/- 750 day for 1900/1/1');
583
+ });
584
+ });
585
+
485
586
  describe('Year', () => {
486
587
  it('has a button for navigation to previous year', async () => {
487
588
  const el = await fixture(
@@ -655,7 +756,7 @@ describe('<lion-calendar>', () => {
655
756
  await el.updateComplete;
656
757
  expect(elObj.activeMonth).to.equal('November');
657
758
  expect(elObj.activeYear).to.equal('2000');
658
- expect(isSameDate(el.centralDate, new Date('2000/11/20'))).to.be.true;
759
+ expect(isSameDate(el.centralDate, new Date('2000/11/15'))).to.be.true;
659
760
 
660
761
  clock.restore();
661
762
  });
@@ -677,7 +778,7 @@ describe('<lion-calendar>', () => {
677
778
  await el.updateComplete;
678
779
  expect(elObj.activeMonth).to.equal('January');
679
780
  expect(elObj.activeYear).to.equal('2001');
680
- expect(isSameDate(el.centralDate, new Date('2001/01/10'))).to.be.true;
781
+ expect(isSameDate(el.centralDate, new Date('2001/01/15'))).to.be.true;
681
782
 
682
783
  clock.restore();
683
784
  });
@@ -696,17 +797,21 @@ describe('<lion-calendar>', () => {
696
797
  expect(remote.activeMonth).to.equal('September');
697
798
  expect(remote.activeYear).to.equal('2019');
698
799
  expect(remote.centralDayObj?.el).dom.to.equal(`
699
- <button
800
+ <div
700
801
  class="calendar__day-button"
802
+ aria-disabled="false"
803
+ role="button"
701
804
  tabindex="0"
702
- aria-label="30 September 2019 Monday"
703
805
  aria-pressed="false"
704
806
  past=""
705
807
  current-month="">
706
808
  <span class="calendar__day-button__text">
707
809
  30
708
810
  </span>
709
- </button>
811
+ <span class="u-sr-only">
812
+ September 2019 Monday
813
+ </span>
814
+ </div>
710
815
  `);
711
816
  });
712
817
  });
@@ -801,7 +906,7 @@ describe('<lion-calendar>', () => {
801
906
  ).to.equal(true);
802
907
  });
803
908
 
804
- it('adds "disabled" attribute to disabled dates', async () => {
909
+ it('adds aria-disabled="true" attribute to disabled dates', async () => {
805
910
  const clock = sinon.useFakeTimers({ now: new Date('2000/12/15').getTime() });
806
911
 
807
912
  const el = await fixture(html`
@@ -815,7 +920,7 @@ describe('<lion-calendar>', () => {
815
920
  const elObj = new CalendarObject(el);
816
921
  expect(
817
922
  elObj.checkForAllDayObjs(
818
- /** @param {DayObject} d */ d => d.el.hasAttribute('disabled'),
923
+ /** @param {DayObject} d */ d => d.el.getAttribute('aria-disabled') === 'true',
819
924
  [1, 2, 30, 31],
820
925
  ),
821
926
  ).to.equal(true);
@@ -972,7 +1077,7 @@ describe('<lion-calendar>', () => {
972
1077
  expect(elObj.focusedDayObj?.monthday).to.equal(12 + 1);
973
1078
  });
974
1079
 
975
- it('navigates (sets focus) to next selectable column item via [arrow right] key', async () => {
1080
+ it('navigates (sets focus) to next column item via [arrow right] key', async () => {
976
1081
  const el = await fixture(html`
977
1082
  <lion-calendar
978
1083
  .selectedDate="${new Date('2001/01/02')}"
@@ -987,7 +1092,7 @@ describe('<lion-calendar>', () => {
987
1092
  new KeyboardEvent('keydown', { key: 'ArrowRight' }),
988
1093
  );
989
1094
  await el.updateComplete;
990
- expect(elObj.focusedDayObj?.monthday).to.equal(5);
1095
+ expect(elObj.focusedDayObj?.monthday).to.equal(3);
991
1096
  });
992
1097
 
993
1098
  it('navigates (sets focus) to next row via [arrow right] key if last item in row', async () => {
@@ -1108,77 +1213,6 @@ describe('<lion-calendar>', () => {
1108
1213
 
1109
1214
  clock.restore();
1110
1215
  });
1111
-
1112
- it('is on day closest to today, if today (and surrounding dates) is/are disabled', async () => {
1113
- const el = await fixture(html`
1114
- <lion-calendar
1115
- .centralDate="${new Date('2000/12/15')}"
1116
- .disableDates="${/** @param {Date} d */ d => d.getDate() <= 16}"
1117
- ></lion-calendar>
1118
- `);
1119
- const elObj = new CalendarObject(el);
1120
- expect(elObj.centralDayObj?.monthday).to.equal(17);
1121
-
1122
- el.disableDates = d => d.getDate() >= 12;
1123
- await el.updateComplete;
1124
- expect(elObj.centralDayObj?.monthday).to.equal(11);
1125
- });
1126
-
1127
- it('future dates take precedence over past dates when "distance" between dates is equal', async () => {
1128
- const clock = sinon.useFakeTimers({ now: new Date('2000/12/15').getTime() });
1129
-
1130
- const el = await fixture(html`
1131
- <lion-calendar
1132
- .disableDates="${/** @param {Date} d */ d => d.getDate() === 15}"
1133
- ></lion-calendar>
1134
- `);
1135
- const elObj = new CalendarObject(el);
1136
- expect(elObj.centralDayObj?.monthday).to.equal(16);
1137
-
1138
- clock.restore();
1139
- });
1140
-
1141
- it('will search 750 days in the past', async () => {
1142
- const clock = sinon.useFakeTimers({ now: new Date('2000/12/15').getTime() });
1143
-
1144
- const el = await fixture(html`
1145
- <lion-calendar
1146
- .disableDates="${/** @param {Date} d */ d => d.getFullYear() > 1998}"
1147
- ></lion-calendar>
1148
- `);
1149
- expect(el.centralDate.getFullYear()).to.equal(1998);
1150
- expect(el.centralDate.getMonth()).to.equal(11);
1151
- expect(el.centralDate.getDate()).to.equal(31);
1152
-
1153
- clock.restore();
1154
- });
1155
-
1156
- it('will search 750 days in the future', async () => {
1157
- const clock = sinon.useFakeTimers({ now: new Date('2000/12/15').getTime() });
1158
-
1159
- const el = await fixture(html`
1160
- <lion-calendar
1161
- .disableDates="${/** @param {Date} d */ d => d.getFullYear() < 2002}"
1162
- ></lion-calendar>
1163
- `);
1164
- expect(el.centralDate.getFullYear()).to.equal(2002);
1165
- expect(el.centralDate.getMonth()).to.equal(0);
1166
- expect(el.centralDate.getDate()).to.equal(1);
1167
-
1168
- clock.restore();
1169
- });
1170
-
1171
- it('throws if no available date can be found within +/- 750 days', async () => {
1172
- const el = await fixture(html`
1173
- <lion-calendar
1174
- .disableDates="${/** @param {Date} d */ d => d.getFullYear() < 2002}"
1175
- ></lion-calendar>
1176
- `);
1177
-
1178
- expect(() => {
1179
- el.centralDate = new Date('1900/01/01');
1180
- }).to.throw(Error, 'Could not find a selectable date within +/- 750 day for 1900/1/1');
1181
- });
1182
1216
  });
1183
1217
 
1184
1218
  /**
@@ -1226,7 +1260,8 @@ describe('<lion-calendar>', () => {
1226
1260
 
1227
1261
  it('renders each day as a button inside a table cell', async () => {
1228
1262
  const elObj = new CalendarObject(await fixture(html`<lion-calendar></lion-calendar>`));
1229
- const hasBtn = /** @param {DayObject} d */ d => d.el.tagName === 'BUTTON';
1263
+ const hasBtn = /** @param {DayObject} d */ d =>
1264
+ d.el.tagName === 'DIV' && d.el.getAttribute('role') === 'button';
1230
1265
  expect(elObj.checkForAllDayObjs(hasBtn)).to.equal(true);
1231
1266
  });
1232
1267
 
@@ -1301,31 +1336,6 @@ describe('<lion-calendar>', () => {
1301
1336
  expect(elObj.checkForAllDayObjs(hasAriaPressed, [12])).to.equal(true);
1302
1337
  });
1303
1338
 
1304
- // This implementation mentions "button" inbetween and doesn't mention table
1305
- // column and row. As an alternative, see Deque implementation below.
1306
- // it(`on focus on a day, the screen reader pronounces "day of the week", "day number"
1307
- // and "month" (in this order)', async () => {
1308
- // // implemented by labelelledby referencing row and column names
1309
- // const el = await fixture('<lion-calendar></lion-calendar>');
1310
- // });
1311
-
1312
- // Alternative: Deque implementation
1313
- it(`sets aria-label on button, that consists of
1314
- "{day number} {month name} {year} {weekday name}"`, async () => {
1315
- const elObj = new CalendarObject(
1316
- await fixture(html`
1317
- <lion-calendar .centralDate="${new Date('2000/11/12')}"></lion-calendar>
1318
- `),
1319
- );
1320
- expect(
1321
- elObj.checkForAllDayObjs(
1322
- /** @param {DayObject} d */ d =>
1323
- d.buttonEl.getAttribute('aria-label') ===
1324
- `${d.monthday} November 2000 ${d.weekdayNameLong}`,
1325
- ),
1326
- ).to.equal(true);
1327
- });
1328
-
1329
1339
  /**
1330
1340
  * Not in scope:
1331
1341
  * - reads the new focused day on month navigation"
@@ -11,14 +11,18 @@ describe('dayTemplate', () => {
11
11
  const el = await fixture(dayTemplate(day, { weekdays }));
12
12
  expect(el).dom.to.equal(`
13
13
  <td role="gridcell" class="calendar__day-cell">
14
- <button
15
- class="calendar__day-button"
16
- aria-label="19 April 2019 Friday"
14
+ <div
15
+ aria-disabled="false"
17
16
  aria-pressed="false"
17
+ role="button"
18
+ class="calendar__day-button"
18
19
  tabindex="-1"
19
20
  >
20
21
  <span class="calendar__day-button__text">19</span>
21
- </button>
22
+ <span class="u-sr-only">
23
+ April 2019 Friday
24
+ </span>
25
+ </div>
22
26
  </td>
23
27
  `);
24
28
  });