@refinitiv-ui/elements 5.7.0 → 5.9.0-alpha.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 (170) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/lib/autosuggest/custom-elements.json +14 -4
  3. package/lib/autosuggest/custom-elements.md +21 -14
  4. package/lib/autosuggest/index.d.ts +4 -0
  5. package/lib/autosuggest/index.js +4 -0
  6. package/lib/calendar/constants.d.ts +4 -0
  7. package/lib/calendar/constants.js +5 -0
  8. package/lib/calendar/custom-elements.json +4 -2
  9. package/lib/calendar/custom-elements.md +2 -2
  10. package/lib/calendar/index.d.ts +108 -17
  11. package/lib/calendar/index.js +488 -120
  12. package/lib/calendar/locales.js +2 -1
  13. package/lib/calendar/themes/halo/dark/index.js +1 -1
  14. package/lib/calendar/themes/halo/light/index.js +1 -1
  15. package/lib/calendar/themes/solar/charcoal/index.js +1 -1
  16. package/lib/calendar/themes/solar/pearl/index.js +1 -1
  17. package/lib/calendar/types.d.ts +11 -8
  18. package/lib/calendar/utils.js +2 -1
  19. package/lib/canvas/custom-elements.json +7 -5
  20. package/lib/canvas/custom-elements.md +8 -8
  21. package/lib/canvas/index.d.ts +1 -0
  22. package/lib/canvas/index.js +1 -0
  23. package/lib/card/custom-elements.json +3 -1
  24. package/lib/card/custom-elements.md +5 -5
  25. package/lib/card/index.d.ts +2 -0
  26. package/lib/card/index.js +2 -0
  27. package/lib/chart/custom-elements.json +1 -1
  28. package/lib/chart/custom-elements.md +4 -4
  29. package/lib/checkbox/custom-elements.json +8 -4
  30. package/lib/checkbox/custom-elements.md +2 -2
  31. package/lib/checkbox/index.d.ts +3 -1
  32. package/lib/checkbox/index.js +2 -0
  33. package/lib/clock/custom-elements.json +8 -4
  34. package/lib/clock/custom-elements.md +9 -9
  35. package/lib/clock/index.d.ts +2 -0
  36. package/lib/clock/index.js +2 -0
  37. package/lib/clock/themes/halo/dark/index.js +1 -1
  38. package/lib/clock/themes/halo/light/index.js +1 -1
  39. package/lib/clock/themes/solar/charcoal/index.js +1 -1
  40. package/lib/clock/themes/solar/pearl/index.js +1 -1
  41. package/lib/color-dialog/custom-elements.json +21 -8
  42. package/lib/color-dialog/custom-elements.md +22 -22
  43. package/lib/color-dialog/index.d.ts +8 -8
  44. package/lib/color-dialog/index.js +8 -8
  45. package/lib/combo-box/custom-elements.json +19 -10
  46. package/lib/combo-box/custom-elements.md +20 -20
  47. package/lib/combo-box/index.d.ts +10 -2
  48. package/lib/combo-box/index.js +10 -1
  49. package/lib/combo-box/themes/halo/dark/index.js +1 -1
  50. package/lib/combo-box/themes/halo/light/index.js +1 -1
  51. package/lib/combo-box/themes/solar/charcoal/index.js +1 -1
  52. package/lib/combo-box/themes/solar/pearl/index.js +1 -1
  53. package/lib/counter/custom-elements.json +8 -4
  54. package/lib/counter/custom-elements.md +4 -4
  55. package/lib/counter/index.d.ts +2 -0
  56. package/lib/counter/index.js +2 -0
  57. package/lib/datetime-picker/custom-elements.json +48 -19
  58. package/lib/datetime-picker/custom-elements.md +36 -28
  59. package/lib/datetime-picker/index.d.ts +15 -4
  60. package/lib/datetime-picker/index.js +15 -4
  61. package/lib/dialog/custom-elements.json +30 -8
  62. package/lib/dialog/custom-elements.md +16 -16
  63. package/lib/dialog/index.d.ts +7 -10
  64. package/lib/dialog/index.js +7 -10
  65. package/lib/email-field/custom-elements.json +80 -93
  66. package/lib/email-field/custom-elements.md +22 -20
  67. package/lib/email-field/index.d.ts +43 -115
  68. package/lib/email-field/index.js +44 -244
  69. package/lib/flag/custom-elements.md +4 -4
  70. package/lib/flag/index.d.ts +2 -0
  71. package/lib/flag/index.js +2 -0
  72. package/lib/icon/custom-elements.md +4 -4
  73. package/lib/icon/index.d.ts +2 -0
  74. package/lib/icon/index.js +2 -0
  75. package/lib/interactive-chart/custom-elements.json +6 -10
  76. package/lib/interactive-chart/custom-elements.md +6 -7
  77. package/lib/interactive-chart/index.d.ts +5 -2
  78. package/lib/interactive-chart/index.js +5 -2
  79. package/lib/item/custom-elements.json +8 -6
  80. package/lib/item/custom-elements.md +14 -14
  81. package/lib/item/index.d.ts +2 -1
  82. package/lib/item/index.js +2 -1
  83. package/lib/led-gauge/custom-elements.json +4 -4
  84. package/lib/led-gauge/custom-elements.md +2 -2
  85. package/lib/led-gauge/index.d.ts +1 -0
  86. package/lib/led-gauge/index.js +1 -0
  87. package/lib/list/custom-elements.json +18 -5
  88. package/lib/list/custom-elements.md +12 -10
  89. package/lib/list/helpers/list-renderer.js +2 -0
  90. package/lib/list/index.d.ts +19 -2
  91. package/lib/list/index.js +34 -1
  92. package/lib/multi-input/custom-elements.json +3 -2
  93. package/lib/multi-input/custom-elements.md +16 -16
  94. package/lib/multi-input/index.d.ts +4 -0
  95. package/lib/multi-input/index.js +4 -0
  96. package/lib/number-field/custom-elements.json +97 -52
  97. package/lib/number-field/custom-elements.md +27 -22
  98. package/lib/number-field/index.d.ts +92 -47
  99. package/lib/number-field/index.js +113 -80
  100. package/lib/overlay/custom-elements.json +23 -13
  101. package/lib/overlay/custom-elements.md +29 -29
  102. package/lib/overlay/elements/overlay.d.ts +5 -0
  103. package/lib/overlay-menu/custom-elements.json +66 -14
  104. package/lib/overlay-menu/custom-elements.md +19 -19
  105. package/lib/overlay-menu/index.d.ts +13 -11
  106. package/lib/overlay-menu/index.js +13 -11
  107. package/lib/password-field/custom-elements.json +62 -67
  108. package/lib/password-field/custom-elements.md +19 -11
  109. package/lib/password-field/index.d.ts +42 -94
  110. package/lib/password-field/index.js +48 -194
  111. package/lib/pill/custom-elements.json +4 -2
  112. package/lib/pill/custom-elements.md +1 -1
  113. package/lib/pill/index.d.ts +1 -1
  114. package/lib/pill/index.js +1 -1
  115. package/lib/radio-button/custom-elements.json +8 -6
  116. package/lib/radio-button/custom-elements.md +3 -3
  117. package/lib/radio-button/index.d.ts +6 -5
  118. package/lib/radio-button/index.js +5 -4
  119. package/lib/search-field/custom-elements.json +70 -74
  120. package/lib/search-field/custom-elements.md +24 -16
  121. package/lib/search-field/index.d.ts +43 -100
  122. package/lib/search-field/index.js +46 -215
  123. package/lib/select/custom-elements.json +3 -2
  124. package/lib/select/custom-elements.md +10 -10
  125. package/lib/select/index.d.ts +11 -3
  126. package/lib/select/index.js +65 -26
  127. package/lib/sidebar-layout/custom-elements.json +2 -6
  128. package/lib/sidebar-layout/custom-elements.md +5 -6
  129. package/lib/sidebar-layout/index.d.ts +2 -1
  130. package/lib/slider/custom-elements.json +2 -2
  131. package/lib/slider/custom-elements.md +1 -1
  132. package/lib/slider/index.d.ts +1 -1
  133. package/lib/slider/index.js +1 -1
  134. package/lib/sparkline/custom-elements.json +4 -4
  135. package/lib/sparkline/custom-elements.md +2 -2
  136. package/lib/sparkline/index.d.ts +3 -1
  137. package/lib/sparkline/index.js +2 -0
  138. package/lib/swing-gauge/custom-elements.json +5 -3
  139. package/lib/swing-gauge/custom-elements.md +11 -11
  140. package/lib/swing-gauge/index.d.ts +3 -1
  141. package/lib/swing-gauge/index.js +3 -1
  142. package/lib/text-field/custom-elements.json +76 -87
  143. package/lib/text-field/custom-elements.md +24 -26
  144. package/lib/text-field/index.d.ts +50 -92
  145. package/lib/text-field/index.js +81 -230
  146. package/lib/time-picker/custom-elements.md +3 -3
  147. package/lib/time-picker/index.d.ts +3 -0
  148. package/lib/time-picker/index.js +3 -0
  149. package/lib/toggle/custom-elements.json +4 -2
  150. package/lib/toggle/custom-elements.md +1 -1
  151. package/lib/toggle/index.d.ts +2 -1
  152. package/lib/toggle/index.js +1 -0
  153. package/lib/tree/custom-elements.json +2 -1
  154. package/lib/tree/custom-elements.md +1 -1
  155. package/lib/tree/elements/tree.d.ts +1 -0
  156. package/lib/tree/elements/tree.js +1 -0
  157. package/lib/tree/themes/halo/dark/index.js +1 -1
  158. package/lib/tree/themes/halo/light/index.js +1 -1
  159. package/lib/tree/themes/solar/charcoal/index.js +1 -1
  160. package/lib/tree/themes/solar/pearl/index.js +1 -1
  161. package/lib/tree-select/custom-elements.json +8 -4
  162. package/lib/tree-select/custom-elements.md +3 -3
  163. package/lib/tree-select/index.d.ts +5 -3
  164. package/lib/tree-select/index.js +3 -2
  165. package/lib/tree-select/themes/halo/dark/index.js +1 -1
  166. package/lib/tree-select/themes/halo/light/index.js +1 -1
  167. package/lib/tree-select/themes/solar/charcoal/index.js +1 -1
  168. package/lib/tree-select/themes/solar/pearl/index.js +1 -1
  169. package/lib/version.js +1 -1
  170. package/package.json +292 -11
