@refinitiv-ui/elements 5.8.1 → 5.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -1
- package/lib/calendar/constants.d.ts +4 -0
- package/lib/calendar/constants.js +5 -0
- package/lib/calendar/index.d.ts +106 -17
- package/lib/calendar/index.js +486 -120
- package/lib/calendar/locales.js +2 -1
- package/lib/calendar/themes/halo/dark/index.js +1 -1
- package/lib/calendar/themes/halo/light/index.js +1 -1
- package/lib/calendar/themes/solar/charcoal/index.js +1 -1
- package/lib/calendar/themes/solar/pearl/index.js +1 -1
- package/lib/calendar/types.d.ts +11 -8
- package/lib/calendar/utils.js +2 -1
- package/lib/combo-box/custom-elements.json +23 -1
- package/lib/combo-box/custom-elements.md +8 -1
- package/lib/combo-box/helpers/renderer.d.ts +8 -0
- package/lib/combo-box/helpers/renderer.js +24 -0
- package/lib/combo-box/index.d.ts +36 -16
- package/lib/combo-box/index.js +60 -32
- package/lib/combo-box/themes/halo/dark/index.js +1 -2
- package/lib/combo-box/themes/halo/light/index.js +1 -2
- package/lib/combo-box/themes/solar/charcoal/index.js +1 -2
- package/lib/combo-box/themes/solar/pearl/index.js +1 -2
- package/lib/time-picker/custom-elements.json +2 -4
- package/lib/time-picker/custom-elements.md +3 -3
- package/lib/time-picker/index.d.ts +92 -62
- package/lib/time-picker/index.js +278 -158
- package/lib/tree-select/themes/halo/dark/index.js +1 -2
- package/lib/tree-select/themes/halo/light/index.js +1 -2
- package/lib/tree-select/themes/solar/charcoal/index.js +1 -2
- package/lib/tree-select/themes/solar/pearl/index.js +1 -2
- package/lib/version.js +1 -1
- package/package.json +291 -10
package/lib/calendar/index.js
CHANGED
|
@@ -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.
|
|
66
|
-
|
|
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
|
|
109
|
+
[part~=navigation], [part~=navigation] section {
|
|
87
110
|
display: flex;
|
|
88
111
|
flex-flow: row nowrap;
|
|
89
112
|
}
|
|
90
|
-
[part
|
|
113
|
+
[part~=navigation] {
|
|
91
114
|
justify-content: space-between;
|
|
92
115
|
}
|
|
93
|
-
[part
|
|
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
|
}
|
|
@@ -240,27 +266,82 @@ let Calendar = class Calendar extends ControlElement {
|
|
|
240
266
|
get values() {
|
|
241
267
|
return this._values.concat();
|
|
242
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
|
+
}
|
|
243
291
|
/**
|
|
244
|
-
*
|
|
245
|
-
*
|
|
292
|
+
* Silently reset cell index without calling request update
|
|
293
|
+
* @returns {void}
|
|
246
294
|
*/
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
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));
|
|
251
312
|
}
|
|
252
313
|
/**
|
|
253
|
-
* Get
|
|
314
|
+
* Get active date button element
|
|
315
|
+
* @returns button HTML date button element or null
|
|
254
316
|
*/
|
|
255
|
-
get
|
|
256
|
-
return this.
|
|
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
|
+
}
|
|
257
338
|
}
|
|
258
339
|
/**
|
|
259
340
|
* Perform asynchronous update
|
|
260
341
|
* @returns promise
|
|
261
342
|
*/
|
|
262
343
|
async performUpdate() {
|
|
263
|
-
const localFirstDayOfWeek = Number(await this.
|
|
344
|
+
const localFirstDayOfWeek = Number(await this.dateTPromise('FIRST_DAY_OF_WEEK'));
|
|
264
345
|
this.localFirstDayOfWeek = isNaN(localFirstDayOfWeek) ? FIRST_DAY_OF_WEEK : (localFirstDayOfWeek % 7);
|
|
265
346
|
void super.performUpdate();
|
|
266
347
|
}
|
|
@@ -271,14 +352,39 @@ let Calendar = class Calendar extends ControlElement {
|
|
|
271
352
|
*/
|
|
272
353
|
update(changedProperties) {
|
|
273
354
|
if (!this.localMonthsNames || changedProperties.has(TranslatePropertyKey)) {
|
|
274
|
-
|
|
355
|
+
const locale = getLocale(this);
|
|
356
|
+
this.localMonthsNames = monthsNames(locale);
|
|
275
357
|
}
|
|
276
358
|
if (!this.localWeekdaysNames || changedProperties.has(TranslatePropertyKey)) {
|
|
277
|
-
|
|
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
|
+
});
|
|
278
364
|
}
|
|
279
365
|
this.shouldConstructFilters(changedProperties) && this.constructFilters();
|
|
280
366
|
super.update(changedProperties);
|
|
281
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
|
+
}
|
|
282
388
|
/**
|
|
283
389
|
* Run when an element has been first updated
|
|
284
390
|
* @param changedProperties properties that was changed on first update
|
|
@@ -286,7 +392,7 @@ let Calendar = class Calendar extends ControlElement {
|
|
|
286
392
|
*/
|
|
287
393
|
firstUpdated(changedProperties) {
|
|
288
394
|
super.firstUpdated(changedProperties);
|
|
289
|
-
this.renderRoot.addEventListener('keydown', event => this.
|
|
395
|
+
this.renderRoot.addEventListener('keydown', event => this.onKeyDown(event));
|
|
290
396
|
}
|
|
291
397
|
/**
|
|
292
398
|
* Show invalid view message
|
|
@@ -418,78 +524,88 @@ let Calendar = class Calendar extends ControlElement {
|
|
|
418
524
|
rangeTo
|
|
419
525
|
};
|
|
420
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
|
+
}
|
|
421
535
|
/**
|
|
422
536
|
* Run when next button is tapped.
|
|
423
537
|
* Change current view to next view
|
|
538
|
+
* @param event Next view tap event
|
|
424
539
|
* @returns {void}
|
|
425
540
|
*/
|
|
426
|
-
onNextTap() {
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
case RenderView.DAY:
|
|
430
|
-
viewSegment = toDateSegment(addMonths(this.view, 1));
|
|
431
|
-
break;
|
|
432
|
-
case RenderView.MONTH:
|
|
433
|
-
viewSegment.year += 1;
|
|
434
|
-
break;
|
|
435
|
-
case RenderView.YEAR:
|
|
436
|
-
viewSegment.year += YEARS_PER_YEAR_VIEW;
|
|
437
|
-
break;
|
|
438
|
-
// no default
|
|
541
|
+
onNextTap(event) {
|
|
542
|
+
if (!event.defaultPrevented) {
|
|
543
|
+
this.toNextView();
|
|
439
544
|
}
|
|
440
|
-
this.notifyViewChange(viewSegment);
|
|
441
545
|
}
|
|
442
546
|
/**
|
|
443
547
|
* Run when previous button is tapped.
|
|
444
548
|
* Change current view to previous view
|
|
549
|
+
* @param event Previous view tap event
|
|
445
550
|
* @returns {void}
|
|
446
551
|
*/
|
|
447
|
-
onPreviousTap() {
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
case RenderView.DAY:
|
|
451
|
-
viewSegment = toDateSegment(subMonths(this.view, 1));
|
|
452
|
-
break;
|
|
453
|
-
case RenderView.MONTH:
|
|
454
|
-
viewSegment.year -= 1;
|
|
455
|
-
break;
|
|
456
|
-
case RenderView.YEAR:
|
|
457
|
-
viewSegment.year -= YEARS_PER_YEAR_VIEW;
|
|
458
|
-
break;
|
|
459
|
-
// no default
|
|
552
|
+
onPreviousTap(event) {
|
|
553
|
+
if (!event.defaultPrevented) {
|
|
554
|
+
this.toPreviousView();
|
|
460
555
|
}
|
|
461
|
-
this.notifyViewChange(viewSegment);
|
|
462
556
|
}
|
|
463
557
|
/**
|
|
464
558
|
* Run when change view button is tapped.
|
|
465
559
|
* Switch between views
|
|
560
|
+
* @param event Render view tap event
|
|
466
561
|
* @returns {void}
|
|
467
562
|
*/
|
|
468
|
-
onRenderViewTap() {
|
|
469
|
-
|
|
563
|
+
onRenderViewTap(event) {
|
|
564
|
+
if (!event.defaultPrevented) {
|
|
565
|
+
this.renderView = this.renderView === RenderView.DAY ? RenderView.YEAR : RenderView.DAY;
|
|
566
|
+
}
|
|
470
567
|
}
|
|
471
568
|
/**
|
|
472
569
|
* Run when key down event happens on calendar
|
|
473
570
|
* @param event Keyboard event
|
|
474
571
|
* @returns {void}
|
|
475
572
|
*/
|
|
476
|
-
|
|
573
|
+
onKeyDown(event) {
|
|
574
|
+
if (event.defaultPrevented) {
|
|
575
|
+
return;
|
|
576
|
+
}
|
|
477
577
|
switch (event.key) {
|
|
478
|
-
case ' ':
|
|
479
|
-
case 'Enter':
|
|
480
|
-
case 'Spacebar':
|
|
481
|
-
event.preventDefault();
|
|
482
|
-
this.onTableTap(event);
|
|
483
|
-
break;
|
|
484
578
|
case 'Esc':
|
|
485
579
|
case 'Escape':
|
|
486
580
|
if (this.renderView === RenderView.YEAR || this.renderView === RenderView.MONTH) {
|
|
487
|
-
event.preventDefault();
|
|
488
581
|
this.renderView = RenderView.DAY;
|
|
582
|
+
break;
|
|
489
583
|
}
|
|
584
|
+
return;
|
|
585
|
+
case 'Up': // IE11
|
|
586
|
+
case 'ArrowUp':
|
|
587
|
+
void this.onNavigation('ArrowUp');
|
|
490
588
|
break;
|
|
491
|
-
|
|
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;
|
|
492
607
|
}
|
|
608
|
+
event.preventDefault();
|
|
493
609
|
}
|
|
494
610
|
/**
|
|
495
611
|
* Run when tap event happens ot table.
|
|
@@ -498,10 +614,14 @@ let Calendar = class Calendar extends ControlElement {
|
|
|
498
614
|
* @returns {void}
|
|
499
615
|
*/
|
|
500
616
|
onTableTap(event) {
|
|
501
|
-
|
|
502
|
-
|
|
617
|
+
if (event.defaultPrevented) {
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
const cell = event.target;
|
|
621
|
+
if (!cell || !this.isDateButton(cell) || !cell.value) {
|
|
503
622
|
return;
|
|
504
623
|
}
|
|
624
|
+
this.activeCellIndex = cell.index;
|
|
505
625
|
const cellSegment = toDateSegment(cell.value);
|
|
506
626
|
const viewSegment = toDateSegment(this.view);
|
|
507
627
|
if (this.renderView === RenderView.YEAR) { /* YEAR -> MONTH */
|
|
@@ -521,6 +641,117 @@ let Calendar = class Calendar extends ControlElement {
|
|
|
521
641
|
}
|
|
522
642
|
this.onTapSelectValue(cell.value);
|
|
523
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
|
+
}
|
|
524
755
|
/**
|
|
525
756
|
* Run when tap event happened on DAY view and the cell has the values
|
|
526
757
|
* Try to select/deselect cell value
|
|
@@ -533,12 +764,14 @@ let Calendar = class Calendar extends ControlElement {
|
|
|
533
764
|
}
|
|
534
765
|
let values;
|
|
535
766
|
if (this.multiple) {
|
|
536
|
-
values = this.values.
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
if (this.values.length === values.length) {
|
|
767
|
+
values = this.values.concat([]);
|
|
768
|
+
const valueIdx = this.values.indexOf(value);
|
|
769
|
+
if (valueIdx === -1) {
|
|
540
770
|
values.push(value);
|
|
541
771
|
}
|
|
772
|
+
else {
|
|
773
|
+
values.splice(valueIdx, 1);
|
|
774
|
+
}
|
|
542
775
|
}
|
|
543
776
|
else if (this.range) {
|
|
544
777
|
if (!this.values.length) {
|
|
@@ -554,12 +787,16 @@ let Calendar = class Calendar extends ControlElement {
|
|
|
554
787
|
values = [value];
|
|
555
788
|
}
|
|
556
789
|
}
|
|
557
|
-
else {
|
|
790
|
+
else if (this.values.indexOf(value) === -1) {
|
|
558
791
|
values = [value];
|
|
559
792
|
}
|
|
793
|
+
else {
|
|
794
|
+
// remove range if start/end index match
|
|
795
|
+
values = [];
|
|
796
|
+
}
|
|
560
797
|
}
|
|
561
798
|
else {
|
|
562
|
-
values = [value];
|
|
799
|
+
values = this.value === value ? [] : [value];
|
|
563
800
|
}
|
|
564
801
|
this.notifyValuesChange(values);
|
|
565
802
|
}
|
|
@@ -603,11 +840,7 @@ let Calendar = class Calendar extends ControlElement {
|
|
|
603
840
|
if (isIE && isBC) {
|
|
604
841
|
return html `${formatLocaleDate(date, getLocale(this), includeMonth, includeEra)}`;
|
|
605
842
|
}
|
|
606
|
-
return html `${this.
|
|
607
|
-
date,
|
|
608
|
-
includeMonth,
|
|
609
|
-
includeEra
|
|
610
|
-
}, ViewFormatTranslateParams)}`;
|
|
843
|
+
return html `${this.dateT('VIEW_FORMAT', { date, includeMonth, includeEra }, ViewFormatTranslateParams)}`;
|
|
611
844
|
}
|
|
612
845
|
/**
|
|
613
846
|
* Get a string representation of current view
|
|
@@ -630,14 +863,49 @@ let Calendar = class Calendar extends ControlElement {
|
|
|
630
863
|
}
|
|
631
864
|
}
|
|
632
865
|
/**
|
|
633
|
-
*
|
|
634
|
-
*
|
|
635
|
-
* @
|
|
636
|
-
* @param selectable True if cell may be selected
|
|
637
|
-
* @returns template result
|
|
866
|
+
* Set an active state of the cell based
|
|
867
|
+
* @param rows A collection of rows with cells
|
|
868
|
+
* @returns {void}
|
|
638
869
|
*/
|
|
639
|
-
|
|
640
|
-
|
|
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);
|
|
641
909
|
}
|
|
642
910
|
/**
|
|
643
911
|
* Get year view template
|
|
@@ -653,18 +921,18 @@ let Calendar = class Calendar extends ControlElement {
|
|
|
653
921
|
for (let i = 0; i < YEAR_VIEW.totalCount; i += 1) {
|
|
654
922
|
if (i % YEAR_VIEW.columnCount === 0) {
|
|
655
923
|
cells = [];
|
|
656
|
-
rows.push(
|
|
657
|
-
cells
|
|
658
|
-
});
|
|
924
|
+
rows.push(cells);
|
|
659
925
|
}
|
|
660
926
|
const year = startIdx + i;
|
|
661
927
|
const value = utcFormat({ year, month: 0, day: 1 }, DateFormat.yyyyMMdd);
|
|
662
|
-
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));
|
|
663
929
|
cells.push(cell);
|
|
664
930
|
years.push(cell);
|
|
665
931
|
}
|
|
666
932
|
years[0].firstDate = true;
|
|
667
933
|
years[years.length - 1].lastDate = true;
|
|
934
|
+
this.setActiveCell(rows);
|
|
935
|
+
this.setNavigationMap(rows);
|
|
668
936
|
return html `${this.renderRows(rows)}`;
|
|
669
937
|
}
|
|
670
938
|
/**
|
|
@@ -676,7 +944,7 @@ let Calendar = class Calendar extends ControlElement {
|
|
|
676
944
|
const columnCount = MONTH_VIEW.columnCount;
|
|
677
945
|
const monthCount = 12;
|
|
678
946
|
const totalCount = MONTH_VIEW.totalCount;
|
|
679
|
-
const monthsNames = this.
|
|
947
|
+
const monthsNames = this.localMonthsNames;
|
|
680
948
|
const before = (totalCount - monthCount) / 2;
|
|
681
949
|
const startIdx = monthCount - before % monthCount;
|
|
682
950
|
const after = before + monthCount;
|
|
@@ -687,21 +955,21 @@ let Calendar = class Calendar extends ControlElement {
|
|
|
687
955
|
for (let i = 0; i < totalCount; i += 1) {
|
|
688
956
|
if (i % columnCount === 0) {
|
|
689
957
|
cells = [];
|
|
690
|
-
rows.push(
|
|
691
|
-
cells
|
|
692
|
-
});
|
|
958
|
+
rows.push(cells);
|
|
693
959
|
}
|
|
694
960
|
const month = (startIdx + i) % monthCount; /* 0 for Jan, 11 for Dev */
|
|
695
961
|
const year = currentYear + Math.floor((i - before) / monthCount);
|
|
696
962
|
const segment = { year, month, day: 1 };
|
|
697
963
|
const value = utcFormat(segment, DateFormat.yyyyMMdd);
|
|
698
964
|
const idle = i < before || i >= after;
|
|
699
|
-
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));
|
|
700
966
|
cells.push(cell);
|
|
701
967
|
months.push(cell);
|
|
702
968
|
}
|
|
703
969
|
months[0].firstDate = true;
|
|
704
970
|
months[months.length - 1].lastDate = true;
|
|
971
|
+
this.setActiveCell(rows);
|
|
972
|
+
this.setNavigationMap(rows);
|
|
705
973
|
return html `${this.renderRows(rows)}`;
|
|
706
974
|
}
|
|
707
975
|
/**
|
|
@@ -724,15 +992,14 @@ let Calendar = class Calendar extends ControlElement {
|
|
|
724
992
|
for (let i = 0; i < DAY_VIEW.totalCount; i += 1) {
|
|
725
993
|
if (i % DAY_VIEW.columnCount === 0) {
|
|
726
994
|
cells = [];
|
|
727
|
-
rows.push(
|
|
728
|
-
cells
|
|
729
|
-
});
|
|
995
|
+
rows.push(cells);
|
|
730
996
|
}
|
|
731
997
|
const datePadding = i - padding + 1;
|
|
732
998
|
if (datePadding <= 0) {
|
|
733
999
|
if (!this.fillCells) {
|
|
734
1000
|
cells.push({
|
|
735
|
-
view
|
|
1001
|
+
view,
|
|
1002
|
+
index: [cells.length, rows.length - 1]
|
|
736
1003
|
});
|
|
737
1004
|
continue;
|
|
738
1005
|
}
|
|
@@ -743,7 +1010,8 @@ let Calendar = class Calendar extends ControlElement {
|
|
|
743
1010
|
else if (datePadding > viewMonth.days) {
|
|
744
1011
|
if (!this.fillCells) {
|
|
745
1012
|
cells.push({
|
|
746
|
-
view
|
|
1013
|
+
view,
|
|
1014
|
+
index: [cells.length, rows.length - 1]
|
|
747
1015
|
});
|
|
748
1016
|
continue;
|
|
749
1017
|
}
|
|
@@ -759,14 +1027,16 @@ let Calendar = class Calendar extends ControlElement {
|
|
|
759
1027
|
const value = utcFormat({ year, month, day }, DateFormat.yyyyMMdd);
|
|
760
1028
|
const disabled = this.isDateAvailable ? !this.isDateAvailable(value) : false;
|
|
761
1029
|
const dayCell = Object.assign({ view, text: day.toString(), value,
|
|
762
|
-
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));
|
|
763
1031
|
cells.push(dayCell);
|
|
764
1032
|
days.push(dayCell);
|
|
765
1033
|
}
|
|
766
1034
|
days[0].firstDate = true;
|
|
767
1035
|
days[days.length - 1].lastDate = true;
|
|
1036
|
+
this.setActiveCell(rows);
|
|
1037
|
+
this.setNavigationMap(rows);
|
|
768
1038
|
return html `
|
|
769
|
-
${this.renderWeekdayNames}
|
|
1039
|
+
${guard([this.firstDayOfWeek, this.lang], () => this.renderWeekdayNames)}
|
|
770
1040
|
${this.renderRows(rows)}
|
|
771
1041
|
`;
|
|
772
1042
|
}
|
|
@@ -774,23 +1044,50 @@ let Calendar = class Calendar extends ControlElement {
|
|
|
774
1044
|
* Get weekday names template
|
|
775
1045
|
*/
|
|
776
1046
|
get renderWeekdayNames() {
|
|
1047
|
+
const firstDayOfWeek = this.firstDayOfWeek;
|
|
1048
|
+
const weekdaysNames = this.localWeekdaysNames.slice(firstDayOfWeek).concat(this.localWeekdaysNames.slice(0, firstDayOfWeek));
|
|
777
1049
|
return html `
|
|
778
|
-
<div
|
|
779
|
-
|
|
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>`;
|
|
780
1056
|
}
|
|
781
1057
|
/**
|
|
782
1058
|
* Render a view based on the current render view
|
|
783
1059
|
*/
|
|
784
1060
|
get viewRender() {
|
|
1061
|
+
let renderView;
|
|
785
1062
|
switch (this.renderView) {
|
|
786
1063
|
case RenderView.MONTH:
|
|
787
|
-
|
|
1064
|
+
renderView = this.monthView;
|
|
1065
|
+
break;
|
|
788
1066
|
case RenderView.YEAR:
|
|
789
|
-
|
|
1067
|
+
renderView = this.yearView;
|
|
1068
|
+
break;
|
|
790
1069
|
case RenderView.DAY:
|
|
791
1070
|
default:
|
|
792
|
-
|
|
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';
|
|
793
1086
|
}
|
|
1087
|
+
if (cell.now) {
|
|
1088
|
+
return 'NOW';
|
|
1089
|
+
}
|
|
1090
|
+
return 'CELL_LABEL';
|
|
794
1091
|
}
|
|
795
1092
|
/**
|
|
796
1093
|
* Render cell template. Cell can be a day, month or year
|
|
@@ -798,10 +1095,13 @@ let Calendar = class Calendar extends ControlElement {
|
|
|
798
1095
|
* @returns template result
|
|
799
1096
|
*/
|
|
800
1097
|
renderCell(cell) {
|
|
1098
|
+
const isSelectable = cell.value !== undefined && !cell.disabled;
|
|
801
1099
|
return html `<div
|
|
1100
|
+
role="gridcell"
|
|
802
1101
|
part="cell ${cell.view}"
|
|
1102
|
+
aria-selected="${ifDefined(isSelectable ? (cell.selected ? 'true' : 'false') : undefined)}"
|
|
1103
|
+
?active=${cell.active}
|
|
803
1104
|
?disabled=${cell.disabled}
|
|
804
|
-
.value=${cell.value}
|
|
805
1105
|
?idle=${cell.idle}
|
|
806
1106
|
?today=${cell.now}
|
|
807
1107
|
?first-date=${cell.firstDate}
|
|
@@ -809,9 +1109,18 @@ let Calendar = class Calendar extends ControlElement {
|
|
|
809
1109
|
?selected=${cell.selected}
|
|
810
1110
|
?range=${cell.range}
|
|
811
1111
|
?range-from=${cell.rangeFrom}
|
|
812
|
-
?range-to=${cell.rangeTo}
|
|
813
|
-
|
|
814
|
-
|
|
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>`;
|
|
815
1124
|
}
|
|
816
1125
|
/**
|
|
817
1126
|
* Render view rows
|
|
@@ -819,32 +1128,80 @@ let Calendar = class Calendar extends ControlElement {
|
|
|
819
1128
|
* @returns template result
|
|
820
1129
|
*/
|
|
821
1130
|
renderRows(rows) {
|
|
822
|
-
return rows.map(row => html `<div part="row">${row.
|
|
1131
|
+
return rows.map(row => html `<div role="row" part="row">${row.map(cell => this.renderCell(cell))}</div>`);
|
|
823
1132
|
}
|
|
824
1133
|
/**
|
|
825
|
-
*
|
|
826
|
-
*
|
|
827
|
-
* @return Render template
|
|
1134
|
+
* Render button navigation template
|
|
1135
|
+
* @returns template result
|
|
828
1136
|
*/
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
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">
|
|
832
1156
|
<ef-button
|
|
833
1157
|
part="btn-prev"
|
|
1158
|
+
aria-label="${prevBtnAriaLabel}"
|
|
834
1159
|
icon="left"
|
|
835
1160
|
@tap=${this.onPreviousTap}></ef-button>
|
|
836
1161
|
<ef-button
|
|
1162
|
+
${ref(this.viewBtnRef)}
|
|
1163
|
+
aria-description="${viewBtnAriaLabel}"
|
|
837
1164
|
part="btn-view"
|
|
838
1165
|
textpos="before"
|
|
839
1166
|
.icon="${this.renderView === RenderView.DAY ? 'down' : 'up'}"
|
|
840
1167
|
@tap="${this.onRenderViewTap}">${this.formattedViewRender}</ef-button>
|
|
841
1168
|
<ef-button
|
|
842
1169
|
part="btn-next"
|
|
1170
|
+
aria-label="${nextBtnAriaLabel}"
|
|
843
1171
|
icon="right"
|
|
844
1172
|
@tap=${this.onNextTap}></ef-button>
|
|
845
|
-
</div
|
|
846
|
-
|
|
847
|
-
|
|
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>
|
|
848
1205
|
<div part="footer"><slot name="footer"></slot></div>
|
|
849
1206
|
`;
|
|
850
1207
|
}
|
|
@@ -891,15 +1248,24 @@ __decorate([
|
|
|
891
1248
|
__decorate([
|
|
892
1249
|
property({ type: Boolean, attribute: 'fill-cells' })
|
|
893
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);
|
|
894
1257
|
__decorate([
|
|
895
1258
|
translate({ mode: 'directive', scope: 'ef-calendar' })
|
|
896
1259
|
], Calendar.prototype, "t", void 0);
|
|
897
1260
|
__decorate([
|
|
898
|
-
|
|
899
|
-
], Calendar.prototype, "
|
|
1261
|
+
state()
|
|
1262
|
+
], Calendar.prototype, "renderView", null);
|
|
900
1263
|
__decorate([
|
|
901
|
-
|
|
902
|
-
], Calendar.prototype, "
|
|
1264
|
+
state()
|
|
1265
|
+
], Calendar.prototype, "activeCellIndex", null);
|
|
1266
|
+
__decorate([
|
|
1267
|
+
state()
|
|
1268
|
+
], Calendar.prototype, "announceValues", void 0);
|
|
903
1269
|
Calendar = __decorate([
|
|
904
1270
|
customElement('ef-calendar', {
|
|
905
1271
|
alias: 'coral-calendar'
|