@vaadin/date-picker 23.0.0-alpha1 → 23.0.0-alpha5

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/date-picker",
3
- "version": "23.0.0-alpha1",
3
+ "version": "23.0.0-alpha5",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "main": "vaadin-date-picker.js",
20
20
  "module": "vaadin-date-picker.js",
21
+ "type": "module",
21
22
  "files": [
22
23
  "src",
23
24
  "theme",
@@ -32,24 +33,23 @@
32
33
  ],
33
34
  "dependencies": {
34
35
  "@open-wc/dedupe-mixin": "^1.3.0",
35
- "@polymer/iron-a11y-announcer": "^3.0.0",
36
36
  "@polymer/iron-media-query": "^3.0.0",
37
37
  "@polymer/polymer": "^3.2.0",
38
- "@vaadin/button": "23.0.0-alpha1",
39
- "@vaadin/component-base": "23.0.0-alpha1",
40
- "@vaadin/field-base": "23.0.0-alpha1",
41
- "@vaadin/input-container": "23.0.0-alpha1",
42
- "@vaadin/vaadin-lumo-styles": "23.0.0-alpha1",
43
- "@vaadin/vaadin-material-styles": "23.0.0-alpha1",
44
- "@vaadin/vaadin-overlay": "23.0.0-alpha1",
45
- "@vaadin/vaadin-themable-mixin": "23.0.0-alpha1"
38
+ "@vaadin/button": "23.0.0-alpha5",
39
+ "@vaadin/component-base": "23.0.0-alpha5",
40
+ "@vaadin/field-base": "23.0.0-alpha5",
41
+ "@vaadin/input-container": "23.0.0-alpha5",
42
+ "@vaadin/vaadin-lumo-styles": "23.0.0-alpha5",
43
+ "@vaadin/vaadin-material-styles": "23.0.0-alpha5",
44
+ "@vaadin/vaadin-overlay": "23.0.0-alpha5",
45
+ "@vaadin/vaadin-themable-mixin": "23.0.0-alpha5"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@esm-bundle/chai": "^4.3.4",
49
- "@vaadin/dialog": "23.0.0-alpha1",
50
- "@vaadin/polymer-legacy-adapter": "23.0.0-alpha1",
49
+ "@vaadin/dialog": "23.0.0-alpha5",
50
+ "@vaadin/polymer-legacy-adapter": "23.0.0-alpha5",
51
51
  "@vaadin/testing-helpers": "^0.3.2",
52
52
  "sinon": "^9.2.0"
53
53
  },
54
- "gitHead": "fbcb07328fdf88260e3b461088d207426b21c710"
54
+ "gitHead": "74f9294964eb8552d96578c14af6ad214f5257bc"
55
55
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
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
6
 
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
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
6
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
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
6
  import '@polymer/iron-media-query/iron-media-query.js';