@@ -2,15 +2,21 @@ import { __decorate } from "tslib";
2
2
  import { ControlElement, html, css, WarningNotice } from '@refinitiv-ui/core';
3
3
  import { customElement } from '@refinitiv-ui/core/lib/decorators/custom-element.js';
4
4
  import { property } from '@refinitiv-ui/core/lib/decorators/property.js';
5
+ import { state } from '@refinitiv-ui/core/lib/decorators/state.js';
5
6
  import { ifDefined } from '@refinitiv-ui/core/lib/directives/if-defined.js';
7
+ import { cache } from '@refinitiv-ui/core/lib/directives/cache.js';
8
+ import { guard } from '@refinitiv-ui/core/lib/directives/guard.js';
9
+ import { ref, createRef } from '@refinitiv-ui/core/lib/directives/ref.js';
6
10
  import { VERSION } from '../version.js';
7
11
  import { isIE } from '@refinitiv-ui/utils/lib/browser.js';
8
- import { DateFormat, format, utcFormat, utcParse, isValidDate, isWeekend, isAfter, isBefore, addMonths, subMonths, isToday, isThisMonth, isThisYear, isSameDay, isSameMonth, isSameYear, toDateSegment } from '@refinitiv-ui/utils/lib/date.js';
12
+ import { DateFormat, format, utcFormat, utcParse, isValidDate, isWeekend, isAfter, isBefore, addMonths, subMonths, isToday, isThisMonth, isThisYear, isSameDay, isSameMonth, isSameYear, toDateSegment, parse } from '@refinitiv-ui/utils/lib/date.js';
13
+ import { left, right, up, down, first, last } from '@refinitiv-ui/utils/lib/navigation.js';
9
14
  import { monthInfo, weekdaysNames, monthsNames, formatLocaleDate, ViewFormatTranslateParams } from './utils.js';
10
15
  import { translate, getLocale, TranslatePropertyKey } from '@refinitiv-ui/translate';
11
- import { RenderView, FIRST_DAY_OF_WEEK, YEARS_PER_YEAR_VIEW, DAY_VIEW, YEAR_VIEW, MONTH_VIEW } from './constants.js';
16
+ import { RenderView, CalendarLocaleScope, FIRST_DAY_OF_WEEK, YEARS_PER_YEAR_VIEW, DAY_VIEW, YEAR_VIEW, MONTH_VIEW } from './constants.js';
12
17
  import './locales.js';
13
18
  import '../button/index.js';
