@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.
- package/CHANGELOG.md +46 -0
- package/lib/autosuggest/custom-elements.json +14 -4
- package/lib/autosuggest/custom-elements.md +21 -14
- package/lib/autosuggest/index.d.ts +4 -0
- package/lib/autosuggest/index.js +4 -0
- package/lib/calendar/constants.d.ts +4 -0
- package/lib/calendar/constants.js +5 -0
- package/lib/calendar/custom-elements.json +4 -2
- package/lib/calendar/custom-elements.md +2 -2
- package/lib/calendar/index.d.ts +108 -17
- package/lib/calendar/index.js +488 -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/canvas/custom-elements.json +7 -5
- package/lib/canvas/custom-elements.md +8 -8
- package/lib/canvas/index.d.ts +1 -0
- package/lib/canvas/index.js +1 -0
- package/lib/card/custom-elements.json +3 -1
- package/lib/card/custom-elements.md +5 -5
- package/lib/card/index.d.ts +2 -0
- package/lib/card/index.js +2 -0
- package/lib/chart/custom-elements.json +1 -1
- package/lib/chart/custom-elements.md +4 -4
- package/lib/checkbox/custom-elements.json +8 -4
- package/lib/checkbox/custom-elements.md +2 -2
- package/lib/checkbox/index.d.ts +3 -1
- package/lib/checkbox/index.js +2 -0
- package/lib/clock/custom-elements.json +8 -4
- package/lib/clock/custom-elements.md +9 -9
- package/lib/clock/index.d.ts +2 -0
- package/lib/clock/index.js +2 -0
- package/lib/clock/themes/halo/dark/index.js +1 -1
- package/lib/clock/themes/halo/light/index.js +1 -1
- package/lib/clock/themes/solar/charcoal/index.js +1 -1
- package/lib/clock/themes/solar/pearl/index.js +1 -1
- package/lib/color-dialog/custom-elements.json +21 -8
- package/lib/color-dialog/custom-elements.md +22 -22
- package/lib/color-dialog/index.d.ts +8 -8
- package/lib/color-dialog/index.js +8 -8
- package/lib/combo-box/custom-elements.json +19 -10
- package/lib/combo-box/custom-elements.md +20 -20
- package/lib/combo-box/index.d.ts +10 -2
- package/lib/combo-box/index.js +10 -1
- package/lib/combo-box/themes/halo/dark/index.js +1 -1
- package/lib/combo-box/themes/halo/light/index.js +1 -1
- package/lib/combo-box/themes/solar/charcoal/index.js +1 -1
- package/lib/combo-box/themes/solar/pearl/index.js +1 -1
- package/lib/counter/custom-elements.json +8 -4
- package/lib/counter/custom-elements.md +4 -4
- package/lib/counter/index.d.ts +2 -0
- package/lib/counter/index.js +2 -0
- package/lib/datetime-picker/custom-elements.json +48 -19
- package/lib/datetime-picker/custom-elements.md +36 -28
- package/lib/datetime-picker/index.d.ts +15 -4
- package/lib/datetime-picker/index.js +15 -4
- package/lib/dialog/custom-elements.json +30 -8
- package/lib/dialog/custom-elements.md +16 -16
- package/lib/dialog/index.d.ts +7 -10
- package/lib/dialog/index.js +7 -10
- package/lib/email-field/custom-elements.json +80 -93
- package/lib/email-field/custom-elements.md +22 -20
- package/lib/email-field/index.d.ts +43 -115
- package/lib/email-field/index.js +44 -244
- package/lib/flag/custom-elements.md +4 -4
- package/lib/flag/index.d.ts +2 -0
- package/lib/flag/index.js +2 -0
- package/lib/icon/custom-elements.md +4 -4
- package/lib/icon/index.d.ts +2 -0
- package/lib/icon/index.js +2 -0
- package/lib/interactive-chart/custom-elements.json +6 -10
- package/lib/interactive-chart/custom-elements.md +6 -7
- package/lib/interactive-chart/index.d.ts +5 -2
- package/lib/interactive-chart/index.js +5 -2
- package/lib/item/custom-elements.json +8 -6
- package/lib/item/custom-elements.md +14 -14
- package/lib/item/index.d.ts +2 -1
- package/lib/item/index.js +2 -1
- package/lib/led-gauge/custom-elements.json +4 -4
- package/lib/led-gauge/custom-elements.md +2 -2
- package/lib/led-gauge/index.d.ts +1 -0
- package/lib/led-gauge/index.js +1 -0
- package/lib/list/custom-elements.json +18 -5
- package/lib/list/custom-elements.md +12 -10
- package/lib/list/helpers/list-renderer.js +2 -0
- package/lib/list/index.d.ts +19 -2
- package/lib/list/index.js +34 -1
- package/lib/multi-input/custom-elements.json +3 -2
- package/lib/multi-input/custom-elements.md +16 -16
- package/lib/multi-input/index.d.ts +4 -0
- package/lib/multi-input/index.js +4 -0
- package/lib/number-field/custom-elements.json +97 -52
- package/lib/number-field/custom-elements.md +27 -22
- package/lib/number-field/index.d.ts +92 -47
- package/lib/number-field/index.js +113 -80
- package/lib/overlay/custom-elements.json +23 -13
- package/lib/overlay/custom-elements.md +29 -29
- package/lib/overlay/elements/overlay.d.ts +5 -0
- package/lib/overlay-menu/custom-elements.json +66 -14
- package/lib/overlay-menu/custom-elements.md +19 -19
- package/lib/overlay-menu/index.d.ts +13 -11
- package/lib/overlay-menu/index.js +13 -11
- package/lib/password-field/custom-elements.json +62 -67
- package/lib/password-field/custom-elements.md +19 -11
- package/lib/password-field/index.d.ts +42 -94
- package/lib/password-field/index.js +48 -194
- package/lib/pill/custom-elements.json +4 -2
- package/lib/pill/custom-elements.md +1 -1
- package/lib/pill/index.d.ts +1 -1
- package/lib/pill/index.js +1 -1
- package/lib/radio-button/custom-elements.json +8 -6
- package/lib/radio-button/custom-elements.md +3 -3
- package/lib/radio-button/index.d.ts +6 -5
- package/lib/radio-button/index.js +5 -4
- package/lib/search-field/custom-elements.json +70 -74
- package/lib/search-field/custom-elements.md +24 -16
- package/lib/search-field/index.d.ts +43 -100
- package/lib/search-field/index.js +46 -215
- package/lib/select/custom-elements.json +3 -2
- package/lib/select/custom-elements.md +10 -10
- package/lib/select/index.d.ts +11 -3
- package/lib/select/index.js +65 -26
- package/lib/sidebar-layout/custom-elements.json +2 -6
- package/lib/sidebar-layout/custom-elements.md +5 -6
- package/lib/sidebar-layout/index.d.ts +2 -1
- package/lib/slider/custom-elements.json +2 -2
- package/lib/slider/custom-elements.md +1 -1
- package/lib/slider/index.d.ts +1 -1
- package/lib/slider/index.js +1 -1
- package/lib/sparkline/custom-elements.json +4 -4
- package/lib/sparkline/custom-elements.md +2 -2
- package/lib/sparkline/index.d.ts +3 -1
- package/lib/sparkline/index.js +2 -0
- package/lib/swing-gauge/custom-elements.json +5 -3
- package/lib/swing-gauge/custom-elements.md +11 -11
- package/lib/swing-gauge/index.d.ts +3 -1
- package/lib/swing-gauge/index.js +3 -1
- package/lib/text-field/custom-elements.json +76 -87
- package/lib/text-field/custom-elements.md +24 -26
- package/lib/text-field/index.d.ts +50 -92
- package/lib/text-field/index.js +81 -230
- package/lib/time-picker/custom-elements.md +3 -3
- package/lib/time-picker/index.d.ts +3 -0
- package/lib/time-picker/index.js +3 -0
- package/lib/toggle/custom-elements.json +4 -2
- package/lib/toggle/custom-elements.md +1 -1
- package/lib/toggle/index.d.ts +2 -1
- package/lib/toggle/index.js +1 -0
- package/lib/tree/custom-elements.json +2 -1
- package/lib/tree/custom-elements.md +1 -1
- package/lib/tree/elements/tree.d.ts +1 -0
- package/lib/tree/elements/tree.js +1 -0
- package/lib/tree/themes/halo/dark/index.js +1 -1
- package/lib/tree/themes/halo/light/index.js +1 -1
- package/lib/tree/themes/solar/charcoal/index.js +1 -1
- package/lib/tree/themes/solar/pearl/index.js +1 -1
- package/lib/tree-select/custom-elements.json +8 -4
- package/lib/tree-select/custom-elements.md +3 -3
- package/lib/tree-select/index.d.ts +5 -3
- package/lib/tree-select/index.js +3 -2
- package/lib/tree-select/themes/halo/dark/index.js +1 -1
- package/lib/tree-select/themes/halo/light/index.js +1 -1
- package/lib/tree-select/themes/solar/charcoal/index.js +1 -1
- package/lib/tree-select/themes/solar/pearl/index.js +1 -1
- package/lib/version.js +1 -1
- package/package.json +292 -11
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
|
}
|
|
@@ -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
|
-
*
|
|
243
|
-
*
|
|
292
|
+
* Silently reset cell index without calling request update
|
|
293
|
+
* @returns {void}
|
|
244
294
|
*/
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
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
|
|
314
|
+
* Get active date button element
|
|
315
|
+
* @returns button HTML date button element or null
|
|
252
316
|
*/
|
|
253
|
-
get
|
|
254
|
-
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
|
+
}
|
|
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.
|
|
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
|
-
|
|
355
|
+
const locale = getLocale(this);
|
|
356
|
+
this.localMonthsNames = monthsNames(locale);
|
|
273
357
|
}
|
|
274
358
|
if (!this.localWeekdaysNames || changedProperties.has(TranslatePropertyKey)) {
|
|
275
|
-
|
|
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.
|
|
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
|
-
|
|
426
|
-
|
|
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
|
-
|
|
447
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
500
|
-
|
|
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.
|
|
535
|
-
|
|
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.
|
|
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
|
-
*
|
|
632
|
-
*
|
|
633
|
-
* @
|
|
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
|
-
|
|
638
|
-
|
|
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.
|
|
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
|
|
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
|
-
|
|
1064
|
+
renderView = this.monthView;
|
|
1065
|
+
break;
|
|
786
1066
|
case RenderView.YEAR:
|
|
787
|
-
|
|
1067
|
+
renderView = this.yearView;
|
|
1068
|
+
break;
|
|
788
1069
|
case RenderView.DAY:
|
|
789
1070
|
default:
|
|
790
|
-
|
|
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
|
-
|
|
812
|
-
|
|
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.
|
|
1131
|
+
return rows.map(row => html `<div role="row" part="row">${row.map(cell => this.renderCell(cell))}</div>`);
|
|
821
1132
|
}
|
|
822
1133
|
/**
|
|
823
|
-
*
|
|
824
|
-
*
|
|
825
|
-
* @return Render template
|
|
1134
|
+
* Render button navigation template
|
|
1135
|
+
* @returns template result
|
|
826
1136
|
*/
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
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
|
-
|
|
845
|
-
|
|
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
|
-
|
|
897
|
-
], Calendar.prototype, "
|
|
1261
|
+
state()
|
|
1262
|
+
], Calendar.prototype, "renderView", null);
|
|
898
1263
|
__decorate([
|
|
899
|
-
|
|
900
|
-
], Calendar.prototype, "
|
|
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'
|