@vaadin/date-picker 23.3.0-alpha5 → 24.0.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.
@@ -5,7 +5,11 @@
5
5
  */
6
6
  import '@vaadin/button/src/vaadin-button.js';
7
7
  import './vaadin-month-calendar.js';
8
- import './vaadin-infinite-scroller.js';
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
- [part='months'],
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
- [part='years'] {
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
- [part='years']::before {
105
- content: '';
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" desktop$="[[_desktopMode]]" aria-hidden="true">
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" desktop$="[[_desktopMode]]">
144
- <vaadin-infinite-scroller
145
- id="monthScroller"
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
- <vaadin-button
193
- id="todayButton"
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: Boolean,
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,9 +201,36 @@ 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
 
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
+ ];
232
+ }
233
+
296
234
  get __isRTL() {
297
235
  return this.getAttribute('dir') === 'rtl';
298
236
  }
@@ -306,11 +244,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
306
244
  * @private
307
245
  */
308
246
  get __useSubMonthScrolling() {
309
- return this.$.monthScroller.clientHeight < this.$.monthScroller.itemHeight + this.$.monthScroller.bufferOffset;
310
- }
311
-
312
- get calendars() {
313
- return [...this.shadowRoot.querySelectorAll('vaadin-month-calendar')];
247
+ return this._monthScroller.clientHeight < this._monthScroller.itemHeight + this._monthScroller.bufferOffset;
314
248
  }
315
249
 
316
250
  get focusableDateElement() {
@@ -324,10 +258,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
324
258
 
325
259
  addListener(this.$.scrollers, 'track', this._track.bind(this));
326
260
  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
261
  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
262
  addListener(
332
263
  this.shadowRoot.querySelector('[part="years-toggle-button"]'),
333
264
  'tap',
@@ -339,6 +270,37 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
339
270
  this._desktopMode = matches;
340
271
  }),
341
272
  );
273
+
274
+ this.addController(
275
+ new SlotController(
276
+ this,
277
+ 'today-button',
278
+ () => document.createElement('vaadin-button'),
279
+ (_, btn) => {
280
+ btn.setAttribute('theme', 'tertiary');
281
+ btn.addEventListener('keydown', (e) => this.__onTodayButtonKeyDown(e));
282
+ addListener(btn, 'tap', this._onTodayTap.bind(this));
283
+ this._todayButton = btn;
284
+ },
285
+ ),
286
+ );
287
+
288
+ this.addController(
289
+ new SlotController(
290
+ this,
291
+ 'cancel-button',
292
+ () => document.createElement('vaadin-button'),
293
+ (_, btn) => {
294
+ btn.setAttribute('theme', 'tertiary');
295
+ btn.addEventListener('keydown', (e) => this.__onCancelButtonKeyDown(e));
296
+ addListener(btn, 'tap', this._cancel.bind(this));
297
+ this._cancelButton = btn;
298
+ },
299
+ ),
300
+ );
301
+
302
+ this.__initMonthScroller();
303
+ this.__initYearScroller();
342
304
  }
343
305
 
344
306
  /**
@@ -359,7 +321,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
359
321
  * Focuses the cancel button
360
322
  */
361
323
  focusCancel() {
362
- this.$.cancelButton.focus();
324
+ this._cancelButton.focus();
363
325
  }
364
326
 