19
+ import '@refinitiv-ui/phrasebook/lib/locale/en/calendar.js';
14
20
  /**
15
21
  * Standard calendar element
16
22
  *
@@ -28,6 +34,11 @@ import '../button/index.js';
28
34
  let Calendar = class Calendar extends ControlElement {
29
35
  constructor() {
30
36
  super(...arguments);
37
+ this.defaultRole = 'group';
38
+ /**
39
+ * Reference to the view button
40
+ */
41
+ this.viewBtnRef = createRef();
31
42
  this._min = '';
32
43
  this._max = '';
33
44
  /**
@@ -62,8 +73,20 @@ let Calendar = class Calendar extends ControlElement {
62
73
  /**
63
74
  * Used for internal navigation between render views
64
75
  */
65
- this.renderView = RenderView.DAY;
66
- this.isDateAvailable = null; /* a constructed filter based on multiple local filters */
76
+ this._renderView = RenderView.DAY;
77
+ /**
78
+ * Used for keyboard navigation when trying
79
+ * to restore focus on re-render and control navigation
80
+ */
81
+ this._activeCellIndex = null;
82
+ // Used to store current navigation map
83
+ this.navigationGrid = [];
84
+ /**
85
+ * Connected to role. If false, the values are not announced in the screen reader
86
+ */
87
+ this.announceValues = true;
88
+ // Cashed filter, which is constructed based on multiple local filters
89
+ this.isDateAvailable = null;
67
90
  }
68
91
  /**
69
92
  * Element version number
@@ -83,14 +106,14 @@ let Calendar = class Calendar extends ControlElement {
83
106
  :host {
84
107
  display: inline-block;
85
108
  }
86
- [part=navigation], [part=navigation] section {
109
+ [part~=navigation], [part~=navigation] section {
87
110
  display: flex;
88
111
  flex-flow: row nowrap;
89
112
  }
90
- [part=navigation] {
113
+ [part~=navigation] {
91
114
  justify-content: space-between;
92
115
  }
93
- [part=navigation] > div {
116
+ [part~=navigation] > div {
94
117
  display: flex;
95
118
  flex: 1;
96
119
  justify-content: center;
@@ -101,7 +124,6 @@ let Calendar = class Calendar extends ControlElement {
101
124
  bottom: 0;
102
125
  left: 0;
103
126
  right: 0;
104
- pointer-events: none;
105
127
  display: flex;
106
128
  align-items: center;
107
129
  justify-content: center;
@@ -131,7 +153,10 @@ let Calendar = class Calendar extends ControlElement {
131
153
  width: calc(100% / ${DAY_VIEW.columnCount});
132
154
  padding-top: calc(100% / ${DAY_VIEW.columnCount});
133
155
  }
134
- [part~=cell][tabindex] {
156
+ [part~=cell-content]:not([tabindex]) {
157
+ pointer-events: none;
158
+ }
159
+ [part~=selection] {
135
160
  cursor: pointer;
136
161
  }
137
162
  `;
@@ -187,6 +212,7 @@ let Calendar = class Calendar extends ControlElement {
187
212
  const oldView = this._view;
188
213
  if (oldView !== view) {
189
214
  this._view = view;
215
+ this.resetActiveCellIndex();
190
216
  this.requestUpdate('view', oldView);
191
217
  }
192
218
  }
@@ -199,6 +225,7 @@ let Calendar = class Calendar extends ControlElement {
199
225
  * 0 - for Sunday, 6 - for Saturday
200
226
  * @param firstDayOfWeek The first day of the week
201
227
  * @type {number | null}
228
+ * @default null
202
229
  */
