@vaadin/date-picker 24.2.0-dev.f254716fe → 24.3.0-alpha2
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 +112 -130
- 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/theme/lumo/vaadin-date-picker-styles.js +1 -0
- package/theme/lumo/vaadin-date-picker.js +0 -1
- package/theme/material/vaadin-date-picker-styles.js +1 -0
- package/theme/material/vaadin-date-picker.js +0 -1
- package/web-types.json +914 -0
- package/web-types.lit.json +384 -0
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2016 - 2023 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { FocusMixin } from '@vaadin/a11y-base/src/focus-mixin.js';
|
|
7
|
+
import { addListener } from '@vaadin/component-base/src/gestures.js';
|
|
8
|
+
import { dateAllowed, dateEquals, getISOWeekNumber } from './vaadin-date-picker-helper.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @polymerMixin
|
|
12
|
+
* @mixes FocusMixin
|
|
13
|
+
*/
|
|
14
|
+
export const MonthCalendarMixin = (superClass) =>
|
|
15
|
+
class MonthCalendarMixinClass extends FocusMixin(superClass) {
|
|
16
|
+
static get properties() {
|
|
17
|
+
return {
|
|
18
|
+
/**
|
|
19
|
+
* A `Date` object defining the month to be displayed. Only year and
|
|
20
|
+
* month properties are actually used.
|
|
21
|
+
*/
|
|
22
|
+
month: {
|
|
23
|
+
type: Object,
|
|
24
|
+
value: new Date(),
|
|
25
|
+
sync: true,
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* A `Date` object for the currently selected date.
|
|
30
|
+
*/
|
|
31
|
+
selectedDate: {
|
|
32
|
+
type: Object,
|
|
33
|
+
notify: true,
|
|
34
|
+
sync: true,
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* A `Date` object for the currently focused date.
|
|
39
|
+
*/
|
|
40
|
+
focusedDate: {
|
|
41
|
+
type: Object,
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Set true to display ISO-8601 week numbers in the calendar. Notice that
|
|
46
|
+
* displaying week numbers is only supported when `i18n.firstDayOfWeek`
|
|
47
|
+
* is 1 (Monday).
|
|
48
|
+
*/
|
|
49
|
+
showWeekNumbers: {
|
|
50
|
+
type: Boolean,
|
|
51
|
+
value: false,
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
i18n: {
|
|
55
|
+
type: Object,
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Flag stating whether taps on the component should be ignored.
|
|
60
|
+
*/
|
|
61
|
+
ignoreTaps: {
|
|
62
|
+
type: Boolean,
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The earliest date that can be selected. All earlier dates will be disabled.
|
|
67
|
+
*/
|
|
68
|
+
minDate: {
|
|
69
|
+
type: Date,
|
|
70
|
+
value: null,
|
|
71
|
+
sync: true,
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* The latest date that can be selected. All later dates will be disabled.
|
|
76
|
+
*/
|
|
77
|
+
maxDate: {
|
|
78
|
+
type: Date,
|
|
79
|
+
value: null,
|
|
80
|
+
sync: true,
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
disabled: {
|
|
84
|
+
type: Boolean,
|
|
85
|
+
reflectToAttribute: true,
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
/** @protected */
|
|
89
|
+
_days: {
|
|
90
|
+
type: Array,
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
/** @protected */
|
|
94
|
+
_weeks: {
|
|
95
|
+
type: Array,
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
/** @private */
|
|
99
|
+
_notTapping: {
|
|
100
|
+
type: Boolean,
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
static get observers() {
|
|
106
|
+
return ['__focusedDateChanged(focusedDate, _days)'];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
get focusableDateElement() {
|
|
110
|
+
return [...this.shadowRoot.querySelectorAll('[part~=date]')].find((datePart) => {
|
|
111
|
+
return dateEquals(datePart.date, this.focusedDate);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** @protected */
|
|
116
|
+
ready() {
|
|
117
|
+
super.ready();
|
|
118
|
+
addListener(this.$.monthGrid, 'tap', this._handleTap.bind(this));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Returns true if all the dates in the month are out of the allowed range
|
|
123
|
+
* @protected
|
|
124
|
+
*/
|
|
125
|
+
_isDisabled(month, minDate, maxDate) {
|
|
126
|
+
// First day of the month
|
|
127
|
+
const firstDate = new Date(0, 0);
|
|
128
|
+
firstDate.setFullYear(month.getFullYear());
|
|
129
|
+
firstDate.setMonth(month.getMonth());
|
|
130
|
+
firstDate.setDate(1);
|
|
131
|
+
|
|
132
|
+
// Last day of the month
|
|
133
|
+
const lastDate = new Date(0, 0);
|
|
134
|
+
lastDate.setFullYear(month.getFullYear());
|
|
135
|
+
lastDate.setMonth(month.getMonth() + 1);
|
|
136
|
+
lastDate.setDate(0);
|
|
137
|
+
|
|
138
|
+
if (
|
|
139
|
+
minDate &&
|
|
140
|
+
maxDate &&
|
|
141
|
+
minDate.getMonth() === maxDate.getMonth() &&
|
|
142
|
+
minDate.getMonth() === month.getMonth() &&
|
|
143
|
+
maxDate.getDate() - minDate.getDate() >= 0
|
|
144
|
+
) {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return !dateAllowed(firstDate, minDate, maxDate) && !dateAllowed(lastDate, minDate, maxDate);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** @protected */
|
|
152
|
+
_getTitle(month, i18n) {
|
|
153
|
+
if (month === undefined || i18n === undefined) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
return i18n.formatTitle(i18n.monthNames[month.getMonth()], month.getFullYear());
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** @protected */
|
|
160
|
+
_onMonthGridTouchStart() {
|
|
161
|
+
this._notTapping = false;
|
|
162
|
+
setTimeout(() => {
|
|
163
|
+
this._notTapping = true;
|
|
164
|
+
}, 300);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/** @private */
|
|
168
|
+
_dateAdd(date, delta) {
|
|
169
|
+
date.setDate(date.getDate() + delta);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** @private */
|
|
173
|
+
_applyFirstDayOfWeek(weekDayNames, firstDayOfWeek) {
|
|
174
|
+
if (weekDayNames === undefined || firstDayOfWeek === undefined) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return weekDayNames.slice(firstDayOfWeek).concat(weekDayNames.slice(0, firstDayOfWeek));
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** @protected */
|
|
182
|
+
_getWeekDayNames(i18n, showWeekNumbers) {
|
|
183
|
+
if (i18n === undefined || showWeekNumbers === undefined) {
|
|
184
|
+
return [];
|
|
185
|
+
}
|
|
186
|
+
const { weekdays, weekdaysShort, firstDayOfWeek } = i18n;
|
|
187
|
+
|
|
188
|
+
const weekDayNamesShort = this._applyFirstDayOfWeek(weekdaysShort, firstDayOfWeek);
|
|
189
|
+
const weekDayNames = this._applyFirstDayOfWeek(weekdays, firstDayOfWeek);
|
|
190
|
+
|
|
191
|
+
return weekDayNames.map((day, index) => {
|
|
192
|
+
return {
|
|
193
|
+
weekDay: day,
|
|
194
|
+
weekDayShort: weekDayNamesShort[index],
|
|
195
|
+
};
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/** @private */
|
|
200
|
+
__focusedDateChanged(focusedDate, days) {
|
|
201
|
+
if (Array.isArray(days) && days.some((date) => dateEquals(date, focusedDate))) {
|
|
202
|
+
this.removeAttribute('aria-hidden');
|
|
203
|
+
} else {
|
|
204
|
+
this.setAttribute('aria-hidden', 'true');
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/** @protected */
|
|
209
|
+
_getDate(date) {
|
|
210
|
+
return date ? date.getDate() : '';
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/** @protected */
|
|
214
|
+
_showWeekSeparator(showWeekNumbers, i18n) {
|
|
215
|
+
// Currently only supported for locales that start the week on Monday.
|
|
216
|
+
return showWeekNumbers && i18n && i18n.firstDayOfWeek === 1;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/** @protected */
|
|
220
|
+
_isToday(date) {
|
|
221
|
+
return dateEquals(new Date(), date);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/** @protected */
|
|
225
|
+
_getDays(month, i18n) {
|
|
226
|
+
if (month === undefined || i18n === undefined) {
|
|
227
|
+
return [];
|
|
228
|
+
}
|
|
229
|
+
// First day of the month (at midnight).
|
|
230
|
+
const date = new Date(0, 0);
|
|
231
|
+
date.setFullYear(month.getFullYear());
|
|
232
|
+
date.setMonth(month.getMonth());
|
|
233
|
+
date.setDate(1);
|
|
234
|
+
|
|
235
|
+
// Rewind to first day of the week.
|
|
236
|
+
while (date.getDay() !== i18n.firstDayOfWeek) {
|
|
237
|
+
this._dateAdd(date, -1);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const days = [];
|
|
241
|
+
const startMonth = date.getMonth();
|
|
242
|
+
const targetMonth = month.getMonth();
|
|
243
|
+
while (date.getMonth() === targetMonth || date.getMonth() === startMonth) {
|
|
244
|
+
days.push(date.getMonth() === targetMonth ? new Date(date.getTime()) : null);
|
|
245
|
+
|
|
246
|
+
// Advance to next day.
|
|
247
|
+
this._dateAdd(date, 1);
|
|
248
|
+
}
|
|
249
|
+
return days;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/** @protected */
|
|
253
|
+
_getWeeks(days) {
|
|
254
|
+
return days.reduce((acc, day, i) => {
|
|
255
|
+
if (i % 7 === 0) {
|
|
256
|
+
acc.push([]);
|
|
257
|
+
}
|
|
258
|
+
acc[acc.length - 1].push(day);
|
|
259
|
+
return acc;
|
|
260
|
+
}, []);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/** @protected */
|
|
264
|
+
_handleTap(e) {
|
|
265
|
+
if (!this.ignoreTaps && !this._notTapping && e.target.date && !e.target.hasAttribute('disabled')) {
|
|
266
|
+
this.selectedDate = e.target.date;
|
|
267
|
+
this.dispatchEvent(
|
|
268
|
+
new CustomEvent('date-tap', { detail: { date: e.target.date }, bubbles: true, composed: true }),
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/** @protected */
|
|
274
|
+
_preventDefault(e) {
|
|
275
|
+
e.preventDefault();
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/** @protected */
|
|
279
|
+
__getWeekNumber(days) {
|
|
280
|
+
const date = days.reduce((acc, d) => {
|
|
281
|
+
return !acc && d ? d : acc;
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
return getISOWeekNumber(date);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/** @protected */
|
|
288
|
+
__getDayAriaLabel(date) {
|
|
289
|
+
if (!date) {
|
|
290
|
+
return '';
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
let ariaLabel = `${this._getDate(date)} ${this.i18n.monthNames[date.getMonth()]} ${date.getFullYear()}, ${
|
|
294
|
+
this.i18n.weekdays[date.getDay()]
|
|
295
|
+
}`;
|
|
296
|
+
|
|
297
|
+
if (this._isToday(date)) {
|
|
298
|
+
ariaLabel += `, ${this.i18n.today}`;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return ariaLabel;
|
|
302
|
+
}
|
|
303
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2016 - 2023 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { css } from 'lit';
|
|
7
|
+
|
|
8
|
+
export const monthCalendarStyles = css`
|
|
9
|
+
:host {
|
|
10
|
+
display: block;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
#monthGrid {
|
|
14
|
+
width: 100%;
|
|
15
|
+
border-collapse: collapse;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
#days-container tr,
|
|
19
|
+
#weekdays-container tr {
|
|
20
|
+
display: flex;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
[part~='date'] {
|
|
24
|
+
outline: none;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
[part~='disabled'] {
|
|
28
|
+
pointer-events: none;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
[part='week-number'][hidden],
|
|
32
|
+
[part='weekday'][hidden] {
|
|
33
|
+
display: none;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
[part='weekday'],
|
|
37
|
+
[part~='date'] {
|
|
38
|
+
width: calc(100% / 7);
|
|
39
|
+
padding: 0;
|
|
40
|
+
font-weight: normal;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
[part='weekday']:empty,
|
|
44
|
+
[part='week-number'] {
|
|
45
|
+
width: 12.5%;
|
|
46
|
+
flex-shrink: 0;
|
|
47
|
+
padding: 0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
:host([week-numbers]) [part='weekday']:not(:empty),
|
|
51
|
+
:host([week-numbers]) [part~='date'] {
|
|
52
|
+
width: 12.5%;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@media (forced-colors: active) {
|
|
56
|
+
[part~='date'][part~='focused'] {
|
|
57
|
+
outline: 1px solid;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
[part~='date'][part~='selected'] {
|
|
61
|
+
outline: 3px solid;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
`;
|