365
327
  /**
@@ -368,7 +330,126 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
368
330
  scrollToDate(date, animate) {
369
331
  const offset = this.__useSubMonthScrolling ? this._calculateWeekScrollOffset(date) : 0;
370
332
  this._scrollToPosition(this._differenceInMonths(date, this._originDate) + offset, animate);
371
- this.$.monthScroller.forceUpdate();
333
+ this._monthScroller.forceUpdate();
334
+ }
335
+
336
+ __initMonthScroller() {
337
+ this.addController(
338
+ new SlotController(
339
+ this,
340
+ 'months',
341
+ () => document.createElement('vaadin-date-picker-month-scroller'),
342
+ (_, scroller) => {
343
+ scroller.addEventListener('custom-scroll', () => {
344
+ this._onMonthScroll();
345
+ });
346
+
347
+ scroller.addEventListener('touchstart', () => {
348
+ this._onMonthScrollTouchStart();
349
+ });
350
+
351
+ scroller.addEventListener('keydown', (e) => {
352
+ this.__onMonthCalendarKeyDown(e);
353
+ });
354
+
355
+ scroller.addEventListener('init-done', () => {
356
+ const calendars = [...this.querySelectorAll('vaadin-month-calendar')];
357
+
358
+ // Two-way binding for selectedDate property
359
+ calendars.forEach((calendar) => {
360
+ calendar.addEventListener('selected-date-changed', (e) => {
361
+ this.selectedDate = e.detail.value;
362
+ });
363
+ });
364
+
365
+ this.calendars = calendars;
366
+ });
367
+
368
+ this._monthScroller = scroller;
369
+ },
370
+ ),
371
+ );
372
+ }
373
+
374
+ __initYearScroller() {
375
+ this.addController(
376
+ new SlotController(
377
+ this,
378
+ 'years',
379
+ () => document.createElement('vaadin-date-picker-year-scroller'),
380
+ (_, scroller) => {
381
+ scroller.setAttribute('aria-hidden', 'true');
382
+
383
+ addListener(scroller, 'tap', (e) => {
384
+ this._onYearTap(e);
385
+ });
386
+
387
+ scroller.addEventListener('custom-scroll', () => {
388
+ this._onYearScroll();
389
+ });
390
+
391
+ scroller.addEventListener('touchstart', () => {
392
+ this._onYearScrollTouchStart();
393
+ });
394
+
395
+ scroller.addEventListener('init-done', () => {
396
+ this.years = [...this.querySelectorAll('vaadin-date-picker-year')];
397
+ });
398
+
399
+ this._yearScroller = scroller;
400
+ },
401
+ ),
402
+ );
403
+ }
404
+
405
+ __updateCancelButton(cancelButton, i18n) {
406
+ if (cancelButton) {
407
+ cancelButton.textContent = i18n && i18n.cancel;
408
+ }
409
+ }
410
+
411
+ __updateTodayButton(todayButton, i18n, minDate, maxDate) {
412
+ if (todayButton) {
413
+ todayButton.textContent = i18n && i18n.today;
414
+ todayButton.disabled = !this._isTodayAllowed(minDate, maxDate);
415
+ }
416
+ }
417
+
418
+ // eslint-disable-next-line max-params
419
+ __updateCalendars(calendars, i18n, minDate, maxDate, selectedDate, focusedDate, showWeekNumbers, ignoreTaps, theme) {
420
+ if (calendars && calendars.length) {
421
+ calendars.forEach((calendar) => {
422
+ calendar.setProperties({
423
+ i18n,
424
+ minDate,
425
+ maxDate,
426
+ focusedDate,
427
+ selectedDate,
428
+ showWeekNumbers,
429
+ ignoreTaps,
430
+ });
431
+
432
+ if (theme) {
433
+ calendar.setAttribute('theme', theme);
434
+ } else {
435
+ calendar.removeAttribute('theme');
436
+ }
437
+ });
438
+ }
439
+ }
440
+
441
+ __updateYears(years, selectedDate, theme) {
442
+ if (years && years.length) {
443
+ years.forEach((year) => {
444
+ year.selectedDate = selectedDate;
445
+
446
+ if (theme) {
447
+ year.setAttribute('theme', theme);
448
+ } else {
449
+ year.removeAttribute('theme');
450
+ }
451
+ });
452
+ }
372
453
  }
373
454
 
374
455
  /**
@@ -382,18 +463,12 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
382
463
  );
383
464
  }
384
465
 
385
- _focusedDateChanged(focusedDate) {
386
- this.revealDate(focusedDate);
387
- }
388
-
389
- _isCurrentYear(yearsFromNow) {
390
- return yearsFromNow === 0;
466
+ _desktopModeChanged(desktopMode) {
467
+ this.toggleAttribute('desktop', desktopMode);
391
468
  }
392
469
 
393
- _isSelectedYear(yearsFromNow, selectedDate) {
394
- if (selectedDate) {
395
- return selectedDate.getFullYear() === this._originDate.getFullYear() + yearsFromNow;
396
- }
470
+ _focusedDateChanged(focusedDate) {
471
+ this.revealDate(focusedDate);
397
472
  }
398
473
 
399
474
  /**
@@ -413,14 +488,14 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
413
488
  }
414
489
 
415
490
  // Otherwise determine if we need to scroll to make the month of the date visible
416
- const scrolledAboveViewport = this.$.monthScroller.position > diff;
491
+ const scrolledAboveViewport = this._monthScroller.position > diff;
417
492
 
418
493
  const visibleArea = Math.max(
419
- this.$.monthScroller.itemHeight,
420
- this.$.monthScroller.clientHeight - this.$.monthScroller.bufferOffset * 2,
494
+ this._monthScroller.itemHeight,
495
+ this._monthScroller.clientHeight - this._monthScroller.bufferOffset * 2,
421
496
  );
422
- const visibleItems = visibleArea / this.$.monthScroller.itemHeight;
423
- const scrolledBelowViewport = this.$.monthScroller.position + visibleItems - 1 < diff;
497
+ const visibleItems = visibleArea / this._monthScroller.itemHeight;
498
+ const scrolledBelowViewport = this._monthScroller.position + visibleItems - 1 < diff;
424
499
 
425
500
  if (scrolledAboveViewport) {
426
501
  this._scrollToPosition(diff, animate);
@@ -460,17 +535,23 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
460
535
  }
461
536
 
462
537
  _initialPositionChanged(initialPosition) {
538
+ if (this._monthScroller && this._yearScroller) {
539
+ this._monthScroller.active = true;
540
+ this._yearScroller.active = true;
541
+ }
542
+
463
543
  this.scrollToDate(initialPosition);
464
544
  }
465
545
 
466
546
  _repositionYearScroller() {
467
- this._visibleMonthIndex = Math.floor(this.$.monthScroller.position);
468
- this.$.yearScroller.position = (this.$.monthScroller.position + this._originDate.getMonth()) / 12;
547
+ const monthPosition = this._monthScroller.position;
548
+ this._visibleMonthIndex = Math.floor(monthPosition);
549
+ this._yearScroller.position = (monthPosition + this._originDate.getMonth()) / 12;
469
550
  }
470
551
 
471
552
  _repositionMonthScroller() {
472
- this.$.monthScroller.position = this.$.yearScroller.position * 12 - this._originDate.getMonth();
473
- this._visibleMonthIndex = Math.floor(this.$.monthScroller.position);
553
+ this._monthScroller.position = this._yearScroller.position * 12 - this._originDate.getMonth();
554
+ this._visibleMonthIndex = Math.floor(this._monthScroller.position);
474
555
  }
475
556
 
476
557
  _onMonthScroll() {
@@ -513,7 +594,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
513
594
  _onTodayTap() {
514
595
  const today = new Date();
515
596
 
516
- if (Math.abs(this.$.monthScroller.position - this._differenceInMonths(today, this._originDate)) < 0.001) {
597
+ if (Math.abs(this._monthScroller.position - this._differenceInMonths(today, this._originDate)) < 0.001) {
517
598
  // Select today only if the month scroller is positioned approximately
518
599
  // at the beginning of the current month
519
600
  this._selectDate(today);
@@ -534,9 +615,9 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
534
615
  _onYearTap(e) {
535
616
  if (!this._ignoreTaps && !this._notTapping) {
536
617
  const scrollDelta =
537
- e.detail.y - (this.$.yearScroller.getBoundingClientRect().top + this.$.yearScroller.clientHeight / 2);
538
- const yearDelta = scrollDelta / this.$.yearScroller.itemHeight;
539
- this._scrollToPosition(this.$.monthScroller.position + yearDelta * 12, true);
618
+ e.detail.y - (this._yearScroller.getBoundingClientRect().top + this._yearScroller.clientHeight / 2);
619
+ const yearDelta = scrollDelta / this._yearScroller.itemHeight;
620
+ this._scrollToPosition(this._monthScroller.position + yearDelta * 12, true);
540
621
  }
541
622
  }
542
623
 
@@ -547,7 +628,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
547
628
  }
548
629
 
549
630
  if (!animate) {
550
- this.$.monthScroller.position = targetPosition;
631
+ this._monthScroller.position = targetPosition;
551
632
  this._targetPosition = undefined;
552
633
  this._repositionYearScroller();
553
634
  this.__tryFocusDate();
@@ -572,7 +653,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
572
653
  };
573
654
 
574
655
  let start = 0;
575
- const initialPosition = this.$.monthScroller.position;
656
+ const initialPosition = this._monthScroller.position;
576
657
 
577
658
  const smoothScroll = (timestamp) => {
578
659
  start = start || timestamp;
@@ -585,7 +666,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
585
666
  this._targetPosition - initialPosition,
586
667
  this.scrollDuration,
587
668
  );
588
- this.$.monthScroller.position = currentPos;
669
+ this._monthScroller.position = currentPos;
589
670
  window.requestAnimationFrame(smoothScroll);
590
671
  } else {
591
672
  this.dispatchEvent(
@@ -599,7 +680,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
599
680
  }),
600
681
  );
601
682
 
602
- this.$.monthScroller.position = this._targetPosition;
683
+ this._monthScroller.position = this._targetPosition;
603
684
  this._targetPosition = undefined;
604
685
 
605
686
  revealResolve();
@@ -694,26 +775,13 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
694
775
 
695
776
  _translateXChanged(x) {
696
777
  if (!this._desktopMode) {
697
- this.$.monthScroller.style.transform = `translateX(${x - this._yearScrollerWidth}px)`;
698
- this.$.yearScroller.style.transform = `translateX(${x}px)`;
778
+ this._monthScroller.style.transform = `translateX(${x - this._yearScrollerWidth}px)`;
779
+ this._yearScroller.style.transform = `translateX(${x}px)`;
699
780
  }
700
781
  }
701
782
 
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
783
  _yearAfterXMonths(months) {
709
- return this._dateAfterXMonths(months).getFullYear();
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;
784
+ return dateAfterXMonths(months).getFullYear();
717
785
  }
718
786
 
719
787
  _differenceInMonths(date1, date2) {
@@ -817,7 +885,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
817
885
 
818
886
  if (this.hasAttribute('fullscreen')) {
819
887
  // Trap focus in the overlay
820
- this.$.cancelButton.focus();
888
+ this.focusCancel();
821
889
  } else {
822
890
  this.__focusInput();
823
891
  }
@@ -890,7 +958,11 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
890
958
  // Wait for `vaadin-month-calendar` elements to be rendered
891
959
  if (!this.calendars.length) {
892
960
  await new Promise((resolve) => {
893
- setTimeout(resolve);
961
+ afterNextRender(this, () => {
962
+ // Force dom-repeat elements to render
963
+ flush();
964
+ resolve();
965
+ });
894
966
  });
895
967
  }
896
968
 
@@ -3,15 +3,26 @@
3
3
  * Copyright (c) 2016 - 2022 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { DisableUpgradeMixin } from '@polymer/polymer/lib/mixins/disable-upgrade-mixin.js';
7
6
  import { Overlay } from '@vaadin/overlay/src/vaadin-overlay.js';
8
7
  import { PositionMixin } from '@vaadin/overlay/src/vaadin-overlay-position-mixin.js';
9
- import { registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
10
- import { datePickerOverlayStyles } from './vaadin-date-picker-styles.js';
8
+ import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
11
9
 
12
- registerStyles('vaadin-date-picker-overlay', datePickerOverlayStyles, {
13
- moduleId: 'vaadin-date-picker-overlay-styles',
14
- });
10
+ registerStyles(
11
+ 'vaadin-date-picker-overlay',
12
+ css`
13
+ [part='overlay'] {
14
+ display: flex;
15
+ flex: auto;
16
+ }
17
+
18
+ [part~='content'] {
19
+ flex: auto;
20
+ }
21
+ `,
22
+ {
23
+ moduleId: 'vaadin-date-picker-overlay-styles',
24
+ },
25
+ );
15
26
 
16
27
  let memoizedTemplate;
17
28
 
@@ -21,7 +32,7 @@ let memoizedTemplate;
21
32
  * @extends Overlay
22
33
  * @private
23
34
  */
24
- class DatePickerOverlay extends DisableUpgradeMixin(PositionMixin(Overlay)) {
35
+ class DatePickerOverlay extends PositionMixin(Overlay) {
25
36
  static get is() {
26
37
  return 'vaadin-date-picker-overlay';
27
38
  }