@@ -74,6 +74,8 @@ class DatePickerLight extends ThemableMixin(DatePickerMixin(PolymerElement)) {
74
74
  opened="{{opened}}"
75
75
  on-vaadin-overlay-open="_onOverlayOpened"
76
76
  on-vaadin-overlay-close="_onOverlayClosed"
77
+ restore-focus-on-close
78
+ restore-focus-node="[[inputElement]]"
77
79
  theme$="[[__getOverlayTheme(theme, _overlayInitialized)]]"
78
80
  >
79
81
  <template>
@@ -137,17 +139,17 @@ class DatePickerLight extends ThemableMixin(DatePickerMixin(PolymerElement)) {
137
139
  this._setFocusElement(this.inputElement);
138
140
  }
139
141
 
142
+ /** @return {string | undefined} */
143
+ get _inputValue() {
144
+ return this.inputElement && this.inputElement[dashToCamelCase(this.attrForValue)];
145
+ }
146
+
140
147
  set _inputValue(value) {
141
148
  if (this.inputElement) {
142
149
  this.inputElement[dashToCamelCase(this.attrForValue)] = value;
143
150
  }
144
151
  }
145
152
 
146
- /** @return {string | undefined} */
147
- get _inputValue() {
148
- return this.inputElement && this.inputElement[dashToCamelCase(this.attrForValue)];
149
- }
150
-
151
153
  // Workaround https://github.com/vaadin/web-components/issues/2855
152
154
  /** @protected */
153
155
  _openedChanged(opened) {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
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
6
  import { Constructor } from '@open-wc/dedupe-mixin';
@@ -1,20 +1,22 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
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 { addListener } from '@polymer/polymer/lib/utils/gestures.js';
7
6
  import { isIOS } from '@vaadin/component-base/src/browser-utils.js';
7
+ import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
8
8
  import { KeyboardMixin } from '@vaadin/component-base/src/keyboard-mixin.js';
9
9
  import { DelegateFocusMixin } from '@vaadin/field-base/src/delegate-focus-mixin.js';
10
10
  import { InputMixin } from '@vaadin/field-base/src/input-mixin.js';
11
+ import { VirtualKeyboardController } from '@vaadin/field-base/src/virtual-keyboard-controller.js';
11
12
  import { dateAllowed, dateEquals, extractDateParts, getClosestDate } from './vaadin-date-picker-helper.js';
12
13
 
13
14
  /**
14
15
  * @polymerMixin
16
+ * @param {function(new:HTMLElement)} subclass
15
17
  */
16
18
  export const DatePickerMixin = (subclass) =>
17
- class VaadinDatePickerMixin extends DelegateFocusMixin(InputMixin(KeyboardMixin(subclass))) {
19
+ class VaadinDatePickerMixin extends ControllerMixin(DelegateFocusMixin(InputMixin(KeyboardMixin(subclass)))) {
18
20
  static get properties() {
19
21
  return {
20
22
  /**
@@ -302,7 +304,7 @@ export const DatePickerMixin = (subclass) =>
302
304
  /** @private */
303
305
  _noInput: {
304
306
  type: Boolean,
305
- computed: '_isNoInput(inputElement, _fullscreen, _ios, i18n, i18n.*)'
307
+ computed: '_isNoInput(inputElement, _fullscreen, _ios, i18n, opened, autoOpenDisabled)'
306
308
  },
307
309
 
308
310
  /** @private */
@@ -349,6 +351,11 @@ export const DatePickerMixin = (subclass) =>
349
351
  return null;
350
352
  }
351
353
 
354
+ /** @protected */
355
+ get _inputValue() {
356
+ return this.inputElement ? this.inputElement.value : undefined;
357
+ }
358
+
352
359
  /** @protected */
353
360
  set _inputValue(value) {
354
361
  if (this.inputElement) {
@@ -356,11 +363,6 @@ export const DatePickerMixin = (subclass) =>
356
363
  }
357
364
  }
358
365
 
359
- /** @protected */
360
- get _inputValue() {
361
- return this.inputElement ? this.inputElement.value : undefined;
362
- }
363
-
364
366
  /** @private */
365
367
  get _nativeInput() {
366
368
  if (this.inputElement) {
@@ -415,17 +417,13 @@ export const DatePickerMixin = (subclass) =>
415
417
  ready() {
416
418
  super.ready();
417
419
 
418
- addListener(this, 'tap', (e) => {
420
+ this.addEventListener('click', (e) => {
419
421
  if (!this._isClearButton(e) && (!this.autoOpenDisabled || this._noInput)) {
420
422
  this.open();
421
423
  }
422
424
  });
423
425
 
424
- this.addEventListener('touchend', (e) => {
425
- if (!this._isClearButton(e)) {
426
- e.preventDefault();
427
- }
428
- });
426
+ this.addController(new VirtualKeyboardController(this));
429
427
  }
430
428
 
431
429
  /** @protected */
@@ -541,8 +539,17 @@ export const DatePickerMixin = (subclass) =>
541
539
  }
542
540
 
543
541
  /** @private */
544
- _isNoInput(inputElement, fullscreen, ios, i18n) {
545
- return !inputElement || fullscreen || ios || !i18n.parseDate;
542
+ // eslint-disable-next-line max-params
543
+ _isNoInput(inputElement, fullscreen, ios, i18n, opened, autoOpenDisabled) {
544
+ // On fullscreen mode, text input is disabled if auto-open isn't disabled or
545
+ // whenever the dropdown is opened
546
+ const noInputOnFullscreenMode = fullscreen && (!autoOpenDisabled || opened);
547
+ // On iOS, text input is disabled whenever the dropdown is opened, because
548
+ // the virtual keyboard doesn't affect the viewport metrics and thus the
549
+ // dropdown could get covered by the keyboard.
550
+ const noInputOnIos = ios && opened;
551
+
552
+ return !inputElement || noInputOnFullscreenMode || noInputOnIos || !i18n.parseDate;
546
553
  }
547
554
 
548
555
  /** @private */
@@ -575,6 +582,7 @@ export const DatePickerMixin = (subclass) =>
575
582
  _inputElementChanged(input) {
576
583
  super._inputElementChanged(input);
577
584
  if (input) {
585
+ input.autocomplete = 'off';
578
586
  input.setAttribute('role', 'combobox');
579
587
  input.setAttribute('aria-expanded', !!this.opened);
580
588
  this._applyInputValue(this._selectedDate);
@@ -901,15 +909,13 @@ export const DatePickerMixin = (subclass) =>
901
909
  this._selectedDate = this._overlayContent.focusedDate;
902
910
  }
903
911
  this.close();
912
+ } else if (!isValidDate && this.inputElement.value !== '') {
913
+ this.validate();
904
914
  } else {
905
- if (!isValidDate && this.inputElement.value !== '') {
915
+ const oldValue = this.value;
916
+ this._selectParsedOrFocusedDate();
917
+ if (oldValue === this.value) {
906
918
  this.validate();
907
- } else {
908
- const oldValue = this.value;
909
- this._selectParsedOrFocusedDate();
910
- if (oldValue === this.value) {
911
- this.validate();
912
- }
913
919
  }
914
920
  }
915
921
  break;
@@ -921,7 +927,7 @@ export const DatePickerMixin = (subclass) =>
921
927
  } else if (this.clearButtonVisible) {
922
928
  this._onClearButtonClick();
923
929
  } else if (this.autoOpenDisabled) {
924
- //Do not restore selected date if Esc was pressed after clearing input field
930
+ // Do not restore selected date if Esc was pressed after clearing input field
925
931
  if (this.inputElement.value === '') {
926
932
  this._selectedDate = null;
927
933
  }
@@ -934,7 +940,7 @@ export const DatePickerMixin = (subclass) =>
934
940
  case 'Tab':
935
941
  if (this.opened) {
936
942
  e.preventDefault();
937
- //Clear the selection range (remains visible on IE)
943
+ // Clear the selection range (remains visible on IE)
938
944
  this._setSelectionRange(0, 0);
939
945
  if (e.shiftKey) {
940
946
  this._overlayContent.focusCancel();
@@ -944,6 +950,8 @@ export const DatePickerMixin = (subclass) =>
944
950
  }
945
951
  }
946
952
  break;
953
+ default:
954
+ break;
947
955
  }
948
956
  }
949
957
 
@@ -1,19 +1,18 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
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
6
  import '@polymer/iron-media-query/iron-media-query.js';
7
7
  import '@vaadin/button/src/vaadin-button.js';
8
8
  import './vaadin-month-calendar.js';
9
9
  import './vaadin-infinite-scroller.js';
10
- import { IronA11yAnnouncer } from '@polymer/iron-a11y-announcer/iron-a11y-announcer.js';
11
- import { GestureEventListeners } from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
12
- import { addListener, setTouchAction } from '@polymer/polymer/lib/utils/gestures.js';
13
10
  import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
11
+ import { announce } from '@vaadin/component-base/src/a11y-announcer.js';
14
12
  import { timeOut } from '@vaadin/component-base/src/async.js';
15
13
  import { Debouncer } from '@vaadin/component-base/src/debounce.js';
16
14
  import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
15
+ import { addListener, setTouchAction } from '@vaadin/component-base/src/gestures.js';
17
16
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
18
17
  import { dateEquals, extractDateParts, getClosestDate, getISOWeekNumber } from './vaadin-date-picker-helper.js';
19
18
 
@@ -21,7 +20,7 @@ import { dateEquals, extractDateParts, getClosestDate, getISOWeekNumber } from '
21
20
  * @extends HTMLElement
22
21
  * @private
23
22
  */
24
- class DatePickerOverlayContent extends ThemableMixin(DirMixin(GestureEventListeners(PolymerElement))) {
23
+ class DatePickerOverlayContent extends ThemableMixin(DirMixin(PolymerElement)) {
25
24
  static get template() {
26
25
  return html`
27
26
  <style>
@@ -164,15 +163,15 @@ class DatePickerOverlayContent extends ThemableMixin(DirMixin(GestureEventListen
164
163
 
165
164
  <div part="overlay-header" on-touchend="_preventDefault" desktop$="[[_desktopMode]]" aria-hidden="true">
166
165
  <div part="label">[[_formatDisplayed(selectedDate, i18n.formatDate, label)]]</div>
167
- <div part="clear-button" on-tap="_clear" showclear$="[[_showClear(selectedDate)]]"></div>
168
- <div part="toggle-button" on-tap="_cancel"></div>
166
+ <div part="clear-button" showclear$="[[_showClear(selectedDate)]]"></div>
167
+ <div part="toggle-button"></div>
169
168
 
170
- <div part="years-toggle-button" desktop$="[[_desktopMode]]" on-tap="_toggleYearScroller" aria-hidden="true">
169
+ <div part="years-toggle-button" desktop$="[[_desktopMode]]" aria-hidden="true">
171
170
  [[_yearAfterXMonths(_visibleMonthIndex)]]
172
171
  </div>
173
172
  </div>
174
173
 
175
- <div id="scrollers" desktop$="[[_desktopMode]]" on-track="_track">
174
+ <div id="scrollers" desktop$="[[_desktopMode]]">
176
175
  <vaadin-infinite-scroller
177
176
  id="monthScroller"
178
177
  on-custom-scroll="_onMonthScroll"
@@ -200,7 +199,6 @@ class DatePickerOverlayContent extends ThemableMixin(DirMixin(GestureEventListen
200
199
  </vaadin-infinite-scroller>
201
200
  <vaadin-infinite-scroller
202
201
  id="yearScroller"
203
- on-tap="_onYearTap"
204
202
  on-custom-scroll="_onYearScroll"
205
203
  on-touchstart="_onYearScrollTouchStart"
206
204
  buffer-size="12"
@@ -227,13 +225,10 @@ class DatePickerOverlayContent extends ThemableMixin(DirMixin(GestureEventListen
227
225
  part="today-button"
228
226
  theme="tertiary"
229
227
  disabled="[[!_isTodayAllowed(minDate, maxDate)]]"
230
- on-tap="_onTodayTap"
231
228
  >
232
229
  [[i18n.today]]
233
230
  </vaadin-button>
234
- <vaadin-button id="cancelButton" part="cancel-button" theme="tertiary" on-tap="_cancel">
235
- [[i18n.cancel]]
236
- </vaadin-button>
231
+ <vaadin-button id="cancelButton" part="cancel-button" theme="tertiary"> [[i18n.cancel]] </vaadin-button>
237
232
  </div>
238
233
  <iron-media-query query="(min-width: 375px)" query-matches="{{_desktopMode}}"></iron-media-query>
239
234
  `;
@@ -330,6 +325,17 @@ class DatePickerOverlayContent extends ThemableMixin(DirMixin(GestureEventListen
330
325
  addListener(this, 'tap', this._stopPropagation);
331
326
  this.addEventListener('focus', this._onOverlayFocus.bind(this));
332
327
  this.addEventListener('blur', this._onOverlayBlur.bind(this));
328
+ addListener(this.$.scrollers, 'track', this._track.bind(this));
329
+ addListener(this.shadowRoot.querySelector('[part="clear-button"]'), 'tap', this._clear.bind(this));
330
+ addListener(this.shadowRoot.querySelector('[part="today-button"]'), 'tap', this._onTodayTap.bind(this));
331
+ addListener(this.shadowRoot.querySelector('[part="cancel-button"]'), 'tap', this._cancel.bind(this));
332
+ addListener(this.shadowRoot.querySelector('[part="toggle-button"]'), 'tap', this._cancel.bind(this));
333
+ addListener(this.shadowRoot.querySelector('[part="years"]'), 'tap', this._onYearTap.bind(this));
334
+ addListener(
335
+ this.shadowRoot.querySelector('[part="years-toggle-button"]'),
336
+ 'tap',
337
+ this._toggleYearScroller.bind(this)
338
+ );
333
339
  }
334
340
 
335
341
  /**
@@ -344,35 +350,25 @@ class DatePickerOverlayContent extends ThemableMixin(DirMixin(GestureEventListen
344
350
  this._closeYearScroller();
345
351
  this._toggleAnimateClass(true);
346
352
  setTouchAction(this.$.scrollers, 'pan-y');
347
- IronA11yAnnouncer.requestAvailability();
348
353
  }
349
354
 
350
355
  announceFocusedDate() {
351
- var focusedDate = this._currentlyFocusedDate();
352
- var announce = [];
356
+ const focusedDate = this._currentlyFocusedDate();
357
+ let messages = [];
353
358
  if (dateEquals(focusedDate, new Date())) {
354
- announce.push(this.i18n.today);
359
+ messages.push(this.i18n.today);
355
360
  }
356
- announce = announce.concat([
361
+ messages = messages.concat([
357
362
  this.i18n.weekdays[focusedDate.getDay()],
358
363
  focusedDate.getDate(),
359
364
  this.i18n.monthNames[focusedDate.getMonth()],
360
365
  focusedDate.getFullYear()
361
366
  ]);
362
367
  if (this.showWeekNumbers && this.i18n.firstDayOfWeek === 1) {
363
- announce.push(this.i18n.week);
364
- announce.push(getISOWeekNumber(focusedDate));
368
+ messages.push(this.i18n.week);
369
+ messages.push(getISOWeekNumber(focusedDate));
365
370
  }
366
- this.dispatchEvent(
367
- new CustomEvent('iron-announce', {
368
- bubbles: true,
369
- composed: true,
370
- detail: {
371
- text: announce.join(' ')
372
- }
373
- })
374
- );
375
- return;
371
+ announce(messages.join(' '));
376
372
  }
377
373
 
378
374
  /**
@@ -406,18 +402,22 @@ class DatePickerOverlayContent extends ThemableMixin(DirMixin(GestureEventListen
406
402
  /**
407
403
  * Scrolls the month and year scrollers enough to reveal the given date.
408
404
  */
409
- revealDate(date) {
405
+ revealDate(date, animate = true) {
410
406
  if (date) {
411
- var diff = this._differenceInMonths(date, this._originDate);
412
- var scrolledAboveViewport = this.$.monthScroller.position > diff;
407
+ const diff = this._differenceInMonths(date, this._originDate);
408
+ const scrolledAboveViewport = this.$.monthScroller.position > diff;
413
409
 
414
- var visibleItems = this.$.monthScroller.clientHeight / this.$.monthScroller.itemHeight;
415
- var scrolledBelowViewport = this.$.monthScroller.position + visibleItems - 1 < diff;
410
+ const visibleArea = Math.max(
411
+ this.$.monthScroller.itemHeight,
412
+ this.$.monthScroller.clientHeight - this.$.monthScroller.bufferOffset * 2
413
+ );
414
+ const visibleItems = visibleArea / this.$.monthScroller.itemHeight;
415
+ const scrolledBelowViewport = this.$.monthScroller.position + visibleItems - 1 < diff;
416
416
 
417
417
  if (scrolledAboveViewport) {
418
- this._scrollToPosition(diff, true);
418
+ this._scrollToPosition(diff, animate);
419
419
  } else if (scrolledBelowViewport) {
420
- this._scrollToPosition(diff - visibleItems + 1, true);
420
+ this._scrollToPosition(diff - visibleItems + 1, animate);
421
421
  }
422
422
  }
423
423
  }
@@ -473,9 +473,8 @@ class DatePickerOverlayContent extends ThemableMixin(DirMixin(GestureEventListen
473
473
  _formatDisplayed(date, formatDate, label) {
474
474
  if (date) {
475
475
  return formatDate(extractDateParts(date));
476
- } else {
477
- return label;
478
476
  }
477
+ return label;
479
478
  }
480
479
 
481
480
  _onTodayTap() {
@@ -533,7 +532,7 @@ class DatePickerOverlayContent extends ThemableMixin(DirMixin(GestureEventListen
533
532
  if (t < 1) {
534
533
  return (c / 2) * t * t + b;
535
534
  }
536
- t--;
535
+ t -= 1;
537
536
  return (-c / 2) * (t * (t - 2) - 1) + b;
538
537
  };
539
538
 
@@ -605,11 +604,9 @@ class DatePickerOverlayContent extends ThemableMixin(DirMixin(GestureEventListen
605
604
  case 'start':
606
605
  this._toggleAnimateClass(false);
607
606
  break;
608
-
609
607
  case 'track':
610
608
  this._handleTrack(e);
611
609
  break;
612
-
613
610
  case 'end':
614
611
  this._toggleAnimateClass(true);
615
612
  if (this._translateX >= this._yearScrollerWidth / 2) {
@@ -618,6 +615,8 @@ class DatePickerOverlayContent extends ThemableMixin(DirMixin(GestureEventListen
618
615
  this._openYearScroller();
619
616
  }
620
617
  break;
618
+ default:
619
+ break;
621
620
  }
622
621
  }
623
622
 
@@ -811,6 +810,8 @@ class DatePickerOverlayContent extends ThemableMixin(DirMixin(GestureEventListen
811
810
  case 'Escape':
812
811
  this._cancel();
813
812
  break;
813
+ default:
814
+ break;
814
815
  }
815
816
  }
816
817
  }
@@ -837,20 +838,18 @@ class DatePickerOverlayContent extends ThemableMixin(DirMixin(GestureEventListen
837
838
 
838
839
  if (this._dateAllowed(dateToFocus, this.minDate, this.maxDate)) {
839
840
  this._focusDate(dateToFocus);
840
- } else {
841
- if (this._dateAllowed(focus, this.minDate, this.maxDate)) {
842
- // Move to min or max date
843
- if (days > 0) {
844
- // down or right
845
- this._focusDate(this.maxDate);
846
- } else {
847
- // up or left
848
- this._focusDate(this.minDate);
849
- }
841
+ } else if (this._dateAllowed(focus, this.minDate, this.maxDate)) {
842
+ // Move to min or max date
843
+ if (days > 0) {
844
+ // down or right
845
+ this._focusDate(this.maxDate);
850
846
  } else {
851
- // Move to closest allowed date
852
- this._focusClosestDate(focus);
847
+ // up or left
848
+ this._focusDate(this.minDate);
853
849
  }
850
+ } else {
851
+ // Move to closest allowed date
852
+ this._focusClosestDate(focus);
854
853
  }
855
854
  }
856
855
 
@@ -869,20 +868,18 @@ class DatePickerOverlayContent extends ThemableMixin(DirMixin(GestureEventListen
869
868
 
870
869
  if (this._dateAllowed(dateToFocus, this.minDate, this.maxDate)) {
871
870
  this.focusedDate = dateToFocus;
872
- } else {
873
- if (this._dateAllowed(focus, this.minDate, this.maxDate)) {
874
- // Move to min or max date
875
- if (months > 0) {
876
- // pagedown
877
- this._focusDate(this.maxDate);
878
- } else {
879
- // pageup
880
- this._focusDate(this.minDate);
881
- }
871
+ } else if (this._dateAllowed(focus, this.minDate, this.maxDate)) {
872
+ // Move to min or max date
873
+ if (months > 0) {
874
+ // pagedown
875
+ this._focusDate(this.maxDate);
882
876
  } else {
883
- // Move to closest allowed date
884
- this._focusClosestDate(focus);
877
+ // pageup
878
+ this._focusDate(this.minDate);
885
879
  }
880
+ } else {
881
+ // Move to closest allowed date
882
+ this._focusClosestDate(focus);
886
883
  }
887
884
  }
888
885
 
@@ -900,14 +897,12 @@ class DatePickerOverlayContent extends ThemableMixin(DirMixin(GestureEventListen
900
897
 
901
898
  if (this._dateAllowed(dateToFocus, this.minDate, this.maxDate)) {
902
899
  this._focusDate(dateToFocus);
900
+ } else if (this._dateAllowed(focusedDate, this.minDate, this.maxDate)) {
901
+ // Move to minDate or maxDate
902
+ this._focusDate(this[property]);
903
903
  } else {
904
- if (this._dateAllowed(focusedDate, this.minDate, this.maxDate)) {
905
- // Move to minDate or maxDate
906
- this._focusDate(this[property]);
907
- } else {
908
- // Move to closest allowed date
909
- this._focusClosestDate(focusedDate);
910
- }
904
+ // Move to closest allowed date
905
+ this._focusClosestDate(focusedDate);
911
906
  }
912
907
  }
913
908
 
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
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
6
  import { DisableUpgradeMixin } from '@polymer/polymer/lib/mixins/disable-upgrade-mixin.js';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
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
6
  import { css } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
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
6
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
@@ -1,15 +1,15 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
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
6
  import '@polymer/iron-media-query/iron-media-query.js';
7
7
  import '@vaadin/input-container/src/vaadin-input-container.js';
8
8
  import './vaadin-date-picker-overlay.js';
9
9
  import './vaadin-date-picker-overlay-content.js';
10
- import { GestureEventListeners } from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
11
10
  import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
12
11
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
12
+ import { addListener } from '@vaadin/component-base/src/gestures.js';
13
13
  import { InputControlMixin } from '@vaadin/field-base/src/input-control-mixin.js';
14
14
  import { InputController } from '@vaadin/field-base/src/input-controller.js';
15
15
  import { LabelledInputController } from '@vaadin/field-base/src/labelled-input-controller.js';
@@ -116,9 +116,7 @@ registerStyles('vaadin-date-picker', [inputFieldShared, datePickerStyles], { mod
116
116
  * @mixes ThemableMixin
117
117
  * @mixes InputControlMixin
118
118
  */
119
- class DatePicker extends DatePickerMixin(
120
- InputControlMixin(GestureEventListeners(ThemableMixin(ElementMixin(PolymerElement))))
121
- ) {
119
+ class DatePicker extends DatePickerMixin(InputControlMixin(ThemableMixin(ElementMixin(PolymerElement)))) {
122
120
  static get is() {
123
121
  return 'vaadin-date-picker';
124
122
  }
@@ -147,7 +145,7 @@ class DatePicker extends DatePickerMixin(
147
145
  <slot name="prefix" slot="prefix"></slot>
148
146
  <slot name="input"></slot>
149
147
  <div id="clearButton" part="clear-button" slot="suffix"></div>
150
- <div part="toggle-button" slot="suffix" on-tap="_toggle" role="button"></div>
148
+ <div part="toggle-button" slot="suffix" role="button"></div>
151
149
  </vaadin-input-container>
152
150
 
153
151
  <div part="helper-text">
@@ -165,6 +163,8 @@ class DatePicker extends DatePickerMixin(
165
163
  theme$="[[__getOverlayTheme(theme, _overlayInitialized)]]"
166
164
  on-vaadin-overlay-open="_onOverlayOpened"
167
165
  on-vaadin-overlay-close="_onOverlayClosed"
166
+ restore-focus-on-close
167
+ restore-focus-node="[[inputElement]]"
168
168
  disable-upgrade
169
169
  >
170
170
  <template>
@@ -212,7 +212,8 @@ class DatePicker extends DatePickerMixin(
212
212
  this.ariaTarget = input;
213
213
  })
214
214
  );
215
- this.addController(new LabelledInputController(this.inputElement, this._labelNode));
215
+ this.addController(new LabelledInputController(this.inputElement, this._labelController));
216
+ addListener(this.shadowRoot.querySelector('[part="toggle-button"]'), 'tap', this._toggle.bind(this));
216
217
  }
217
218
 
218
219
  /** @private */
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
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
6
  import { afterNextRender } from '@polymer/polymer/lib/utils/render-status.js';
@@ -186,9 +186,9 @@ class InfiniteScroller extends PolymerElement {
186
186
  }
187
187
 
188
188
  // Check if we scrolled enough to translate the buffer positions.
189
- const bufferOffset = this.root.querySelector('.buffer').offsetTop;
190
- const upperThresholdReached = scrollTop > this._buffers[1].translateY + this.itemHeight + bufferOffset;
191
- const lowerThresholdReached = scrollTop < this._buffers[0].translateY + this.itemHeight + bufferOffset;
189
+ const offset = this.itemHeight + this.bufferOffset;
190
+ const upperThresholdReached = scrollTop > this._buffers[1].translateY + offset;
191
+ const lowerThresholdReached = scrollTop < this._buffers[0].translateY + offset;
192
192
 
193
193
  if (upperThresholdReached || lowerThresholdReached) {
194
194
  this._translateBuffer(lowerThresholdReached);
@@ -209,10 +209,24 @@ class InfiniteScroller extends PolymerElement {
209
209
  });
210
210
  }
211
211
 
212
+ /**
213
+ * @return {number}
214
+ */
215
+ get bufferOffset() {
216
+ return this._buffers[0].offsetTop;
217
+ }
218
+
219
+ /**
220
+ * @return {number}
221
+ */
222
+ get position() {
223
+ return (this.$.scroller.scrollTop - this._buffers[0].translateY) / this.itemHeight + this._firstIndex;
224
+ }
225
+
212
226
  /**
213
227
  * Current scroller position as index. Can be a fractional number.
214
228
  *
215
- * @type {Number}
229
+ * @type {number}
216
230
  */
217
231
  set position(index) {
218
232
  this._preventScrollEvent = true;
@@ -239,12 +253,8 @@ class InfiniteScroller extends PolymerElement {
239
253
  }
240
254
 
241
255
  /**
242
- * @private
256
+ * @return {number}
243
257
  */
244
- get position() {
245
- return (this.$.scroller.scrollTop - this._buffers[0].translateY) / this.itemHeight + this._firstIndex;
246
- }
247
-
248
258
  get itemHeight() {
249
259
  if (!this._itemHeightVal) {
250
260
  const itemHeight = getComputedStyle(this).getPropertyValue('--vaadin-infinite-scroller-item-height');
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
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
6
  import '@polymer/polymer/lib/elements/dom-repeat.js';
7
- import { GestureEventListeners } from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
8
7
  import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
8
+ import { addListener } from '@vaadin/component-base/src/gestures.js';
9
9
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
10
10
  import { dateAllowed, dateEquals, getISOWeekNumber } from './vaadin-date-picker-helper.js';
11
11
 
@@ -13,7 +13,7 @@ import { dateAllowed, dateEquals, getISOWeekNumber } from './vaadin-date-picker-
13
13
  * @extends HTMLElement
14
14
  * @private
15
15
  */
16
- class MonthCalendar extends ThemableMixin(GestureEventListeners(PolymerElement)) {
16
+ class MonthCalendar extends ThemableMixin(PolymerElement) {
17
17
  static get template() {
18
18
  return html`
19
19
  <style>
@@ -59,7 +59,7 @@ class MonthCalendar extends ThemableMixin(GestureEventListeners(PolymerElement))
59
59
  </style>
60
60
 
61
61
  <div part="month-header" role="heading">[[_getTitle(month, i18n.monthNames)]]</div>
62
- <div id="monthGrid" on-tap="_handleTap" on-touchend="_preventDefault" on-touchstart="_onMonthGridTouchStart">
62
+ <div id="monthGrid" on-touchend="_preventDefault" on-touchstart="_onMonthGridTouchStart">
63
63
  <div id="weekdays-container">
64
64
  <div hidden$="[[!_showWeekSeparator(showWeekNumbers, i18n.firstDayOfWeek)]]" part="weekday"></div>
65
65
  <div part="weekdays">
@@ -174,6 +174,12 @@ class MonthCalendar extends ThemableMixin(GestureEventListeners(PolymerElement))
174
174
  return ['_showWeekNumbersChanged(showWeekNumbers, i18n.firstDayOfWeek)'];
175
175
  }
176
176
 
177
+ /** @protected */
178
+ ready() {
179
+ super.ready();
180
+ addListener(this.$.monthGrid, 'tap', this._handleTap.bind(this));
181
+ }
182
+
177
183
  _dateEquals(date1, date2) {
178
184
  return dateEquals(date1, date2);
179
185
  }
@@ -110,7 +110,7 @@ registerStyles(
110
110
  /* Month scroller */
111
111
 
112
112
  [part='months'] {
113
- --vaadin-infinite-scroller-item-height: 320px;
113
+ --vaadin-infinite-scroller-item-height: 328px;
114
114
  text-align: center;
115
115
  }
116
116