@brightspace-ui/core 3.44.2 → 3.45.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -40,11 +40,26 @@ function getCalendarData() {
40
40
  return calendarData;
41
41
  }
42
42
 
43
+ function getInitialFocusDate(selectedValue, minValue, maxValue) {
44
+ if (selectedValue) return getDateFromISODate(selectedValue);
45
+ else return getDateFromISODate(getClosestValidDate(minValue, maxValue, false));
46
+ }
47
+
43
48
  export function checkIfDatesEqual(date1, date2) {
44
49
  if (!date1 || !date2) return false;
45
50
  return date1.getTime() === date2.getTime();
46
51
  }
47
52
 
53
+ export function getMinMaxDatesInView(selectedValue, minValue, maxValue) {
54
+ getCalendarData();
55
+ const date = getInitialFocusDate(selectedValue, minValue, maxValue);
56
+ const dates = getDatesInMonthArray(date.getMonth(), date.getFullYear());
57
+ return {
58
+ maxValue: dates[dates.length - 1][6],
59
+ minValue: dates[0][0]
60
+ };
61
+ }
62
+
48
63
  export function getDatesInMonthArray(shownMonth, shownYear) {
49
64
  const dates = [];
50
65
  const numDays = getNumberOfDaysInMonth(shownMonth, shownYear);
@@ -135,6 +150,11 @@ class Calendar extends LocalizeCoreElement(RtlMixin(LitElement)) {
135
150
 
136
151
  static get properties() {
137
152
  return {
153
+ /**
154
+ * Additional info for each day (ex. events on [{"date": "2024-09-19"}])
155
+ * @type {Array}
156
+ */
157
+ dayInfos: { type: Array, attribute: 'day-infos' },
138
158
  /**
139
159
  * Unique label text for calendar (necessary if multiple calendars on page)
140
160
  * @type {string}
@@ -145,19 +165,16 @@ class Calendar extends LocalizeCoreElement(RtlMixin(LitElement)) {
145
165
  * @type {string}
146
166
  */
147
167
  maxValue: { attribute: 'max-value', reflect: true, type: String },
148
-
149
168
  /**
150
169
  * Minimum valid date that could be selected by a user
151
170
  * @type {string}
152
171
  */
153
172
  minValue: { attribute: 'min-value', reflect: true, type: String },
154
-
155
173
  /**
156
174
  * Currently selected date
157
175
  * @type {string}
158
176
  */
159
177
  selectedValue: { type: String, attribute: 'selected-value' },
160
-
161
178
  /**
162
179
  * ACCESSIBILITY: Summary of the calendar used by screen reader users for identifying the calendar and/or summarizing its purpose
163
180
  * @type {string}
@@ -395,6 +412,24 @@ class Calendar extends LocalizeCoreElement(RtlMixin(LitElement)) {
395
412
  font-size: 1rem;
396
413
  font-weight: 700;
397
414
  }
415
+
416
+ .d2l-calendar-date-day-info::after {
417
+ background-color: var(--d2l-color-celestine);
418
+ border-radius: 3px;
419
+ bottom: 4px;
420
+ content: "";
421
+ display: inline-block;
422
+ height: 6px;
423
+ position: absolute;
424
+ width: 6px;
425
+ }
426
+ .d2l-calendar-date-selected.d2l-calendar-date-day-info::after {
427
+ bottom: 2px;
428
+ }
429
+ td:focus .d2l-calendar-date-day-info::after {
430
+ bottom: 0;
431
+ }
432
+
398
433
  `];
399
434
  }
400
435
 
@@ -435,9 +470,7 @@ class Calendar extends LocalizeCoreElement(RtlMixin(LitElement)) {
435
470
  }
436
471
 
437
472
  render() {
438
- if (this._shownMonth === undefined || !this._shownYear) {
439
- return nothing;
440
- }
473
+ if (this._shownMonth === undefined || !this._shownYear) return nothing;
441
474
 
442
475
  const weekdayHeaders = calendarData.daysOfWeekIndex.map((index) => html`
443
476
  <th>
@@ -450,20 +483,28 @@ class Calendar extends LocalizeCoreElement(RtlMixin(LitElement)) {
450
483
  const dates = getDatesInMonthArray(this._shownMonth, this._shownYear);
451
484
  const dayRows = dates.map((week) => {
452
485
  const weekHtml = week.map((day, index) => {
486
+
453
487
  const disabled = !isDateInRange(day, getDateFromISODate(this.minValue), getDateFromISODate(this.maxValue));
454
488
  const focused = checkIfDatesEqual(day, this._focusDate);
455
489
  const selected = this.selectedValue ? checkIfDatesEqual(day, getDateFromISODate(this.selectedValue)) : false;
490
+
491
+ const year = day.getFullYear();
492
+ const month = day.getMonth();
493
+ const date = day.getDate();
494
+
495
+ const hasDayInfo = !!this.dayInfos?.find(dayInfo => checkIfDatesEqual(day, getDateFromISODate(dayInfo.date)));
496
+
456
497
  const classes = {
457
498
  'd2l-calendar-date': true,
499
+ 'd2l-calendar-date-day-info': hasDayInfo,
458
500
  'd2l-calendar-date-initial': this._isInitialFocusDate,
459
501
  'd2l-calendar-date-selected': selected,
460
502
  'd2l-calendar-date-today': checkIfDatesEqual(day, this._today)
461
503
  };
462
- const year = day.getFullYear();
463
- const month = day.getMonth();
464
- const date = day.getDate();
504
+
465
505
  const weekday = calendarData.descriptor.calendar.days.long[calendarData.daysOfWeekIndex[index]];
466
- const description = `${weekday} ${date} ${formatDate(day, { format: 'monthYear' })}`;
506
+ const dayInfoText = hasDayInfo ? `${this.localize('components.calendar.hasEvents')} ` : '';
507
+ const description = `${dayInfoText}${weekday} ${date} ${formatDate(day, { format: 'monthYear' })}`;
467
508
  return html`
468
509
  <td
469
510
  aria-selected="${selected ? 'true' : 'false'}"
@@ -487,6 +528,7 @@ class Calendar extends LocalizeCoreElement(RtlMixin(LitElement)) {
487
528
 
488
529
  return html`<tr>${weekHtml}</tr>`;
489
530
  });
531
+
490
532
  const summary = this.summary ? html`<caption class="d2l-offscreen">${this.summary}</caption>` : '';
491
533
  const calendarClasses = {
492
534
  'd2l-calendar': true,
@@ -501,6 +543,7 @@ class Calendar extends LocalizeCoreElement(RtlMixin(LitElement)) {
501
543
  const heading = formatDate(new Date(this._shownYear, this._shownMonth, 1), { format: 'monthYear' });
502
544
  const regionLabel = this.label ? `${this.label}. ${heading}` : heading;
503
545
  const role = this._dialog ? 'dialog' : undefined;
546
+
504
547
  return html`
505
548
  <div role="region" aria-label="${regionLabel}">
506
549
  <div class="${classMap(calendarClasses)}" role="${ifDefined(role)}">
@@ -532,6 +575,7 @@ class Calendar extends LocalizeCoreElement(RtlMixin(LitElement)) {
532
575
  </div>
533
576
  </div>
534
577
  `;
578
+
535
579
  }
536
580
 
537
581
  updated(changedProperties) {
@@ -551,6 +595,26 @@ class Calendar extends LocalizeCoreElement(RtlMixin(LitElement)) {
551
595
  });
552
596
  }
553
597
 
598
+ willUpdate(changedProperties) {
599
+ super.willUpdate(changedProperties);
600
+
601
+ // don't dispatch d2l-calendar-view-change when _shownYear and _shownMonth are being initialized
602
+ if (changedProperties.get('_shownYear') === undefined && changedProperties.get('_shownMonth') === undefined) return;
603
+
604
+ const dates = getDatesInMonthArray(this._shownMonth, this._shownYear);
605
+
606
+ /** Dispatched when the calender view changes. "e.detail" provides the year and month in view. */
607
+ this.dispatchEvent(new CustomEvent('d2l-calendar-view-change', {
608
+ bubbles: false,
609
+ composed: false,
610
+ detail: {
611
+ maxValue: dates[dates.length - 1][6],
612
+ minValue: dates[0][0]
613
+ }
614
+ }));
615
+
616
+ }
617
+
554
618
  async focus() {
555
619
  if (this._dialog) {
556
620
  await this.updateComplete;
@@ -585,9 +649,7 @@ class Calendar extends LocalizeCoreElement(RtlMixin(LitElement)) {
585
649
  }
586
650
 
587
651
  _getInitialFocusDate() {
588
- let date;
589
- if (this.selectedValue) date = getDateFromISODate(this.selectedValue);
590
- else date = getDateFromISODate(getClosestValidDate(this.minValue, this.maxValue, false));
652
+ const date = getInitialFocusDate(this.selectedValue, this.minValue, this.maxValue);
591
653
  this._shownMonth = date.getMonth();
592
654
  this._shownYear = date.getFullYear();
593
655
  return date;
@@ -7,6 +7,22 @@
7
7
  <script type="module">
8
8
  import '../../demo/demo-page.js';
9
9
  import '../calendar.js';
10
+
11
+ window._allEvents = [
12
+ { date: '2024-08-21' },
13
+ { date: '2024-08-22' },
14
+ { date: '2024-09-04' },
15
+ { date: '2024-09-19' },
16
+ { date: '2024-09-20' },
17
+ { date: '2024-09-20' },
18
+ { date: '2024-09-28' },
19
+ { date: '2024-09-30' },
20
+ { date: '2024-10-02' },
21
+ { date: '2024-10-30' },
22
+ { date: '2024-10-31' },
23
+ { date: '2024-11-01' },
24
+ { date: '2024-11-11' }
25
+ ];
10
26
  </script>
11
27
  </head>
12
28
  <body unresolved>
@@ -33,6 +49,25 @@
33
49
  </template>
34
50
  </d2l-demo-snippet>
35
51
 
52
+ <h2>Calendar (with events)</h2>
53
+ <d2l-demo-snippet>
54
+ <template>
55
+ <d2l-calendar id="eventsCalendar" selected-value="2024-09-16"></d2l-calendar>
56
+ <script type="module">
57
+ import { getDateFromISODate, isDateInRange } from '../../../helpers/dateTime.js';
58
+ import { getMinMaxDatesInView } from '../calendar.js';
59
+
60
+ const getEvents = datesInView => {
61
+ return window._allEvents.filter(event => isDateInRange(getDateFromISODate(event.date), datesInView.minValue, datesInView.maxValue));
62
+ };
63
+
64
+ const calendar = document.querySelector('#eventsCalendar');
65
+ calendar.dayInfos = getEvents(getMinMaxDatesInView(calendar.selectedValue));
66
+ calendar.addEventListener('d2l-calendar-view-change', e => calendar.dayInfos = getEvents(e.detail));
67
+ </script>
68
+ </template>
69
+ </d2l-demo-snippet>
70
+
36
71
  </d2l-demo-page>
37
72
  </body>
38
73
  </html>
@@ -813,6 +813,11 @@
813
813
  "path": "./components/calendar/calendar.js",
814
814
  "description": "A component can be used to display a responsively sized calendar that allows for date selection.",
815
815
  "attributes": [
816
+ {
817
+ "name": "day-infos",
818
+ "description": "Additional info for each day (ex. events on [{\"date\": \"2024-09-19\"}])",
819
+ "type": "Array"
820
+ },
816
821
  {
817
822
  "name": "label",
818
823
  "description": "Unique label text for calendar (necessary if multiple calendars on page)",
@@ -840,6 +845,12 @@
840
845
  }
841
846
  ],
842
847
  "properties": [
848
+ {
849
+ "name": "dayInfos",
850
+ "attribute": "day-infos",
851
+ "description": "Additional info for each day (ex. events on [{\"date\": \"2024-09-19\"}])",
852
+ "type": "Array"
853
+ },
843
854
  {
844
855
  "name": "label",
845
856
  "attribute": "label",
@@ -872,6 +883,10 @@
872
883
  }
873
884
  ],
874
885
  "events": [
886
+ {
887
+ "name": "d2l-calendar-view-change",
888
+ "description": "Dispatched when the calender view changes. \"e.detail\" provides the year and month in view."
889
+ },
875
890
  {
876
891
  "name": "d2l-calendar-selected",
877
892
  "description": "Dispatched when a date is selected through click, space, or enter. \"e.detail.date\" is in ISO 8601 calendar date format (\"YYYY-MM-DD\")."
package/lang/ar.js CHANGED
@@ -2,6 +2,7 @@ export default {
2
2
  "components.alert.close": "إغلاق التنبيه",
3
3
  "components.breadcrumbs.breadcrumb": "شريط التنقل",
4
4
  "components.button-add.addItem": "إضافة عنصر",
5
+ "components.calendar.hasEvents": "Has Events.",
5
6
  "components.calendar.notSelected": "لم يتم التحديد.",
6
7
  "components.calendar.selected": "تم التحديد.",
7
8
  "components.calendar.show": "إظهار {month}",
package/lang/cy.js CHANGED
@@ -2,6 +2,7 @@ export default {
2
2
  "components.alert.close": "Cau Hysbysiad",
3
3
  "components.breadcrumbs.breadcrumb": "Briwsionyn Bara",
4
4
  "components.button-add.addItem": "Ychwanegu Eitem",
5
+ "components.calendar.hasEvents": "Has Events.",
5
6
  "components.calendar.notSelected": "Heb ei Ddewis.",
6
7
  "components.calendar.selected": "Wedi'i Ddewis.",
7
8
  "components.calendar.show": "Dangos {month}",
package/lang/da.js CHANGED
@@ -2,6 +2,7 @@ export default {
2
2
  "components.alert.close": "Luk besked",
3
3
  "components.breadcrumbs.breadcrumb": "Brødkrumme",
4
4
  "components.button-add.addItem": "Tilføj element",
5
+ "components.calendar.hasEvents": "Has Events.",
5
6
  "components.calendar.notSelected": "Ikke valgt.",
6
7
  "components.calendar.selected": "Valgt.",
7
8
  "components.calendar.show": "Vis {month}",
package/lang/de.js CHANGED
@@ -2,6 +2,7 @@ export default {
2
2
  "components.alert.close": "Benachrichtigung schließen",
3
3
  "components.breadcrumbs.breadcrumb": "Brotkrümelnavigation",
4
4
  "components.button-add.addItem": "Element hinzufügen",
5
+ "components.calendar.hasEvents": "Has Events.",
5
6
  "components.calendar.notSelected": "Nicht ausgewählt.",
6
7
  "components.calendar.selected": "Ausgewählt.",
7
8
  "components.calendar.show": "{month} anzeigen",
package/lang/en-gb.js CHANGED
@@ -2,6 +2,7 @@ export default {
2
2
  "components.alert.close": "Close Alert",
3
3
  "components.breadcrumbs.breadcrumb": "Breadcrumb",
4
4
  "components.button-add.addItem": "Add Item",
5
+ "components.calendar.hasEvents": "Has Events.",
5
6
  "components.calendar.notSelected": "Not Selected.",
6
7
  "components.calendar.selected": "Selected.",
7
8
  "components.calendar.show": "Show {month}",
package/lang/en.js CHANGED
@@ -2,6 +2,7 @@ export default {
2
2
  "components.alert.close": "Close Alert",
3
3
  "components.breadcrumbs.breadcrumb": "Breadcrumb",
4
4
  "components.button-add.addItem": "Add Item",
5
+ "components.calendar.hasEvents": "Has Events.",
5
6
  "components.calendar.notSelected": "Not Selected.",
6
7
  "components.calendar.selected": "Selected.",
7
8
  "components.calendar.show": "Show {month}",
package/lang/es-es.js CHANGED
@@ -2,6 +2,7 @@ export default {
2
2
  "components.alert.close": "Cerrar alerta",
3
3
  "components.breadcrumbs.breadcrumb": "Ruta de navegación",
4
4
  "components.button-add.addItem": "Agregar elemento",
5
+ "components.calendar.hasEvents": "Has Events.",
5
6
  "components.calendar.notSelected": "No seleccionado.",
6
7
  "components.calendar.selected": "Seleccionado.",
7
8
  "components.calendar.show": "Mostrar {month}",
package/lang/es.js CHANGED
@@ -2,6 +2,7 @@ export default {
2
2
  "components.alert.close": "Cerrar alerta",
3
3
  "components.breadcrumbs.breadcrumb": "Ruta de navegación",
4
4
  "components.button-add.addItem": "Agregar elemento",
5
+ "components.calendar.hasEvents": "Has Events.",
5
6
  "components.calendar.notSelected": "No seleccionado.",
6
7
  "components.calendar.selected": "Seleccionado.",
7
8
  "components.calendar.show": "Mostrar {month}",
package/lang/fr-fr.js CHANGED
@@ -2,6 +2,7 @@ export default {
2
2
  "components.alert.close": "Fermer l'alerte",
3
3
  "components.breadcrumbs.breadcrumb": "Chemin de navigation",
4
4
  "components.button-add.addItem": "Ajouter un élément",
5
+ "components.calendar.hasEvents": "Has Events.",
5
6
  "components.calendar.notSelected": "Non sélectionné.",
6
7
  "components.calendar.selected": "Sélectionné.",
7
8
  "components.calendar.show": "Afficher {month}",
package/lang/fr.js CHANGED
@@ -2,6 +2,7 @@ export default {
2
2
  "components.alert.close": "Fermer l'alerte",
3
3
  "components.breadcrumbs.breadcrumb": "Chemin de navigation",
4
4
  "components.button-add.addItem": "Ajouter un élément",
5
+ "components.calendar.hasEvents": "Has Events.",
5
6
  "components.calendar.notSelected": "Non sélectionné(e)",
6
7
  "components.calendar.selected": "Sélectionné(e).",
7
8
  "components.calendar.show": "Afficher {month}",
package/lang/hi.js CHANGED
@@ -2,6 +2,7 @@ export default {
2
2
  "components.alert.close": "अलर्ट बंद करें",
3
3
  "components.breadcrumbs.breadcrumb": "ब्रेडक्रंब",
4
4
  "components.button-add.addItem": "आइटम जोड़ें",
5
+ "components.calendar.hasEvents": "Has Events.",
5
6
  "components.calendar.notSelected": "चयनित नहीं।",
6
7
  "components.calendar.selected": "चयनित।",
7
8
  "components.calendar.show": "{month} दिखाएँ",
package/lang/ja.js CHANGED
@@ -2,6 +2,7 @@ export default {
2
2
  "components.alert.close": "アラートを閉じる",
3
3
  "components.breadcrumbs.breadcrumb": "階層",
4
4
  "components.button-add.addItem": "項目の追加",
5
+ "components.calendar.hasEvents": "Has Events.",
5
6
  "components.calendar.notSelected": "選択されていません。",
6
7
  "components.calendar.selected": "選択されています。",
7
8
  "components.calendar.show": "{month} を表示",
package/lang/ko.js CHANGED
@@ -2,6 +2,7 @@ export default {
2
2
  "components.alert.close": "경보 닫기",
3
3
  "components.breadcrumbs.breadcrumb": "이동 경로",
4
4
  "components.button-add.addItem": "항목 추가",
5
+ "components.calendar.hasEvents": "Has Events.",
5
6
  "components.calendar.notSelected": "선택되지 않음.",
6
7
  "components.calendar.selected": "선택됨.",
7
8
  "components.calendar.show": "{month} 표시",
package/lang/nl.js CHANGED
@@ -2,6 +2,7 @@ export default {
2
2
  "components.alert.close": "Waarschuwing sluiten",
3
3
  "components.breadcrumbs.breadcrumb": "Kruimelpad",
4
4
  "components.button-add.addItem": "Item toevoegen",
5
+ "components.calendar.hasEvents": "Has Events.",
5
6
  "components.calendar.notSelected": "Niet geselecteerd.",
6
7
  "components.calendar.selected": "Geselecteerd.",
7
8
  "components.calendar.show": "{month} weergeven",
package/lang/pt.js CHANGED
@@ -2,6 +2,7 @@ export default {
2
2
  "components.alert.close": "Fechar alerta",
3
3
  "components.breadcrumbs.breadcrumb": "Auxiliar de navegação",
4
4
  "components.button-add.addItem": "Adicionar item",
5
+ "components.calendar.hasEvents": "Has Events.",
5
6
  "components.calendar.notSelected": "Não selecionado.",
6
7
  "components.calendar.selected": "Selecionado.",
7
8
  "components.calendar.show": "Mostrar {month}",
package/lang/sv.js CHANGED
@@ -2,6 +2,7 @@ export default {
2
2
  "components.alert.close": "Stängningsvarning",
3
3
  "components.breadcrumbs.breadcrumb": "Sökväg",
4
4
  "components.button-add.addItem": "Lägg till objekt",
5
+ "components.calendar.hasEvents": "Has Events.",
5
6
  "components.calendar.notSelected": "Inte vald.",
6
7
  "components.calendar.selected": "Markerad.",
7
8
  "components.calendar.show": "Visa {month}",
package/lang/tr.js CHANGED
@@ -2,6 +2,7 @@ export default {
2
2
  "components.alert.close": "Kapatma Uyarısı",
3
3
  "components.breadcrumbs.breadcrumb": "İçerik Haritası",
4
4
  "components.button-add.addItem": "Öğe Ekle",
5
+ "components.calendar.hasEvents": "Has Events.",
5
6
  "components.calendar.notSelected": "Seçili Değil.",
6
7
  "components.calendar.selected": "Seçili.",
7
8
  "components.calendar.show": "{month} Göster",
package/lang/zh-cn.js CHANGED
@@ -2,6 +2,7 @@ export default {
2
2
  "components.alert.close": "关闭提醒",
3
3
  "components.breadcrumbs.breadcrumb": "痕迹导航",
4
4
  "components.button-add.addItem": "添加项目",
5
+ "components.calendar.hasEvents": "Has Events.",
5
6
  "components.calendar.notSelected": "未选择。",
6
7
  "components.calendar.selected": "已选择。",
7
8
  "components.calendar.show": "显示 {month}",
package/lang/zh-tw.js CHANGED
@@ -2,6 +2,7 @@ export default {
2
2
  "components.alert.close": "關閉警示",
3
3
  "components.breadcrumbs.breadcrumb": "導覽路徑",
4
4
  "components.button-add.addItem": "新增項目",
5
+ "components.calendar.hasEvents": "Has Events.",
5
6
  "components.calendar.notSelected": "未選取。",
6
7
  "components.calendar.selected": "已選取。",
7
8
  "components.calendar.show": "顯示{month}",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspace-ui/core",
3
- "version": "3.44.2",
3
+ "version": "3.45.0",
4
4
  "description": "A collection of accessible, free, open-source web components for building Brightspace applications",
5
5
  "type": "module",
6
6
  "repository": "https://github.com/BrightspaceUI/core.git",