203
230
  set firstDayOfWeek(firstDayOfWeek) {
204
231
  firstDayOfWeek %= 7;
@@ -226,6 +253,7 @@ let Calendar = class Calendar extends ControlElement {
226
253
  * Set multiple selected values
227
254
  * @param values Values to set
228
255
  * @type {string[]}
256
+ * @default []
229
257
  */
230
258
  set values(values) {
231
259
  const oldValues = this._values;
@@ -238,27 +266,82 @@ let Calendar = class Calendar extends ControlElement {
238
266
  get values() {
239
267
  return this._values.concat();
240
268
  }
269
+ get renderView() {
270
+ return this._renderView;
271
+ }
272
+ set renderView(renderView) {
273
+ const oldRenderView = this._renderView;
274
+ if (oldRenderView !== renderView) {
275
+ this._renderView = renderView;
276
+ // always reset active cell to not focus on potentially invalid cell
277
+ this.resetActiveCellIndex();
278
+ this.requestUpdate('renderView', oldRenderView);
279
+ }
280
+ }
281
+ get activeCellIndex() {
282
+ return this._activeCellIndex;
283
+ }
284
+ set activeCellIndex(activeCellIndex) {
285
+ const oldCellIndex = this._activeCellIndex;
286
+ if (String(activeCellIndex) !== String(oldCellIndex)) {
287
+ this._activeCellIndex = activeCellIndex;
288
+ this.requestUpdate('activeCellIndex', oldCellIndex);
289
+ }
290
+ }
241
291
  /**
242
- * Get weekday numbers.
243
- * Sort the list based on first day of the week
292
+ * Silently reset cell index without calling request update
293
+ * @returns {void}
244
294
  */
245
- get weekdaysNames() {
246
- const firstDayOfWeek = this.firstDayOfWeek;
247
- const localWeekdaysNames = this.localWeekdaysNames;
248
- return localWeekdaysNames.slice(firstDayOfWeek).concat(localWeekdaysNames.slice(0, firstDayOfWeek));
295
+ resetActiveCellIndex() {
296
+ this._activeCellIndex = null;
297
+ }
298
+ /**
299
+ * Get an active element
300
+ */
301
+ get activeElement() {
302
+ return this.shadowRoot.activeElement;
303
+ }
304
+ /**
305
+ * Get selectable date button element by index
306
+ * @param index Cell index
307
+ * @returns button HTML date button element or null
308
+ */
309
+ getDateButtonByIndex(index) {
310
+ const elements = Array.from(this.renderRoot.querySelectorAll('[part~=cell] > [part~=selection]'));
311
+ return elements.find((element) => this.isDateButton(element) && String(element.index) === String(index));
249
312
  }
250
313
  /**
251
- * Get localised month names from January to December
314
+ * Get active date button element
315
+ * @returns button HTML date button element or null
252
316
  */
253
- get monthsNames() {
254
- return this.localMonthsNames;
317
+ get activeDateButton() {
318
+ return this.renderRoot.querySelector('[part~=cell][active] > [part~=selection]');
319
+ }
320
+ /**
321
+ * Return true if passed target is HTML
322
+ * date button element that can be selected
323
+ * @param target Target to check
324
+ * @returns isDateButtonElement
325
+ */
326
+ isDateButton(target) {
327
+ return target.index !== undefined;
328
+ }
329
+ static get observedAttributes() {
330
+ const observed = super.observedAttributes;
331
+ return ['role'].concat(observed);
332
+ }
333
+ attributeChangedCallback(name, oldValue, newValue) {
334
+ super.attributeChangedCallback(name, oldValue, newValue);
335
+ if (name === 'role') {
336
+ this.announceValues = !(!newValue || newValue === 'none' || newValue === 'presentation');
337
+ }
255
338
  }
256
339
  /**
257
340
  * Perform asynchronous update
258
341
  * @returns promise
259
342
  */
260
343
  async performUpdate() {
261
- const localFirstDayOfWeek = Number(await this.tPromise('FIRST_DAY_OF_WEEK'));
344
+ const localFirstDayOfWeek = Number(await this.dateTPromise('FIRST_DAY_OF_WEEK'));
262
345
  this.localFirstDayOfWeek = isNaN(localFirstDayOfWeek) ? FIRST_DAY_OF_WEEK : (localFirstDayOfWeek % 7);
263
346
  void super.performUpdate();
264
347
  }
@@ -269,14 +352,39 @@ let Calendar = class Calendar extends ControlElement {
269
352
  */
270
353
  update(changedProperties) {
271
354
  if (!this.localMonthsNames || changedProperties.has(TranslatePropertyKey)) {
272
- this.localMonthsNames = monthsNames(getLocale(this));
355
+ const locale = getLocale(this);
356
+ this.localMonthsNames = monthsNames(locale);
273
357
  }
274
358
  if (!this.localWeekdaysNames || changedProperties.has(TranslatePropertyKey)) {
275
- this.localWeekdaysNames = weekdaysNames(getLocale(this));
359
+ const locale = getLocale(this);
360
+ const longWeekdaysNames = weekdaysNames(locale, 'long');
361
+ this.localWeekdaysNames = weekdaysNames(locale).map((narrow, index) => {
362
+ return { narrow, long: longWeekdaysNames[index] };
363
+ });
276
364
  }
277
365
  this.shouldConstructFilters(changedProperties) && this.constructFilters();
278
366
  super.update(changedProperties);
279
367
  }
368
+ /**
369
+ * Called after render life-cycle finished
370
+ * @param changedProperties Properties which have changed
371
+ * @return {void}
372
+ */
373
+ updated(changedProperties) {
374
+ super.updated(changedProperties);
375
+ // This code is here to ensure that focus is not lost
376
+ // while navigating through the render views using keyboard
377
+ if (this.focused && changedProperties.has('renderView') && this.viewBtnRef.value && this.activeElement !== this.viewBtnRef.value) {
378
+ this.viewBtnRef.value.focus();
379
+ }
380
+ const cellIndex = this.activeCellIndex;
381
+ if (cellIndex && changedProperties.has('activeCellIndex')) {
382
+ const dateButtonEl = this.getDateButtonByIndex(cellIndex);
383
+ if (dateButtonEl && this.activeElement !== dateButtonEl) {
384
+ dateButtonEl.focus();
385
+ }
386
+ }
387
+ }
280
388
  /**
281
389
  * Run when an element has been first updated
282
390
  * @param changedProperties properties that was changed on first update
@@ -284,7 +392,7 @@ let Calendar = class Calendar extends ControlElement {
284
392
  */
285
393
  firstUpdated(changedProperties) {
286
394
  super.firstUpdated(changedProperties);
287
- this.renderRoot.addEventListener('keydown', event => this.onTableKeyDown(event));
395
+ this.renderRoot.addEventListener('keydown', event => this.onKeyDown(event));
288
396
  }
289
397
  /**
290
398
  * Show invalid view message
@@ -416,78 +524,88 @@ let Calendar = class Calendar extends ControlElement {
416
524
  rangeTo
417
525
  };
418
526
  }
527
+ /**
528
+ * Set navigation map based on rows
529
+ * @param rows A collection of rows with cells
530
+ * @returns {void}
531
+ */
532
+ setNavigationMap(rows) {
533
+ this.navigationGrid = rows.map(row => row.map(cell => cell.value && !cell.disabled ? 1 : 0));
534
+ }
419
535
  /**
420
536
  * Run when next button is tapped.
421
537
  * Change current view to next view
538
+ * @param event Next view tap event
422
539
  * @returns {void}
423
540
  */
424
- onNextTap() {
425
- let viewSegment = toDateSegment(this.view);
426
- switch (this.renderView) {
427
- case RenderView.DAY:
428
- viewSegment = toDateSegment(addMonths(this.view, 1));
429
- break;
430
- case RenderView.MONTH:
431
- viewSegment.year += 1;
432
- break;
433
- case RenderView.YEAR:
434
- viewSegment.year += YEARS_PER_YEAR_VIEW;
435
- break;
436
- // no default
541
+ onNextTap(event) {
542
+ if (!event.defaultPrevented) {
543
+ this.toNextView();
437
544
  }
438
- this.notifyViewChange(viewSegment);
439
545
  }
440
546
  /**
441
547
  * Run when previous button is tapped.
442
548
  * Change current view to previous view
549
+ * @param event Previous view tap event
443
550
  * @returns {void}
444
551
  */
445
- onPreviousTap() {
446
- let viewSegment = toDateSegment(this.view);
447
- switch (this.renderView) {
448
- case RenderView.DAY:
449
- viewSegment = toDateSegment(subMonths(this.view, 1));
450
- break;
451
- case RenderView.MONTH:
452
- viewSegment.year -= 1;
453
- break;
454
- case RenderView.YEAR:
455
- viewSegment.year -= YEARS_PER_YEAR_VIEW;
456
- break;
457
- // no default
552
+ onPreviousTap(event) {
553
+ if (!event.defaultPrevented) {
554
+ this.toPreviousView();
458
555
  }
459
- this.notifyViewChange(viewSegment);
460
556
  }
461
557
  /**
462
558
  * Run when change view button is tapped.
463
559
  * Switch between views
560
+ * @param event Render view tap event
464
561
  * @returns {void}
465
562
  */
466
- onRenderViewTap() {
467
- this.renderView = this.renderView === RenderView.DAY ? RenderView.YEAR : RenderView.DAY;
563
+ onRenderViewTap(event) {
564
+ if (!event.defaultPrevented) {
565
+ this.renderView = this.renderView === RenderView.DAY ? RenderView.YEAR : RenderView.DAY;
566
+ }
468
567
  }
469
568
  /**
470
569
  * Run when key down event happens on calendar
471
570
  * @param event Keyboard event
472
571
  * @returns {void}
473
572
  */
474
- onTableKeyDown(event) {
573
+ onKeyDown(event) {
574
+ if (event.defaultPrevented) {
575
+ return;
576
+ }
475
577
  switch (event.key) {
476
- case ' ':
477
- case 'Enter':
478
- case 'Spacebar':
479
- event.preventDefault();
480
- this.onTableTap(event);
481
- break;
482
578
  case 'Esc':
483
579
  case 'Escape':
484
580
  if (this.renderView === RenderView.YEAR || this.renderView === RenderView.MONTH) {
485
- event.preventDefault();
486
581
  this.renderView = RenderView.DAY;
582
+ break;
487
583
  }
584
+ return;
585
+ case 'Up': // IE11
586
+ case 'ArrowUp':
587
+ void this.onNavigation('ArrowUp');
488
588
  break;
489
- // no default
589
+ case 'Down':
590
+ case 'ArrowDown':
591
+ void this.onNavigation('ArrowDown');
592
+ break;
593
+ case 'Left':
594
+ case 'ArrowLeft':
595
+ void this.onNavigation('ArrowLeft');
596
+ break;
597
+ case 'Right':
598
+ case 'ArrowRight':
599
+ void this.onNavigation('ArrowRight');
600
+ break;
601
+ case 'Home':
602
+ case 'End':
603
+ void this.onNavigation(event.key);
604
+ break;
605
+ default:
606
+ return;
490
607
  }
608
+ event.preventDefault();
491
609
  }
492
610
  /**
493
611
  * Run when tap event happens ot table.
@@ -496,10 +614,14 @@ let Calendar = class Calendar extends ControlElement {
496
614
  * @returns {void}
497
615
  */
498
616
  onTableTap(event) {
499
- const cell = event.target; /* here we just emulate interface */
500
- if (!cell || !cell.value) {
617
+ if (event.defaultPrevented) {
618
+ return;
619
+ }
620
+ const cell = event.target;
621
+ if (!cell || !this.isDateButton(cell) || !cell.value) {
501
622
  return;
502
623
  }
624
+ this.activeCellIndex = cell.index;
503
625
  const cellSegment = toDateSegment(cell.value);
504
626
  const viewSegment = toDateSegment(this.view);
505
627
  if (this.renderView === RenderView.YEAR) { /* YEAR -> MONTH */
@@ -519,6 +641,117 @@ let Calendar = class Calendar extends ControlElement {
519
641
  }
520
642
  this.onTapSelectValue(cell.value);
521
643
  }
644
+ /**
645
+ * Navigate over the grid
646
+ * @param key Navigation direction
647
+ * @returns navigation promise
648
+ */
649
+ async onNavigation(key) {
650
+ const grid = this.navigationGrid;
651
+ switch (key) {
652
+ case 'Home':
653
+ this.activeCellIndex = first(grid);
654
+ return;
655
+ case 'End':
656
+ this.activeCellIndex = last(grid);
657
+ return;
658
+ // no default
659
+ }
660
+ // no previously selected cell, but there is cell which is a candidate for navigation
661
+ const activeDateEl = this.activeDateButton;
662
+ if (!this.activeCellIndex && activeDateEl) {
663
+ this.activeCellIndex = activeDateEl.index;
664
+ // current cell is already in focus (e.g. via Tab key, continue navigation from that point)
665
+ if (!(this.activeElement === activeDateEl)) {
666
+ return;
667
+ }
668
+ }
669
+ const activeCellIndex = this.activeCellIndex;
670
+ // All cells are disabled
671
+ if (!activeCellIndex) {
672
+ return;
673
+ }
674
+ // active cell is selected
675
+ if (activeCellIndex) {
676
+ let newActiveCell;
677
+ switch (key) {
678
+ case 'ArrowUp':
679
+ newActiveCell = up(grid, activeCellIndex);
680
+ break;
681
+ case 'ArrowDown':
682
+ newActiveCell = down(grid, activeCellIndex);
683
+ break;
684
+ case 'ArrowLeft':
685
+ newActiveCell = left(grid, activeCellIndex);
686
+ break;
687
+ case 'ArrowRight':
688
+ newActiveCell = right(grid, activeCellIndex);
689
+ break;
690
+ // no default
691
+ }
692
+ // Standard navigation withing the same view
693
+ if (newActiveCell) {
694
+ this.activeCellIndex = newActiveCell;
695
+ return;
696
+ }
697
+ }
698
+ // Jump to the next view
699
+ switch (key) {
700
+ // case 'ArrowUp': // it feels better not having Up/Down in these case
701
+ case 'ArrowLeft':
702
+ this.toPreviousView();
703
+ await this.updateComplete; // must wait until the render cycle has finished
704
+ await this.onNavigation('End');
705
+ break;
706
+ // case 'ArrowDown':
707
+ case 'ArrowRight':
708
+ this.toNextView();
709
+ await this.updateComplete;
710
+ await this.onNavigation('Home');
711
+ break;
712
+ // no default
713
+ }
714
+ }
715
+ /**
716
+ * Navigate to the next view
717
+ * @returns {void}
718
+ */
719
+ toNextView() {
720
+ let viewSegment = toDateSegment(this.view);
721
+ switch (this.renderView) {
722
+ case RenderView.DAY:
723
+ viewSegment = toDateSegment(addMonths(this.view, 1));
724
+ break;
725
+ case RenderView.MONTH:
726
+ viewSegment.year += 1;
727
+ break;
728
+ case RenderView.YEAR:
729
+ viewSegment.year += YEARS_PER_YEAR_VIEW;
730
+ break;
731
+ // no default
732
+ }
733
+ this.notifyViewChange(viewSegment);
734
+ }
735
+ /**
736
+ * Navigate to the previous view
737
+ * @returns {void}
738
+ */
739
+ toPreviousView() {
740
+ let viewSegment = toDateSegment(this.view);
741
+ switch (this.renderView) {
742
+ case RenderView.DAY:
743
+ viewSegment = toDateSegment(subMonths(this.view, 1));
744
+ break;
745
+ case RenderView.MONTH:
746
+ viewSegment.year -= 1;
747
+ break;
748
+ case RenderView.YEAR:
749
+ viewSegment.year -= YEARS_PER_YEAR_VIEW;
750
+ break;
751
+ // no default
752
+ }
753
+ this.notifyViewChange(viewSegment);
754
+ }
522
755
  /**
523
756
  * Run when tap event happened on DAY view and the cell has the values
524
757
  * Try to select/deselect cell value
@@ -531,12 +764,14 @@ let Calendar = class Calendar extends ControlElement {
531
764
  }
532
765
  let values;
533
766
  if (this.multiple) {
534
- values = this.values.filter(oldValue => {
535
- return oldValue !== value;
536
- });
537
- if (this.values.length === values.length) {
767
+ values = this.values.concat([]);
768
+ const valueIdx = this.values.indexOf(value);
769
+ if (valueIdx === -1) {
538
770
  values.push(value);
539
771
  }
772
+ else {
773
+ values.splice(valueIdx, 1);
774
+ }
540
775
  }
541
776
  else if (this.range) {
542
777
  if (!this.values.length) {
@@ -552,12 +787,16 @@ let Calendar = class Calendar extends ControlElement {
552
787
  values = [value];
553
788
  }
554
789
  }
555
- else {
790
+ else if (this.values.indexOf(value) === -1) {
556
791
  values = [value];
557
792
  }
793
+ else {
794
+ // remove range if start/end index match
795
+ values = [];
796
+ }
558
797
  }
559
798
  else {
560
- values = [value];
799
+ values = this.value === value ? [] : [value];
561
800
  }
562
801
  this.notifyValuesChange(values);
563
802
  }
@@ -601,11 +840,7 @@ let Calendar = class Calendar extends ControlElement {
601
840
  if (isIE && isBC) {
602
841
  return html `${formatLocaleDate(date, getLocale(this), includeMonth, includeEra)}`;
603
842
  }
604
- return html `${this.t('VIEW_FORMAT', {
605
- date,
606
- includeMonth,
607
- includeEra
608
- }, ViewFormatTranslateParams)}`;
843
+ return html `${this.dateT('VIEW_FORMAT', { date, includeMonth, includeEra }, ViewFormatTranslateParams)}`;
609
844
  }
610
845
  /**
611
846
  * Get a string representation of current view
@@ -628,14 +863,49 @@ let Calendar = class Calendar extends ControlElement {
628
863
  }
629
864
  }
630
865
  /**
631
- * Render cell content template.
632
- * If the cell is selectable (aka has value) add selection part
633
- * @param text Text to render
634
- * @param selectable True if cell may be selected
635
- * @returns template result
866
+ * Set an active state of the cell based
867
+ * @param rows A collection of rows with cells
868
+ * @returns {void}
636
869
  */
637
- renderContentBox(text = '', selectable = false) {
638
- return html `<div part="cell-content${selectable ? ' selection' : ''}">${text}</div>`;
870
+ setActiveCell(rows) {
871
+ const setActive = (cell) => {
872
+ if (cell) {
873
+ cell.active = true;
874
+ }
875
+ };
876
+ const columnIdx = this.activeCellIndex ? this.activeCellIndex[0] : NaN;
877
+ const rowIdx = this.activeCellIndex ? this.activeCellIndex[1] : NaN;
878
+ // Selected cell is active or today cell or first available cell
879
+ let activeCell;
880
+ let nowCell;
881
+ let firstCell;
882
+ let selectedCell;
883
+ for (let i = 0; i < rows.length; i += 1) {
884
+ const row = rows[i];
885
+ for (let e = 0; e < row.length; e += 1) {
886
+ const cell = row[e];
887
+ if (cell.disabled || !cell.value) {
888
+ continue;
889
+ }
890
+ if (i === rowIdx && e === columnIdx) {
891
+ activeCell = cell;
892
+ }
893
+ if (!selectedCell && cell.selected) {
894
+ selectedCell = cell;
895
+ }
896
+ if (cell.now) {
897
+ nowCell = cell;
898
+ }
899
+ if (!firstCell) {
900
+ firstCell = cell;
901
+ }
902
+ }
903
+ }
904
+ // If a cell that was active before last render is not available now, remove index
905
+ if (!activeCell && this.activeCellIndex) {
906
+ this.resetActiveCellIndex(); // set on private to not cause another re-render
907
+ }
908
+ setActive(activeCell || selectedCell || nowCell || firstCell);
639
909
  }
640
910
  /**
641
911
  * Get year view template
@@ -651,18 +921,18 @@ let Calendar = class Calendar extends ControlElement {
651
921
  for (let i = 0; i < YEAR_VIEW.totalCount; i += 1) {
652
922
  if (i % YEAR_VIEW.columnCount === 0) {
653
923
  cells = [];
654
- rows.push({
655
- cells
656
- });
924
+ rows.push(cells);
657
925
  }
658
926
  const year = startIdx + i;
659
927
  const value = utcFormat({ year, month: 0, day: 1 }, DateFormat.yyyyMMdd);
660
- cell = Object.assign({ view, text: year > 0 ? `${year}` : year === 0 ? '1' : `${Math.abs(year - 1)}`, value: `${year}`, now: isThisYear(value) }, this.getCellSelection(value, isSameYear));
928
+ cell = Object.assign({ view, text: year > 0 ? `${year}` : year === 0 ? '1' : `${Math.abs(year - 1)}`, value: `${year}`, now: isThisYear(value), index: [cells.length, rows.length - 1] }, this.getCellSelection(value, isSameYear));
661
929
  cells.push(cell);
662
930
  years.push(cell);
663
931
  }
664
932
  years[0].firstDate = true;
665
933
  years[years.length - 1].lastDate = true;
934
+ this.setActiveCell(rows);
935
+ this.setNavigationMap(rows);
666
936
  return html `${this.renderRows(rows)}`;
667
937
  }
668
938
  /**
@@ -674,7 +944,7 @@ let Calendar = class Calendar extends ControlElement {
674
944
  const columnCount = MONTH_VIEW.columnCount;
675
945
  const monthCount = 12;
676
946
  const totalCount = MONTH_VIEW.totalCount;
677
- const monthsNames = this.monthsNames;
947
+ const monthsNames = this.localMonthsNames;
678
948
  const before = (totalCount - monthCount) / 2;
679
949
  const startIdx = monthCount - before % monthCount;
680
950
  const after = before + monthCount;
@@ -685,21 +955,21 @@ let Calendar = class Calendar extends ControlElement {
685
955
  for (let i = 0; i < totalCount; i += 1) {
686
956
  if (i % columnCount === 0) {
687
957
  cells = [];
688
- rows.push({
689
- cells
690
- });
958
+ rows.push(cells);
691
959
  }
692
960
  const month = (startIdx + i) % monthCount; /* 0 for Jan, 11 for Dev */
693
961
  const year = currentYear + Math.floor((i - before) / monthCount);
694
962
  const segment = { year, month, day: 1 };
695
963
  const value = utcFormat(segment, DateFormat.yyyyMMdd);
696
964
  const idle = i < before || i >= after;
697
- cell = Object.assign({ view, text: monthsNames[month], value: utcFormat(segment, DateFormat.yyyyMM), idle, now: isThisMonth(value) }, this.getCellSelection(value, isSameMonth));
965
+ cell = Object.assign({ view, text: monthsNames[month], value: utcFormat(segment, DateFormat.yyyyMM), idle, now: isThisMonth(value), index: [cells.length, rows.length - 1] }, this.getCellSelection(value, isSameMonth));
698
966
  cells.push(cell);
699
967
  months.push(cell);
700
968
  }
701
969
  months[0].firstDate = true;
702
970
  months[months.length - 1].lastDate = true;
971
+ this.setActiveCell(rows);
972
+ this.setNavigationMap(rows);
703
973
  return html `${this.renderRows(rows)}`;
704
974
  }
705
975
  /**
@@ -722,15 +992,14 @@ let Calendar = class Calendar extends ControlElement {
722
992
  for (let i = 0; i < DAY_VIEW.totalCount; i += 1) {
723
993
  if (i % DAY_VIEW.columnCount === 0) {
724
994
  cells = [];
725
- rows.push({
726
- cells
727
- });
995
+ rows.push(cells);
728
996
  }
729
997
  const datePadding = i - padding + 1;
730
998
  if (datePadding <= 0) {
731
999
  if (!this.fillCells) {
732
1000
  cells.push({
733
- view
1001
+ view,
1002
+ index: [cells.length, rows.length - 1]
734
1003
  });
735
1004
  continue;
736
1005
  }
@@ -741,7 +1010,8 @@ let Calendar = class Calendar extends ControlElement {
741
1010
  else if (datePadding > viewMonth.days) {
742
1011
  if (!this.fillCells) {
743
1012
  cells.push({
744
- view
1013
+ view,
1014
+ index: [cells.length, rows.length - 1]
745
1015
  });
746
1016
  continue;
747
1017
  }
@@ -757,14 +1027,16 @@ let Calendar = class Calendar extends ControlElement {
757
1027
  const value = utcFormat({ year, month, day }, DateFormat.yyyyMMdd);
758
1028
  const disabled = this.isDateAvailable ? !this.isDateAvailable(value) : false;
759
1029
  const dayCell = Object.assign({ view, text: day.toString(), value,
760
- disabled, idle: month !== viewMonth.month || year !== viewMonth.year, now: isToday(value) }, this.getCellSelection(value, isSameDay));
1030
+ disabled, idle: month !== viewMonth.month || year !== viewMonth.year, now: isToday(value), index: [cells.length, rows.length - 1] }, this.getCellSelection(value, isSameDay));
761
1031
  cells.push(dayCell);
762
1032
  days.push(dayCell);
763
1033
  }
764
1034
  days[0].firstDate = true;
765
1035
  days[days.length - 1].lastDate = true;
1036
+ this.setActiveCell(rows);
1037
+ this.setNavigationMap(rows);
766
1038
  return html `
767
- ${this.renderWeekdayNames}
1039
+ ${guard([this.firstDayOfWeek, this.lang], () => this.renderWeekdayNames)}
768
1040
  ${this.renderRows(rows)}
769
1041
  `;
770
1042
  }
@@ -772,23 +1044,50 @@ let Calendar = class Calendar extends ControlElement {
772
1044
  * Get weekday names template
773
1045
  */
774
1046
  get renderWeekdayNames() {
1047
+ const firstDayOfWeek = this.firstDayOfWeek;
1048
+ const weekdaysNames = this.localWeekdaysNames.slice(firstDayOfWeek).concat(this.localWeekdaysNames.slice(0, firstDayOfWeek));
775
1049
  return html `
776
- <div part="row day-name-row">${this.weekdaysNames.map(day => html `<div part="cell day-name">${this.renderContentBox(day)}</div>`)}</div>
777
- `;
1050
+ <div role="row"
1051
+ part="row day-name-row">${weekdaysNames.map(day => html `
1052
+ <div scope="col" role="columnheader" part="cell day-name" abbr="${day.long}">
1053
+ <div part="cell-content">${day.narrow}</div>
1054
+ </div>
1055
+ `)}</div>`;
778
1056
  }
779
1057
  /**
780
1058
  * Render a view based on the current render view
781
1059
  */
782
1060
  get viewRender() {
1061
+ let renderView;
783
1062
  switch (this.renderView) {
784
1063
  case RenderView.MONTH:
785
- return this.monthView;
1064
+ renderView = this.monthView;
1065
+ break;
786
1066
  case RenderView.YEAR:
787
- return this.yearView;
1067
+ renderView = this.yearView;
1068
+ break;
788
1069
  case RenderView.DAY:
789
1070
  default:
790
- return this.dayView;
1071
+ renderView = this.dayView;
1072
+ }
1073
+ return html `${cache(renderView)}`;
1074
+ }
1075
+ /**
1076
+ * Get cell translate label key based on selected state
1077
+ * @param cell Cell
1078
+ * @returns key Translate label key
1079
+ */
1080
+ getCellLabelKey(cell) {
1081
+ if (cell.selected && cell.now) {
1082
+ return 'SELECTED_NOW';
1083
+ }
1084
+ if (cell.selected) {
1085
+ return 'SELECTED';
791
1086
  }
1087
+ if (cell.now) {
1088
+ return 'NOW';
1089
+ }
1090
+ return 'CELL_LABEL';
792
1091
  }
793
1092
  /**
794
1093
  * Render cell template. Cell can be a day, month or year
@@ -796,10 +1095,13 @@ let Calendar = class Calendar extends ControlElement {
796
1095
  * @returns template result
797
1096
  */
798
1097
  renderCell(cell) {
1098
+ const isSelectable = cell.value !== undefined && !cell.disabled;
799
1099
  return html `<div
1100
+ role="gridcell"
800
1101
  part="cell ${cell.view}"
1102
+ aria-selected="${ifDefined(isSelectable ? (cell.selected ? 'true' : 'false') : undefined)}"
1103
+ ?active=${cell.active}
801
1104
  ?disabled=${cell.disabled}
802
- .value=${cell.value}
803
1105
  ?idle=${cell.idle}
804
1106
  ?today=${cell.now}
805
1107
  ?first-date=${cell.firstDate}
@@ -807,9 +1109,18 @@ let Calendar = class Calendar extends ControlElement {
807
1109
  ?selected=${cell.selected}
808
1110
  ?range=${cell.range}
809
1111
  ?range-from=${cell.rangeFrom}
810
- ?range-to=${cell.rangeTo}
811
- tabindex=${ifDefined(cell.value !== undefined && !cell.disabled ? 0 : undefined)}
812
- >${this.renderContentBox(cell.text, cell.value !== undefined)}</div>`;
1112
+ ?range-to=${cell.rangeTo}>
1113
+ <div role="${ifDefined(cell.value ? 'button' : undefined)}"
1114
+ tabindex=${ifDefined(isSelectable ? (cell.active ? 0 : -1) : undefined)}
1115
+ aria-label="${ifDefined(isSelectable && !isIE ? this.t(this.getCellLabelKey(cell), {
1116
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1117
+ value: parse(cell.value),
1118
+ view: this.renderView
1119
+ }) : undefined)}"
1120
+ part="cell-content${isSelectable ? ' selection' : ''}"
1121
+ .value=${cell.value}
1122
+ .index=${cell.index}>${cell.text}</div>
1123
+ </div>`;
813
1124
  }
814
1125
  /**
815
1126
  * Render view rows
@@ -817,32 +1128,80 @@ let Calendar = class Calendar extends ControlElement {
817
1128
  * @returns template result
818
1129
  */
819
1130
  renderRows(rows) {
820
- return rows.map(row => html `<div part="row">${row.cells.map(cell => this.renderCell(cell))}</div>`);
1131
+ return rows.map(row => html `<div role="row" part="row">${row.map(cell => this.renderCell(cell))}</div>`);
821
1132
  }
822
1133
  /**
823
- * A `TemplateResult` that will be used
824
- * to render the updated internal template.
825
- * @return Render template
1134
+ * Render button navigation template
1135
+ * @returns template result
826
1136
  */
827
- render() {
828
- return html `
829
- <div part="navigation">
1137
+ get buttonNavigationTemplate() {
1138
+ let prevBtnAriaLabel = this.t('PREVIOUS_MONTH');
1139
+ let nextBtnAriaLabel = this.t('NEXT_MONTH');
1140
+ let viewBtnAriaLabel = this.t('YEAR_SELECTOR');
1141
+ switch (this.renderView) {
1142
+ case RenderView.YEAR:
1143
+ prevBtnAriaLabel = this.t('PREVIOUS_DECADE');
1144
+ nextBtnAriaLabel = this.t('NEXT_DECADE');
1145
+ viewBtnAriaLabel = this.t('DATE_SELECTOR');
1146
+ break;
1147
+ case RenderView.MONTH:
1148
+ prevBtnAriaLabel = this.t('PREVIOUS_YEAR');
1149
+ nextBtnAriaLabel = this.t('NEXT_YEAR');
1150
+ viewBtnAriaLabel = this.t('DATE_SELECTOR');
1151
+ break;
1152
+ // RenderView.DAY
1153
+ // no default
1154
+ }
1155
+ return html `<div part="navigation">
830
1156
  <ef-button
831
1157
  part="btn-prev"
1158
+ aria-label="${prevBtnAriaLabel}"
832
1159
  icon="left"
833
1160
  @tap=${this.onPreviousTap}></ef-button>
834
1161
  <ef-button
1162
+ ${ref(this.viewBtnRef)}
1163
+ aria-description="${viewBtnAriaLabel}"
835
1164
  part="btn-view"
836
1165
  textpos="before"
837
1166
  .icon="${this.renderView === RenderView.DAY ? 'down' : 'up'}"
838
1167
  @tap="${this.onRenderViewTap}">${this.formattedViewRender}</ef-button>
839
1168
  <ef-button
840
1169
  part="btn-next"
1170
+ aria-label="${nextBtnAriaLabel}"
841
1171
  icon="right"
842
1172
  @tap=${this.onNextTap}></ef-button>
843
- </div>
844
- <div part="table"
845
- @tap=${this.onTableTap}>${this.viewRender}</div>
1173
+ </div>`;
1174
+ }
1175
+ /**
1176
+ * A template used to notify currently selected value for screen readers
1177
+ * @returns template result
1178
+ */
1179
+ get selectionTemplate() {
1180
+ if (isIE || !this.announceValues) { /* IE11 has significant performance complications */
1181
+ return;
1182
+ }
1183
+ return html `<div
1184
+ part="aria-selection"
1185
+ aria-live="polite"
1186
+ aria-label="${this.value
1187
+ ? this.range
1188
+ ? this.t('SELECTED_RANGE', { from: parse(this.values[0]), to: this.values[1] ? parse(this.values[1]) : null })
1189
+ : this.t('SELECTED_DATE', { value: parse(this.value), count: this.values.length })
1190
+ : this.t('SELECTED_NONE', { multiple: this.multiple, range: this.range })}"></div>`;
1191
+ }
1192
+ /**
1193
+ * A `TemplateResult` that will be used
1194
+ * to render the updated internal template.
1195
+ * @return Render template
1196
+ */
1197
+ render() {
1198
+ return html `
1199
+ ${guard([this.values, this.lang, this.range, this.multiple, this.announceValues], () => this.selectionTemplate)}
1200
+ ${guard([this.view, this.renderView, this.lang], () => this.buttonNavigationTemplate)}
1201
+ <div role="grid"
1202
+ aria-multiselectable="${this.range || this.multiple}"
1203
+ part="table"
1204
+ @tap=${this.onTableTap}>${this.viewRender}</div>
846
1205
  <div part="footer"><slot name="footer"></slot></div>
847
1206
  `;
848
1207
  }
@@ -889,15 +1248,24 @@ __decorate([
889
1248
  __decorate([
890
1249
  property({ type: Boolean, attribute: 'fill-cells' })
891
1250
  ], Calendar.prototype, "fillCells", void 0);
1251
+ __decorate([
1252
+ translate({ mode: 'directive', scope: CalendarLocaleScope })
1253
+ ], Calendar.prototype, "dateT", void 0);
1254
+ __decorate([
1255
+ translate({ mode: 'promise', scope: CalendarLocaleScope })
1256
+ ], Calendar.prototype, "dateTPromise", void 0);
892
1257
  __decorate([
893
1258
  translate({ mode: 'directive', scope: 'ef-calendar' })
894
1259
  ], Calendar.prototype, "t", void 0);
895
1260
  __decorate([
896
- translate({ mode: 'promise', scope: 'ef-calendar' })
897
- ], Calendar.prototype, "tPromise", void 0);
1261
+ state()
1262
+ ], Calendar.prototype, "renderView", null);
898
1263
  __decorate([
899
- property({ type: String })
900
- ], Calendar.prototype, "renderView", void 0);
1264
+ state()
1265
+ ], Calendar.prototype, "activeCellIndex", null);
1266
+ __decorate([
1267
+ state()
1268
+ ], Calendar.prototype, "announceValues", void 0);
901
1269
  Calendar = __decorate([
902
1270
  customElement('ef-calendar', {
903
1271
  alias: 'coral-calendar'