@vaadin/date-picker 23.3.3 → 24.0.0-alpha10
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 +10 -10
- package/src/vaadin-date-picker-helper.d.ts +7 -0
- package/src/vaadin-date-picker-helper.js +16 -2
- package/src/vaadin-date-picker-light.d.ts +1 -7
- package/src/vaadin-date-picker-light.js +12 -50
- package/src/vaadin-date-picker-mixin.d.ts +4 -18
- package/src/vaadin-date-picker-mixin.js +121 -83
- package/src/vaadin-date-picker-month-scroller.js +74 -0
- package/src/vaadin-date-picker-overlay-content.js +268 -208
- package/src/vaadin-date-picker-overlay.js +19 -8
- package/src/vaadin-date-picker-year-scroller.js +104 -0
- package/src/vaadin-date-picker-year.js +57 -0
- package/src/vaadin-date-picker.d.ts +24 -12
- package/src/vaadin-date-picker.js +43 -39
- package/src/vaadin-infinite-scroller.js +98 -101
- package/src/vaadin-month-calendar.js +37 -14
- package/theme/lumo/vaadin-date-picker-overlay-content-styles.js +13 -50
- package/theme/lumo/vaadin-date-picker-year-styles.js +32 -0
- package/theme/lumo/vaadin-month-calendar-styles.js +16 -16
- package/theme/material/vaadin-date-picker-overlay-content-styles.js +10 -31
- package/theme/material/vaadin-date-picker-year-styles.js +28 -0
- package/theme/material/vaadin-month-calendar-styles.js +14 -14
- package/web-types.json +145 -5
- package/web-types.lit.json +61 -5
- package/src/vaadin-date-picker-styles.js +0 -28
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2016 -
|
|
3
|
+
* Copyright (c) 2016 - 2023 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
6
|
import '@vaadin/button/src/vaadin-button.js';
|
|
7
7
|
import './vaadin-month-calendar.js';
|
|
8
|
-
import './vaadin-
|
|
8
|
+
import './vaadin-date-picker-month-scroller.js';
|
|
9
|
+
import './vaadin-date-picker-year-scroller.js';
|
|
10
|
+
import './vaadin-date-picker-year.js';
|
|
11
|
+
import { flush } from '@polymer/polymer/lib/utils/flush.js';
|
|
12
|
+
import { afterNextRender } from '@polymer/polymer/lib/utils/render-status.js';
|
|
9
13
|
import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
|
|
10
14
|
import { timeOut } from '@vaadin/component-base/src/async.js';
|
|
11
15
|
import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
|
|
@@ -13,8 +17,9 @@ import { Debouncer } from '@vaadin/component-base/src/debounce.js';
|
|
|
13
17
|
import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
|
|
14
18
|
import { addListener, setTouchAction } from '@vaadin/component-base/src/gestures.js';
|
|
15
19
|
import { MediaQueryController } from '@vaadin/component-base/src/media-query-controller.js';
|
|
20
|
+
import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
|
|
16
21
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
17
|
-
import { dateEquals, extractDateParts, getClosestDate } from './vaadin-date-picker-helper.js';
|
|
22
|
+
import { dateAfterXMonths, dateEquals, extractDateParts, getClosestDate } from './vaadin-date-picker-helper.js';
|
|
18
23
|
|
|
19
24
|
/**
|
|
20
25
|
* @extends HTMLElement
|
|
@@ -63,62 +68,17 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
|
|
|
63
68
|
overflow: hidden;
|
|
64
69
|
}
|
|
65
70
|
|
|
66
|
-
[
|
|
67
|
-
[part='years'] {
|
|
68
|
-
height: 100%;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
[part='months'] {
|
|
72
|
-
--vaadin-infinite-scroller-item-height: 270px;
|
|
73
|
-
position: absolute;
|
|
74
|
-
top: 0;
|
|
75
|
-
left: 0;
|
|
76
|
-
right: 0;
|
|
77
|
-
bottom: 0;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
#scrollers[desktop] [part='months'] {
|
|
71
|
+
:host([desktop]) ::slotted([slot='months']) {
|
|
81
72
|
right: 50px;
|
|
82
73
|
transform: none !important;
|
|
83
74
|
}
|
|
84
75
|
|
|
85
|
-
[
|
|
86
|
-
--vaadin-infinite-scroller-item-height: 80px;
|
|
87
|
-
width: 50px;
|
|
88
|
-
position: absolute;
|
|
89
|
-
right: 0;
|
|
90
|
-
transform: translateX(100%);
|
|
91
|
-
-webkit-tap-highlight-color: transparent;
|
|
92
|
-
-webkit-user-select: none;
|
|
93
|
-
-moz-user-select: none;
|
|
94
|
-
user-select: none;
|
|
95
|
-
/* Center the year scroller position. */
|
|
96
|
-
--vaadin-infinite-scroller-buffer-offset: 50%;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
#scrollers[desktop] [part='years'] {
|
|
100
|
-
position: absolute;
|
|
76
|
+
:host([desktop]) ::slotted([slot='years']) {
|
|
101
77
|
transform: none !important;
|
|
102
78
|
}
|
|
103
79
|
|
|
104
|
-
[
|
|
105
|
-
|
|
106
|
-
display: block;
|
|
107
|
-
background: transparent;
|
|
108
|
-
width: 0;
|
|
109
|
-
height: 0;
|
|
110
|
-
position: absolute;
|
|
111
|
-
left: 0;
|
|
112
|
-
top: 50%;
|
|
113
|
-
transform: translateY(-50%);
|
|
114
|
-
border-width: 6px;
|
|
115
|
-
border-style: solid;
|
|
116
|
-
border-color: transparent;
|
|
117
|
-
border-left-color: #000;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
:host(.animate) [part='months'],
|
|
121
|
-
:host(.animate) [part='years'] {
|
|
80
|
+
:host(.animate) ::slotted([slot='months']),
|
|
81
|
+
:host(.animate) ::slotted([slot='years']) {
|
|
122
82
|
transition: all 200ms;
|
|
123
83
|
}
|
|
124
84
|
|
|
@@ -130,7 +90,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
|
|
|
130
90
|
}
|
|
131
91
|
</style>
|
|
132
92
|
|
|
133
|
-
<div part="overlay-header" on-touchend="_preventDefault"
|
|
93
|
+
<div part="overlay-header" on-touchend="_preventDefault" aria-hidden="true">
|
|
134
94
|
<div part="label">[[_formatDisplayed(selectedDate, i18n.formatDate, label)]]</div>
|
|
135
95
|
<div part="clear-button" hidden$="[[!selectedDate]]"></div>
|
|
136
96
|
<div part="toggle-button"></div>
|
|
@@ -140,67 +100,14 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
|
|
|
140
100
|
</div>
|
|
141
101
|
</div>
|
|
142
102
|
|
|
143
|
-
<div id="scrollers"
|
|
144
|
-
<
|
|
145
|
-
|
|
146
|
-
on-custom-scroll="_onMonthScroll"
|
|
147
|
-
on-touchstart="_onMonthScrollTouchStart"
|
|
148
|
-
buffer-size="3"
|
|
149
|
-
active="[[initialPosition]]"
|
|
150
|
-
part="months"
|
|
151
|
-
>
|
|
152
|
-
<template>
|
|
153
|
-
<vaadin-month-calendar
|
|
154
|
-
i18n="[[i18n]]"
|
|
155
|
-
month="[[_dateAfterXMonths(index)]]"
|
|
156
|
-
selected-date="{{selectedDate}}"
|
|
157
|
-
focused-date="[[focusedDate]]"
|
|
158
|
-
ignore-taps="[[_ignoreTaps]]"
|
|
159
|
-
show-week-numbers="[[showWeekNumbers]]"
|
|
160
|
-
min-date="[[minDate]]"
|
|
161
|
-
max-date="[[maxDate]]"
|
|
162
|
-
part="month"
|
|
163
|
-
theme$="[[_theme]]"
|
|
164
|
-
on-keydown="__onMonthCalendarKeyDown"
|
|
165
|
-
>
|
|
166
|
-
</vaadin-month-calendar>
|
|
167
|
-
</template>
|
|
168
|
-
</vaadin-infinite-scroller>
|
|
169
|
-
<vaadin-infinite-scroller
|
|
170
|
-
id="yearScroller"
|
|
171
|
-
on-custom-scroll="_onYearScroll"
|
|
172
|
-
on-touchstart="_onYearScrollTouchStart"
|
|
173
|
-
buffer-size="12"
|
|
174
|
-
active="[[initialPosition]]"
|
|
175
|
-
part="years"
|
|
176
|
-
aria-hidden="true"
|
|
177
|
-
>
|
|
178
|
-
<template>
|
|
179
|
-
<div
|
|
180
|
-
part="year-number"
|
|
181
|
-
current$="[[_isCurrentYear(index)]]"
|
|
182
|
-
selected$="[[_isSelectedYear(index, selectedDate)]]"
|
|
183
|
-
>
|
|
184
|
-
[[_yearAfterXYears(index)]]
|
|
185
|
-
</div>
|
|
186
|
-
<div part="year-separator" aria-hidden="true"></div>
|
|
187
|
-
</template>
|
|
188
|
-
</vaadin-infinite-scroller>
|
|
103
|
+
<div id="scrollers">
|
|
104
|
+
<slot name="months"></slot>
|
|
105
|
+
<slot name="years"></slot>
|
|
189
106
|
</div>
|
|
190
107
|
|
|
191
108
|
<div on-touchend="_preventDefault" role="toolbar" part="toolbar">
|
|
192
|
-
<
|
|
193
|
-
|
|
194
|
-
part="today-button"
|
|
195
|
-
theme="tertiary"
|
|
196
|
-
disabled="[[!_isTodayAllowed(minDate, maxDate)]]"
|
|
197
|
-
on-keydown="__onTodayButtonKeyDown"
|
|
198
|
-
>
|
|
199
|
-
[[i18n.today]]
|
|
200
|
-
</vaadin-button>
|
|
201
|
-
<vaadin-button id="cancelButton" part="cancel-button" theme="tertiary" on-keydown="__onCancelButtonKeyDown">
|
|
202
|
-
[[i18n.cancel]]
|
|
203
|
-
</vaadin-button>
|
|
109
|
+
<slot name="today-button"></slot>
|
|
110
|
+
<slot name="cancel-button"></slot>
|
|
204
111
|
</div>
|
|
205
112
|
`;
|
|
206
113
|
}
|
|
@@ -249,7 +156,10 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
|
|
|
249
156
|
|
|
250
157
|
_visibleMonthIndex: Number,
|
|
251
158
|
|
|
252
|
-
_desktopMode:
|
|
159
|
+
_desktopMode: {
|
|
160
|
+
type: Boolean,
|
|
161
|
+
observer: '_desktopModeChanged',
|
|
162
|
+
},
|
|
253
163
|
|
|
254
164
|
_desktopMediaQuery: {
|
|
255
165
|
type: String,
|
|
@@ -270,6 +180,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
|
|
|
270
180
|
|
|
271
181
|
showWeekNumbers: {
|
|
272
182
|
type: Boolean,
|
|
183
|
+
value: false,
|
|
273
184
|
},
|
|
274
185
|
|
|
275
186
|
_ignoreTaps: Boolean,
|
|
@@ -290,11 +201,34 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
|
|
|
290
201
|
* Input label
|
|
291
202
|
*/
|
|
292
203
|
label: String,
|
|
204
|
+
|
|
205
|
+
_cancelButton: {
|
|
206
|
+
type: Object,
|
|
207
|
+
},
|
|
208
|
+
|
|
209
|
+
_todayButton: {
|
|
210
|
+
type: Object,
|
|
211
|
+
},
|
|
212
|
+
|
|
213
|
+
calendars: {
|
|
214
|
+
type: Array,
|
|
215
|
+
value: () => [],
|
|
216
|
+
},
|
|
217
|
+
|
|
218
|
+
years: {
|
|
219
|
+
type: Array,
|
|
220
|
+
value: () => [],
|
|
221
|
+
},
|
|
293
222
|
};
|
|
294
223
|
}
|
|
295
224
|
|
|
296
|
-
get
|
|
297
|
-
return
|
|
225
|
+
static get observers() {
|
|
226
|
+
return [
|
|
227
|
+
'__updateCalendars(calendars, i18n, minDate, maxDate, selectedDate, focusedDate, showWeekNumbers, _ignoreTaps, _theme)',
|
|
228
|
+
'__updateCancelButton(_cancelButton, i18n)',
|
|
229
|
+
'__updateTodayButton(_todayButton, i18n, minDate, maxDate)',
|
|
230
|
+
'__updateYears(years, selectedDate, _theme)',
|
|
231
|
+
];
|
|
298
232
|
}
|
|
299
233
|
|
|
300
234
|
/**
|
|
@@ -306,11 +240,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
|
|
|
306
240
|
* @private
|
|
307
241
|
*/
|
|
308
242
|
get __useSubMonthScrolling() {
|
|
309
|
-
return this
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
get calendars() {
|
|
313
|
-
return [...this.shadowRoot.querySelectorAll('vaadin-month-calendar')];
|
|
243
|
+
return this._monthScroller.clientHeight < this._monthScroller.itemHeight + this._monthScroller.bufferOffset;
|
|
314
244
|
}
|
|
315
245
|
|
|
316
246
|
get focusableDateElement() {
|
|
@@ -324,10 +254,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
|
|
|
324
254
|
|
|
325
255
|
addListener(this.$.scrollers, 'track', this._track.bind(this));
|
|
326
256
|
addListener(this.shadowRoot.querySelector('[part="clear-button"]'), 'tap', this._clear.bind(this));
|
|
327
|
-
addListener(this.shadowRoot.querySelector('[part="today-button"]'), 'tap', this._onTodayTap.bind(this));
|
|
328
|
-
addListener(this.shadowRoot.querySelector('[part="cancel-button"]'), 'tap', this._cancel.bind(this));
|
|
329
257
|
addListener(this.shadowRoot.querySelector('[part="toggle-button"]'), 'tap', this._cancel.bind(this));
|
|
330
|
-
addListener(this.shadowRoot.querySelector('[part="years"]'), 'tap', this._onYearTap.bind(this));
|
|
331
258
|
addListener(
|
|
332
259
|
this.shadowRoot.querySelector('[part="years-toggle-button"]'),
|
|
333
260
|
'tap',
|
|
@@ -339,6 +266,33 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
|
|
|
339
266
|
this._desktopMode = matches;
|
|
340
267
|
}),
|
|
341
268
|
);
|
|
269
|
+
|
|
270
|
+
this.addController(
|
|
271
|
+
new SlotController(this, 'today-button', 'vaadin-button', {
|
|
272
|
+
observe: false,
|
|
273
|
+
initializer: (btn) => {
|
|
274
|
+
btn.setAttribute('theme', 'tertiary');
|
|
275
|
+
btn.addEventListener('keydown', (e) => this.__onTodayButtonKeyDown(e));
|
|
276
|
+
addListener(btn, 'tap', this._onTodayTap.bind(this));
|
|
277
|
+
this._todayButton = btn;
|
|
278
|
+
},
|
|
279
|
+
}),
|
|
280
|
+
);
|
|
281
|
+
|
|
282
|
+
this.addController(
|
|
283
|
+
new SlotController(this, 'cancel-button', 'vaadin-button', {
|
|
284
|
+
observe: false,
|
|
285
|
+
initializer: (btn) => {
|
|
286
|
+
btn.setAttribute('theme', 'tertiary');
|
|
287
|
+
btn.addEventListener('keydown', (e) => this.__onCancelButtonKeyDown(e));
|
|
288
|
+
addListener(btn, 'tap', this._cancel.bind(this));
|
|
289
|
+
this._cancelButton = btn;
|
|
290
|
+
},
|
|
291
|
+
}),
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
this.__initMonthScroller();
|
|
295
|
+
this.__initYearScroller();
|
|
342
296
|
}
|
|
343
297
|
|
|
344
298
|
/**
|
|
@@ -359,7 +313,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
|
|
|
359
313
|
* Focuses the cancel button
|
|
360
314
|
*/
|
|
361
315
|
focusCancel() {
|
|
362
|
-
this
|
|
316
|
+
this._cancelButton.focus();
|
|
363
317
|
}
|
|
364
318
|
|
|
365
319
|
/**
|
|
@@ -368,7 +322,122 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
|
|
|
368
322
|
scrollToDate(date, animate) {
|
|
369
323
|
const offset = this.__useSubMonthScrolling ? this._calculateWeekScrollOffset(date) : 0;
|
|
370
324
|
this._scrollToPosition(this._differenceInMonths(date, this._originDate) + offset, animate);
|
|
371
|
-
this
|
|
325
|
+
this._monthScroller.forceUpdate();
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
__initMonthScroller() {
|
|
329
|
+
this.addController(
|
|
330
|
+
new SlotController(this, 'months', 'vaadin-date-picker-month-scroller', {
|
|
331
|
+
observe: false,
|
|
332
|
+
initializer: (scroller) => {
|
|
333
|
+
scroller.addEventListener('custom-scroll', () => {
|
|
334
|
+
this._onMonthScroll();
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
scroller.addEventListener('touchstart', () => {
|
|
338
|
+
this._onMonthScrollTouchStart();
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
scroller.addEventListener('keydown', (e) => {
|
|
342
|
+
this.__onMonthCalendarKeyDown(e);
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
scroller.addEventListener('init-done', () => {
|
|
346
|
+
const calendars = [...this.querySelectorAll('vaadin-month-calendar')];
|
|
347
|
+
|
|
348
|
+
// Two-way binding for selectedDate property
|
|
349
|
+
calendars.forEach((calendar) => {
|
|
350
|
+
calendar.addEventListener('selected-date-changed', (e) => {
|
|
351
|
+
this.selectedDate = e.detail.value;
|
|
352
|
+
});
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
this.calendars = calendars;
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
this._monthScroller = scroller;
|
|
359
|
+
},
|
|
360
|
+
}),
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
__initYearScroller() {
|
|
365
|
+
this.addController(
|
|
366
|
+
new SlotController(this, 'years', 'vaadin-date-picker-year-scroller', {
|
|
367
|
+
observe: false,
|
|
368
|
+
initializer: (scroller) => {
|
|
369
|
+
scroller.setAttribute('aria-hidden', 'true');
|
|
370
|
+
|
|
371
|
+
addListener(scroller, 'tap', (e) => {
|
|
372
|
+
this._onYearTap(e);
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
scroller.addEventListener('custom-scroll', () => {
|
|
376
|
+
this._onYearScroll();
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
scroller.addEventListener('touchstart', () => {
|
|
380
|
+
this._onYearScrollTouchStart();
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
scroller.addEventListener('init-done', () => {
|
|
384
|
+
this.years = [...this.querySelectorAll('vaadin-date-picker-year')];
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
this._yearScroller = scroller;
|
|
388
|
+
},
|
|
389
|
+
}),
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
__updateCancelButton(cancelButton, i18n) {
|
|
394
|
+
if (cancelButton) {
|
|
395
|
+
cancelButton.textContent = i18n && i18n.cancel;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
__updateTodayButton(todayButton, i18n, minDate, maxDate) {
|
|
400
|
+
if (todayButton) {
|
|
401
|
+
todayButton.textContent = i18n && i18n.today;
|
|
402
|
+
todayButton.disabled = !this._isTodayAllowed(minDate, maxDate);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// eslint-disable-next-line max-params
|
|
407
|
+
__updateCalendars(calendars, i18n, minDate, maxDate, selectedDate, focusedDate, showWeekNumbers, ignoreTaps, theme) {
|
|
408
|
+
if (calendars && calendars.length) {
|
|
409
|
+
calendars.forEach((calendar) => {
|
|
410
|
+
calendar.setProperties({
|
|
411
|
+
i18n,
|
|
412
|
+
minDate,
|
|
413
|
+
maxDate,
|
|
414
|
+
focusedDate,
|
|
415
|
+
selectedDate,
|
|
416
|
+
showWeekNumbers,
|
|
417
|
+
ignoreTaps,
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
if (theme) {
|
|
421
|
+
calendar.setAttribute('theme', theme);
|
|
422
|
+
} else {
|
|
423
|
+
calendar.removeAttribute('theme');
|
|
424
|
+
}
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
__updateYears(years, selectedDate, theme) {
|
|
430
|
+
if (years && years.length) {
|
|
431
|
+
years.forEach((year) => {
|
|
432
|
+
year.selectedDate = selectedDate;
|
|
433
|
+
|
|
434
|
+
if (theme) {
|
|
435
|
+
year.setAttribute('theme', theme);
|
|
436
|
+
} else {
|
|
437
|
+
year.removeAttribute('theme');
|
|
438
|
+
}
|
|
439
|
+
});
|
|
440
|
+
}
|
|
372
441
|
}
|
|
373
442
|
|
|
374
443
|
/**
|
|
@@ -382,18 +451,12 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
|
|
|
382
451
|
);
|
|
383
452
|
}
|
|
384
453
|
|
|
385
|
-
|
|
386
|
-
this.
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
_isCurrentYear(yearsFromNow) {
|
|
390
|
-
return yearsFromNow === 0;
|
|
454
|
+
_desktopModeChanged(desktopMode) {
|
|
455
|
+
this.toggleAttribute('desktop', desktopMode);
|
|
391
456
|
}
|
|
392
457
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
return selectedDate.getFullYear() === this._originDate.getFullYear() + yearsFromNow;
|
|
396
|
-
}
|
|
458
|
+
_focusedDateChanged(focusedDate) {
|
|
459
|
+
this.revealDate(focusedDate);
|
|
397
460
|
}
|
|
398
461
|
|
|
399
462
|
/**
|
|
@@ -413,14 +476,14 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
|
|
|
413
476
|
}
|
|
414
477
|
|
|
415
478
|
// Otherwise determine if we need to scroll to make the month of the date visible
|
|
416
|
-
const scrolledAboveViewport = this
|
|
479
|
+
const scrolledAboveViewport = this._monthScroller.position > diff;
|
|
417
480
|
|
|
418
481
|
const visibleArea = Math.max(
|
|
419
|
-
this
|
|
420
|
-
this
|
|
482
|
+
this._monthScroller.itemHeight,
|
|
483
|
+
this._monthScroller.clientHeight - this._monthScroller.bufferOffset * 2,
|
|
421
484
|
);
|
|
422
|
-
const visibleItems = visibleArea / this
|
|
423
|
-
const scrolledBelowViewport = this
|
|
485
|
+
const visibleItems = visibleArea / this._monthScroller.itemHeight;
|
|
486
|
+
const scrolledBelowViewport = this._monthScroller.position + visibleItems - 1 < diff;
|
|
424
487
|
|
|
425
488
|
if (scrolledAboveViewport) {
|
|
426
489
|
this._scrollToPosition(diff, animate);
|
|
@@ -460,17 +523,23 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
|
|
|
460
523
|
}
|
|
461
524
|
|
|
462
525
|
_initialPositionChanged(initialPosition) {
|
|
526
|
+
if (this._monthScroller && this._yearScroller) {
|
|
527
|
+
this._monthScroller.active = true;
|
|
528
|
+
this._yearScroller.active = true;
|
|
529
|
+
}
|
|
530
|
+
|
|
463
531
|
this.scrollToDate(initialPosition);
|
|
464
532
|
}
|
|
465
533
|
|
|
466
534
|
_repositionYearScroller() {
|
|
467
|
-
|
|
468
|
-
this
|
|
535
|
+
const monthPosition = this._monthScroller.position;
|
|
536
|
+
this._visibleMonthIndex = Math.floor(monthPosition);
|
|
537
|
+
this._yearScroller.position = (monthPosition + this._originDate.getMonth()) / 12;
|
|
469
538
|
}
|
|
470
539
|
|
|
471
540
|
_repositionMonthScroller() {
|
|
472
|
-
this
|
|
473
|
-
this._visibleMonthIndex = Math.floor(this
|
|
541
|
+
this._monthScroller.position = this._yearScroller.position * 12 - this._originDate.getMonth();
|
|
542
|
+
this._visibleMonthIndex = Math.floor(this._monthScroller.position);
|
|
474
543
|
}
|
|
475
544
|
|
|
476
545
|
_onMonthScroll() {
|
|
@@ -513,7 +582,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
|
|
|
513
582
|
_onTodayTap() {
|
|
514
583
|
const today = new Date();
|
|
515
584
|
|
|
516
|
-
if (Math.abs(this
|
|
585
|
+
if (Math.abs(this._monthScroller.position - this._differenceInMonths(today, this._originDate)) < 0.001) {
|
|
517
586
|
// Select today only if the month scroller is positioned approximately
|
|
518
587
|
// at the beginning of the current month
|
|
519
588
|
this._selectDate(today);
|
|
@@ -534,9 +603,9 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
|
|
|
534
603
|
_onYearTap(e) {
|
|
535
604
|
if (!this._ignoreTaps && !this._notTapping) {
|
|
536
605
|
const scrollDelta =
|
|
537
|
-
e.detail.y - (this
|
|
538
|
-
const yearDelta = scrollDelta / this
|
|
539
|
-
this._scrollToPosition(this
|
|
606
|
+
e.detail.y - (this._yearScroller.getBoundingClientRect().top + this._yearScroller.clientHeight / 2);
|
|
607
|
+
const yearDelta = scrollDelta / this._yearScroller.itemHeight;
|
|
608
|
+
this._scrollToPosition(this._monthScroller.position + yearDelta * 12, true);
|
|
540
609
|
}
|
|
541
610
|
}
|
|
542
611
|
|
|
@@ -547,7 +616,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
|
|
|
547
616
|
}
|
|
548
617
|
|
|
549
618
|
if (!animate) {
|
|
550
|
-
this
|
|
619
|
+
this._monthScroller.position = targetPosition;
|
|
551
620
|
this._targetPosition = undefined;
|
|
552
621
|
this._repositionYearScroller();
|
|
553
622
|
this.__tryFocusDate();
|
|
@@ -572,10 +641,13 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
|
|
|
572
641
|
};
|
|
573
642
|
|
|
574
643
|
let start = 0;
|
|
575
|
-
const initialPosition = this
|
|
644
|
+
const initialPosition = this._monthScroller.position;
|
|
576
645
|
|
|
577
646
|
const smoothScroll = (timestamp) => {
|
|
578
|
-
|
|
647
|
+
if (!start) {
|
|
648
|
+
start = timestamp;
|
|
649
|
+
}
|
|
650
|
+
|
|
579
651
|
const currentTime = timestamp - start;
|
|
580
652
|
|
|
581
653
|
if (currentTime < this.scrollDuration) {
|
|
@@ -585,7 +657,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
|
|
|
585
657
|
this._targetPosition - initialPosition,
|
|
586
658
|
this.scrollDuration,
|
|
587
659
|
);
|
|
588
|
-
this
|
|
660
|
+
this._monthScroller.position = currentPos;
|
|
589
661
|
window.requestAnimationFrame(smoothScroll);
|
|
590
662
|
} else {
|
|
591
663
|
this.dispatchEvent(
|
|
@@ -599,7 +671,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
|
|
|
599
671
|
}),
|
|
600
672
|
);
|
|
601
673
|
|
|
602
|
-
this
|
|
674
|
+
this._monthScroller.position = this._targetPosition;
|
|
603
675
|
this._targetPosition = undefined;
|
|
604
676
|
|
|
605
677
|
revealResolve();
|
|
@@ -694,26 +766,13 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
|
|
|
694
766
|
|
|
695
767
|
_translateXChanged(x) {
|
|
696
768
|
if (!this._desktopMode) {
|
|
697
|
-
this
|
|
698
|
-
this
|
|
769
|
+
this._monthScroller.style.transform = `translateX(${x - this._yearScrollerWidth}px)`;
|
|
770
|
+
this._yearScroller.style.transform = `translateX(${x}px)`;
|
|
699
771
|
}
|
|
700
772
|
}
|
|
701
773
|
|
|
702
|
-
_yearAfterXYears(index) {
|
|
703
|
-
const result = new Date(this._originDate);
|
|
704
|
-
result.setFullYear(parseInt(index) + this._originDate.getFullYear());
|
|
705
|
-
return result.getFullYear();
|
|
706
|
-
}
|
|
707
|
-
|
|
708
774
|
_yearAfterXMonths(months) {
|
|
709
|
-
return
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
_dateAfterXMonths(months) {
|
|
713
|
-
const result = new Date(this._originDate);
|
|
714
|
-
result.setDate(1);
|
|
715
|
-
result.setMonth(parseInt(months) + this._originDate.getMonth());
|
|
716
|
-
return result;
|
|
775
|
+
return dateAfterXMonths(months).getFullYear();
|
|
717
776
|
}
|
|
718
777
|
|
|
719
778
|
_differenceInMonths(date1, date2) {
|
|
@@ -817,7 +876,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
|
|
|
817
876
|
|
|
818
877
|
if (this.hasAttribute('fullscreen')) {
|
|
819
878
|
// Trap focus in the overlay
|
|
820
|
-
this
|
|
879
|
+
this.focusCancel();
|
|
821
880
|
} else {
|
|
822
881
|
this.__focusInput();
|
|
823
882
|
}
|
|
@@ -890,7 +949,11 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
|
|
|
890
949
|
// Wait for `vaadin-month-calendar` elements to be rendered
|
|
891
950
|
if (!this.calendars.length) {
|
|
892
951
|
await new Promise((resolve) => {
|
|
893
|
-
|
|
952
|
+
afterNextRender(this, () => {
|
|
953
|
+
// Force dom-repeat elements to render
|
|
954
|
+
flush();
|
|
955
|
+
resolve();
|
|
956
|
+
});
|
|
894
957
|
});
|
|
895
958
|
}
|
|
896
959
|
|
|
@@ -912,58 +975,55 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
|
|
|
912
975
|
this.focusDate(getClosestDate(focus, [this.minDate, this.maxDate]));
|
|
913
976
|
}
|
|
914
977
|
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
dateToFocus.setMonth(focus.getMonth());
|
|
920
|
-
dateToFocus.setDate(focus.getDate() + days);
|
|
921
|
-
|
|
922
|
-
if (this._dateAllowed(dateToFocus, this.minDate, this.maxDate)) {
|
|
923
|
-
this.focusDate(dateToFocus);
|
|
924
|
-
} else if (this._dateAllowed(focus, this.minDate, this.maxDate)) {
|
|
978
|
+
_focusAllowedDate(dateToFocus, diff, keepMonth) {
|
|
979
|
+
if (this._dateAllowed(dateToFocus)) {
|
|
980
|
+
this.focusDate(dateToFocus, keepMonth);
|
|
981
|
+
} else if (this._dateAllowed(this.focusedDate)) {
|
|
925
982
|
// Move to min or max date
|
|
926
|
-
if (
|
|
927
|
-
// Down or
|
|
983
|
+
if (diff > 0) {
|
|
984
|
+
// Down, Right or Page Down key
|
|
928
985
|
this.focusDate(this.maxDate);
|
|
929
986
|
} else {
|
|
930
|
-
// Up or
|
|
987
|
+
// Up, Left or Page Up key
|
|
931
988
|
this.focusDate(this.minDate);
|
|
932
989
|
}
|
|
933
990
|
} else {
|
|
934
991
|
// Move to closest allowed date
|
|
935
|
-
this._focusClosestDate(
|
|
992
|
+
this._focusClosestDate(this.focusedDate);
|
|
936
993
|
}
|
|
937
994
|
}
|
|
938
995
|
|
|
939
|
-
|
|
940
|
-
const
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
996
|
+
_getDateDiff(months, days) {
|
|
997
|
+
const date = new Date(0, 0);
|
|
998
|
+
date.setFullYear(this.focusedDate.getFullYear());
|
|
999
|
+
date.setMonth(this.focusedDate.getMonth() + months);
|
|
1000
|
+
if (days) {
|
|
1001
|
+
date.setDate(this.focusedDate.getDate() + days);
|
|
1002
|
+
}
|
|
1003
|
+
return date;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
_moveFocusByDays(days) {
|
|
1007
|
+
const dateToFocus = this._getDateDiff(0, days);
|
|
1008
|
+
|
|
1009
|
+
this._focusAllowedDate(dateToFocus, days, false);
|
|
1010
|
+
}
|
|
944
1011
|
|
|
1012
|
+
_moveFocusByMonths(months) {
|
|
1013
|
+
const dateToFocus = this._getDateDiff(months);
|
|
945
1014
|
const targetMonth = dateToFocus.getMonth();
|
|
946
1015
|
|
|
947
|
-
|
|
1016
|
+
if (!this._focusedMonthDate) {
|
|
1017
|
+
this._focusedMonthDate = this.focusedDate.getDate();
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
dateToFocus.setDate(this._focusedMonthDate);
|
|
1021
|
+
|
|
948
1022
|
if (dateToFocus.getMonth() !== targetMonth) {
|
|
949
1023
|
dateToFocus.setDate(0);
|
|
950
1024
|
}
|
|
951
1025
|
|
|
952
|
-
|
|
953
|
-
this.focusDate(dateToFocus, true);
|
|
954
|
-
} else if (this._dateAllowed(focus, this.minDate, this.maxDate)) {
|
|
955
|
-
// Move to min or max date
|
|
956
|
-
if (months > 0) {
|
|
957
|
-
// Pagedown
|
|
958
|
-
this.focusDate(this.maxDate);
|
|
959
|
-
} else {
|
|
960
|
-
// Pageup
|
|
961
|
-
this.focusDate(this.minDate);
|
|
962
|
-
}
|
|
963
|
-
} else {
|
|
964
|
-
// Move to closest allowed date
|
|
965
|
-
this._focusClosestDate(focus);
|
|
966
|
-
}
|
|
1026
|
+
this._focusAllowedDate(dateToFocus, months, true);
|
|
967
1027
|
}
|
|
968
1028
|
|
|
969
1029
|
_moveFocusInsideMonth(focusedDate, property) {
|
|
@@ -978,9 +1038,9 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
|
|
|
978
1038
|
dateToFocus.setDate(0);
|
|
979
1039
|
}
|
|
980
1040
|
|
|
981
|
-
if (this._dateAllowed(dateToFocus
|
|
1041
|
+
if (this._dateAllowed(dateToFocus)) {
|
|
982
1042
|
this.focusDate(dateToFocus);
|
|
983
|
-
} else if (this._dateAllowed(focusedDate
|
|
1043
|
+
} else if (this._dateAllowed(focusedDate)) {
|
|
984
1044
|
// Move to minDate or maxDate
|
|
985
1045
|
this.focusDate(this[property]);
|
|
986
1046
|
} else {
|
|
@@ -989,7 +1049,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
|
|
|
989
1049
|
}
|
|
990
1050
|
}
|
|
991
1051
|
|
|
992
|
-
_dateAllowed(date, min, max) {
|
|
1052
|
+
_dateAllowed(date, min = this.minDate, max = this.maxDate) {
|
|
993
1053
|
return (!min || date >= min) && (!max || date <= max);
|
|
994
1054
|
}
|
|
995
1055
|
|