@vaadin/date-picker 24.2.0-dev.f254716fe → 24.2.0-rc1
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/package.json +16 -12
- package/src/vaadin-date-picker-light.js +4 -2
- package/src/vaadin-date-picker-mixin.js +88 -97
- package/src/vaadin-date-picker-month-scroller.js +9 -20
- package/src/vaadin-date-picker-overlay-content-mixin.js +1032 -0
- package/src/vaadin-date-picker-overlay-content-styles.js +68 -0
- package/src/vaadin-date-picker-overlay-content.js +18 -1014
- package/src/vaadin-date-picker-overlay-styles.js +23 -0
- package/src/vaadin-date-picker-overlay.js +10 -20
- package/src/vaadin-date-picker-styles.js +21 -0
- package/src/vaadin-date-picker-year-scroller.js +9 -21
- package/src/vaadin-date-picker-year.js +3 -1
- package/src/vaadin-date-picker.js +6 -17
- package/src/vaadin-infinite-scroller.js +118 -117
- package/src/vaadin-month-calendar-mixin.js +303 -0
- package/src/vaadin-month-calendar-styles.js +64 -0
- package/src/vaadin-month-calendar.js +30 -320
- package/web-types.json +914 -0
- package/web-types.lit.json +384 -0
|
@@ -5,76 +5,25 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import '@polymer/polymer/lib/elements/dom-repeat.js';
|
|
7
7
|
import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
8
|
+
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
|
|
9
|
+
import { registerStyles, ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
10
|
+
import { dateAllowed, dateEquals } from './vaadin-date-picker-helper.js';
|
|
11
|
+
import { MonthCalendarMixin } from './vaadin-month-calendar-mixin.js';
|
|
12
|
+
import { monthCalendarStyles } from './vaadin-month-calendar-styles.js';
|
|
13
|
+
|
|
14
|
+
registerStyles('vaadin-month-calendar', monthCalendarStyles, {
|
|
15
|
+
moduleId: 'vaadin-month-calendar-styles',
|
|
16
|
+
});
|
|
12
17
|
|
|
13
18
|
/**
|
|
19
|
+
* @customElement
|
|
14
20
|
* @extends HTMLElement
|
|
15
21
|
* @private
|
|
16
22
|
*/
|
|
17
|
-
class MonthCalendar extends
|
|
23
|
+
class MonthCalendar extends MonthCalendarMixin(ThemableMixin(PolymerElement)) {
|
|
18
24
|
static get template() {
|
|
19
25
|
return html`
|
|
20
|
-
<
|
|
21
|
-
:host {
|
|
22
|
-
display: block;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
#monthGrid {
|
|
26
|
-
width: 100%;
|
|
27
|
-
border-collapse: collapse;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
#days-container tr,
|
|
31
|
-
#weekdays-container tr {
|
|
32
|
-
display: flex;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
[part~='date'] {
|
|
36
|
-
outline: none;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
[part~='disabled'] {
|
|
40
|
-
pointer-events: none;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
[part='week-number'][hidden],
|
|
44
|
-
[part='weekday'][hidden] {
|
|
45
|
-
display: none;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
[part='weekday'],
|
|
49
|
-
[part~='date'] {
|
|
50
|
-
width: calc(100% / 7);
|
|
51
|
-
padding: 0;
|
|
52
|
-
font-weight: normal;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
[part='weekday']:empty,
|
|
56
|
-
[part='week-number'] {
|
|
57
|
-
width: 12.5%;
|
|
58
|
-
flex-shrink: 0;
|
|
59
|
-
padding: 0;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
:host([week-numbers]) [part='weekday']:not(:empty),
|
|
63
|
-
:host([week-numbers]) [part~='date'] {
|
|
64
|
-
width: 12.5%;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
@media (forced-colors: active) {
|
|
68
|
-
[part~='date'][part~='focused'] {
|
|
69
|
-
outline: 1px solid;
|
|
70
|
-
}
|
|
71
|
-
[part~='date'][part~='selected'] {
|
|
72
|
-
outline: 3px solid;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
</style>
|
|
76
|
-
|
|
77
|
-
<div part="month-header" id="month-header" aria-hidden="true">[[_getTitle(month, i18n.monthNames)]]</div>
|
|
26
|
+
<div part="month-header" id="month-header" aria-hidden="true">[[_getTitle(month, i18n)]]</div>
|
|
78
27
|
<table
|
|
79
28
|
id="monthGrid"
|
|
80
29
|
role="grid"
|
|
@@ -84,15 +33,8 @@ class MonthCalendar extends FocusMixin(ThemableMixin(PolymerElement)) {
|
|
|
84
33
|
>
|
|
85
34
|
<thead id="weekdays-container">
|
|
86
35
|
<tr role="row" part="weekdays">
|
|
87
|
-
<th
|
|
88
|
-
|
|
89
|
-
aria-hidden="true"
|
|
90
|
-
hidden$="[[!_showWeekSeparator(showWeekNumbers, i18n.firstDayOfWeek)]]"
|
|
91
|
-
></th>
|
|
92
|
-
<template
|
|
93
|
-
is="dom-repeat"
|
|
94
|
-
items="[[_getWeekDayNames(i18n.weekdays, i18n.weekdaysShort, showWeekNumbers, i18n.firstDayOfWeek)]]"
|
|
95
|
-
>
|
|
36
|
+
<th part="weekday" aria-hidden="true" hidden$="[[!_showWeekSeparator(showWeekNumbers, i18n)]]"></th>
|
|
37
|
+
<template is="dom-repeat" items="[[_getWeekDayNames(i18n, showWeekNumbers)]]">
|
|
96
38
|
<th role="columnheader" part="weekday" scope="col" abbr$="[[item.weekDay]]" aria-hidden="true">
|
|
97
39
|
[[item.weekDayShort]]
|
|
98
40
|
</th>
|
|
@@ -102,11 +44,7 @@ class MonthCalendar extends FocusMixin(ThemableMixin(PolymerElement)) {
|
|
|
102
44
|
<tbody id="days-container">
|
|
103
45
|
<template is="dom-repeat" items="[[_weeks]]" as="week">
|
|
104
46
|
<tr role="row">
|
|
105
|
-
<td
|
|
106
|
-
part="week-number"
|
|
107
|
-
aria-hidden="true"
|
|
108
|
-
hidden$="[[!_showWeekSeparator(showWeekNumbers, i18n.firstDayOfWeek)]]"
|
|
109
|
-
>
|
|
47
|
+
<td part="week-number" aria-hidden="true" hidden$="[[!_showWeekSeparator(showWeekNumbers, i18n)]]">
|
|
110
48
|
[[__getWeekNumber(week)]]
|
|
111
49
|
</td>
|
|
112
50
|
<template is="dom-repeat" items="[[week]]">
|
|
@@ -135,65 +73,13 @@ class MonthCalendar extends FocusMixin(ThemableMixin(PolymerElement)) {
|
|
|
135
73
|
|
|
136
74
|
static get properties() {
|
|
137
75
|
return {
|
|
138
|
-
/**
|
|
139
|
-
* A `Date` object defining the month to be displayed. Only year and
|
|
140
|
-
* month properties are actually used.
|
|
141
|
-
*/
|
|
142
|
-
month: {
|
|
143
|
-
type: Date,
|
|
144
|
-
value: new Date(),
|
|
145
|
-
},
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* A `Date` object for the currently selected date.
|
|
149
|
-
*/
|
|
150
|
-
selectedDate: {
|
|
151
|
-
type: Date,
|
|
152
|
-
notify: true,
|
|
153
|
-
},
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* A `Date` object for the currently focused date.
|
|
157
|
-
*/
|
|
158
|
-
focusedDate: Date,
|
|
159
|
-
|
|
160
|
-
showWeekNumbers: {
|
|
161
|
-
type: Boolean,
|
|
162
|
-
value: false,
|
|
163
|
-
},
|
|
164
|
-
|
|
165
|
-
i18n: {
|
|
166
|
-
type: Object,
|
|
167
|
-
},
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Flag stating whether taps on the component should be ignored.
|
|
171
|
-
*/
|
|
172
|
-
ignoreTaps: Boolean,
|
|
173
|
-
|
|
174
|
-
_notTapping: Boolean,
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* The earliest date that can be selected. All earlier dates will be disabled.
|
|
178
|
-
*/
|
|
179
|
-
minDate: {
|
|
180
|
-
type: Date,
|
|
181
|
-
value: null,
|
|
182
|
-
},
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* The latest date that can be selected. All later dates will be disabled.
|
|
186
|
-
*/
|
|
187
|
-
maxDate: {
|
|
188
|
-
type: Date,
|
|
189
|
-
value: null,
|
|
190
|
-
},
|
|
191
|
-
|
|
76
|
+
/** @protected */
|
|
192
77
|
_days: {
|
|
193
78
|
type: Array,
|
|
194
|
-
computed: '_getDays(month, i18n
|
|
79
|
+
computed: '_getDays(month, i18n, minDate, maxDate)',
|
|
195
80
|
},
|
|
196
81
|
|
|
82
|
+
/** @protected */
|
|
197
83
|
_weeks: {
|
|
198
84
|
type: Array,
|
|
199
85
|
computed: '_getWeeks(_days)',
|
|
@@ -208,177 +94,19 @@ class MonthCalendar extends FocusMixin(ThemableMixin(PolymerElement)) {
|
|
|
208
94
|
}
|
|
209
95
|
|
|
210
96
|
static get observers() {
|
|
211
|
-
return [
|
|
212
|
-
'_showWeekNumbersChanged(showWeekNumbers, i18n.firstDayOfWeek)',
|
|
213
|
-
'__focusedDateChanged(focusedDate, _days)',
|
|
214
|
-
];
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
get focusableDateElement() {
|
|
218
|
-
return [...this.shadowRoot.querySelectorAll('[part~=date]')].find((datePart) => {
|
|
219
|
-
return dateEquals(datePart.date, this.focusedDate);
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
/** @protected */
|
|
224
|
-
ready() {
|
|
225
|
-
super.ready();
|
|
226
|
-
addListener(this.$.monthGrid, 'tap', this._handleTap.bind(this));
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
/* Returns true if all the dates in the month are out of the allowed range */
|
|
230
|
-
_isDisabled(month, minDate, maxDate) {
|
|
231
|
-
// First day of the month
|
|
232
|
-
const firstDate = new Date(0, 0);
|
|
233
|
-
firstDate.setFullYear(month.getFullYear());
|
|
234
|
-
firstDate.setMonth(month.getMonth());
|
|
235
|
-
firstDate.setDate(1);
|
|
236
|
-
|
|
237
|
-
// Last day of the month
|
|
238
|
-
const lastDate = new Date(0, 0);
|
|
239
|
-
lastDate.setFullYear(month.getFullYear());
|
|
240
|
-
lastDate.setMonth(month.getMonth() + 1);
|
|
241
|
-
lastDate.setDate(0);
|
|
242
|
-
|
|
243
|
-
if (
|
|
244
|
-
minDate &&
|
|
245
|
-
maxDate &&
|
|
246
|
-
minDate.getMonth() === maxDate.getMonth() &&
|
|
247
|
-
minDate.getMonth() === month.getMonth() &&
|
|
248
|
-
maxDate.getDate() - minDate.getDate() >= 0
|
|
249
|
-
) {
|
|
250
|
-
return false;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
return !dateAllowed(firstDate, minDate, maxDate) && !dateAllowed(lastDate, minDate, maxDate);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
_getTitle(month, monthNames) {
|
|
257
|
-
if (month === undefined || monthNames === undefined) {
|
|
258
|
-
return;
|
|
259
|
-
}
|
|
260
|
-
return this.i18n.formatTitle(monthNames[month.getMonth()], month.getFullYear());
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
_onMonthGridTouchStart() {
|
|
264
|
-
this._notTapping = false;
|
|
265
|
-
setTimeout(() => {
|
|
266
|
-
this._notTapping = true;
|
|
267
|
-
}, 300);
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
_dateAdd(date, delta) {
|
|
271
|
-
date.setDate(date.getDate() + delta);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
_applyFirstDayOfWeek(weekDayNames, firstDayOfWeek) {
|
|
275
|
-
if (weekDayNames === undefined || firstDayOfWeek === undefined) {
|
|
276
|
-
return;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
return weekDayNames.slice(firstDayOfWeek).concat(weekDayNames.slice(0, firstDayOfWeek));
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
_getWeekDayNames(weekDayNames, weekDayNamesShort, showWeekNumbers, firstDayOfWeek) {
|
|
283
|
-
if (
|
|
284
|
-
weekDayNames === undefined ||
|
|
285
|
-
weekDayNamesShort === undefined ||
|
|
286
|
-
showWeekNumbers === undefined ||
|
|
287
|
-
firstDayOfWeek === undefined
|
|
288
|
-
) {
|
|
289
|
-
return;
|
|
290
|
-
}
|
|
291
|
-
weekDayNames = this._applyFirstDayOfWeek(weekDayNames, firstDayOfWeek);
|
|
292
|
-
weekDayNamesShort = this._applyFirstDayOfWeek(weekDayNamesShort, firstDayOfWeek);
|
|
293
|
-
weekDayNames = weekDayNames.map((day, index) => {
|
|
294
|
-
return {
|
|
295
|
-
weekDay: day,
|
|
296
|
-
weekDayShort: weekDayNamesShort[index],
|
|
297
|
-
};
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
return weekDayNames;
|
|
97
|
+
return ['_showWeekNumbersChanged(showWeekNumbers, i18n)'];
|
|
301
98
|
}
|
|
302
99
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
} else {
|
|
307
|
-
this.setAttribute('aria-hidden', 'true');
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
_getDate(date) {
|
|
312
|
-
return date ? date.getDate() : '';
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
_showWeekNumbersChanged(showWeekNumbers, firstDayOfWeek) {
|
|
316
|
-
if (showWeekNumbers && firstDayOfWeek === 1) {
|
|
100
|
+
/** @private */
|
|
101
|
+
_showWeekNumbersChanged(showWeekNumbers, i18n) {
|
|
102
|
+
if (showWeekNumbers && i18n && i18n.firstDayOfWeek === 1) {
|
|
317
103
|
this.setAttribute('week-numbers', '');
|
|
318
104
|
} else {
|
|
319
105
|
this.removeAttribute('week-numbers');
|
|
320
106
|
}
|
|
321
107
|
}
|
|
322
108
|
|
|
323
|
-
|
|
324
|
-
// Currently only supported for locales that start the week on Monday.
|
|
325
|
-
return showWeekNumbers && firstDayOfWeek === 1;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
_isToday(date) {
|
|
329
|
-
return dateEquals(new Date(), date);
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
_getDays(month, firstDayOfWeek) {
|
|
333
|
-
if (month === undefined || firstDayOfWeek === undefined) {
|
|
334
|
-
return;
|
|
335
|
-
}
|
|
336
|
-
// First day of the month (at midnight).
|
|
337
|
-
const date = new Date(0, 0);
|
|
338
|
-
date.setFullYear(month.getFullYear());
|
|
339
|
-
date.setMonth(month.getMonth());
|
|
340
|
-
date.setDate(1);
|
|
341
|
-
|
|
342
|
-
// Rewind to first day of the week.
|
|
343
|
-
while (date.getDay() !== firstDayOfWeek) {
|
|
344
|
-
this._dateAdd(date, -1);
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
const days = [];
|
|
348
|
-
const startMonth = date.getMonth();
|
|
349
|
-
const targetMonth = month.getMonth();
|
|
350
|
-
while (date.getMonth() === targetMonth || date.getMonth() === startMonth) {
|
|
351
|
-
days.push(date.getMonth() === targetMonth ? new Date(date.getTime()) : null);
|
|
352
|
-
|
|
353
|
-
// Advance to next day.
|
|
354
|
-
this._dateAdd(date, 1);
|
|
355
|
-
}
|
|
356
|
-
return days;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
_getWeeks(days) {
|
|
360
|
-
return days.reduce((acc, day, i) => {
|
|
361
|
-
if (i % 7 === 0) {
|
|
362
|
-
acc.push([]);
|
|
363
|
-
}
|
|
364
|
-
acc[acc.length - 1].push(day);
|
|
365
|
-
return acc;
|
|
366
|
-
}, []);
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
_handleTap(e) {
|
|
370
|
-
if (!this.ignoreTaps && !this._notTapping && e.target.date && !e.target.hasAttribute('disabled')) {
|
|
371
|
-
this.selectedDate = e.target.date;
|
|
372
|
-
this.dispatchEvent(
|
|
373
|
-
new CustomEvent('date-tap', { detail: { date: e.target.date }, bubbles: true, composed: true }),
|
|
374
|
-
);
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
_preventDefault(e) {
|
|
379
|
-
e.preventDefault();
|
|
380
|
-
}
|
|
381
|
-
|
|
109
|
+
/** @private */
|
|
382
110
|
__getDatePart(date, focusedDate, selectedDate, minDate, maxDate) {
|
|
383
111
|
const result = ['date'];
|
|
384
112
|
|
|
@@ -401,32 +129,29 @@ class MonthCalendar extends FocusMixin(ThemableMixin(PolymerElement)) {
|
|
|
401
129
|
return result.join(' ');
|
|
402
130
|
}
|
|
403
131
|
|
|
404
|
-
|
|
405
|
-
const date = days.reduce((acc, d) => {
|
|
406
|
-
return !acc && d ? d : acc;
|
|
407
|
-
});
|
|
408
|
-
|
|
409
|
-
return getISOWeekNumber(date);
|
|
410
|
-
}
|
|
411
|
-
|
|
132
|
+
/** @private */
|
|
412
133
|
__isDayFocused(date, focusedDate) {
|
|
413
134
|
return dateEquals(date, focusedDate);
|
|
414
135
|
}
|
|
415
136
|
|
|
137
|
+
/** @private */
|
|
416
138
|
__isDaySelected(date, selectedDate) {
|
|
417
139
|
return dateEquals(date, selectedDate);
|
|
418
140
|
}
|
|
419
141
|
|
|
142
|
+
/** @private */
|
|
420
143
|
__getDayAriaSelected(date, selectedDate) {
|
|
421
144
|
if (this.__isDaySelected(date, selectedDate)) {
|
|
422
145
|
return 'true';
|
|
423
146
|
}
|
|
424
147
|
}
|
|
425
148
|
|
|
149
|
+
/** @private */
|
|
426
150
|
__isDayDisabled(date, minDate, maxDate) {
|
|
427
151
|
return !dateAllowed(date, minDate, maxDate);
|
|
428
152
|
}
|
|
429
153
|
|
|
154
|
+
/** @private */
|
|
430
155
|
__getDayAriaDisabled(date, min, max) {
|
|
431
156
|
if (date === undefined || min === undefined || max === undefined) {
|
|
432
157
|
return;
|
|
@@ -437,22 +162,7 @@ class MonthCalendar extends FocusMixin(ThemableMixin(PolymerElement)) {
|
|
|
437
162
|
}
|
|
438
163
|
}
|
|
439
164
|
|
|
440
|
-
|
|
441
|
-
if (!date) {
|
|
442
|
-
return '';
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
let ariaLabel = `${this._getDate(date)} ${this.i18n.monthNames[date.getMonth()]} ${date.getFullYear()}, ${
|
|
446
|
-
this.i18n.weekdays[date.getDay()]
|
|
447
|
-
}`;
|
|
448
|
-
|
|
449
|
-
if (this._isToday(date)) {
|
|
450
|
-
ariaLabel += `, ${this.i18n.today}`;
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
return ariaLabel;
|
|
454
|
-
}
|
|
455
|
-
|
|
165
|
+
/** @private */
|
|
456
166
|
__getDayTabindex(date, focusedDate) {
|
|
457
167
|
if (this.__isDayFocused(date, focusedDate)) {
|
|
458
168
|
return '0';
|
|
@@ -462,4 +172,4 @@ class MonthCalendar extends FocusMixin(ThemableMixin(PolymerElement)) {
|
|
|
462
172
|
}
|
|
463
173
|
}
|
|
464
174
|
|
|
465
|
-
|
|
175
|
+
defineCustomElement(MonthCalendar);
|