@vaadin/date-picker 23.1.0-beta4 → 23.1.0-rc3

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.1.0-beta4",
3
+ "version": "23.1.0-rc3",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -34,21 +34,19 @@
34
34
  "dependencies": {
35
35
  "@open-wc/dedupe-mixin": "^1.3.0",
36
36
  "@polymer/polymer": "^3.2.0",
37
- "@vaadin/button": "23.1.0-beta4",
38
- "@vaadin/component-base": "23.1.0-beta4",
39
- "@vaadin/field-base": "23.1.0-beta4",
40
- "@vaadin/input-container": "23.1.0-beta4",
41
- "@vaadin/vaadin-lumo-styles": "23.1.0-beta4",
42
- "@vaadin/vaadin-material-styles": "23.1.0-beta4",
43
- "@vaadin/vaadin-overlay": "23.1.0-beta4",
44
- "@vaadin/vaadin-themable-mixin": "23.1.0-beta4"
37
+ "@vaadin/button": "23.1.0-rc3",
38
+ "@vaadin/component-base": "23.1.0-rc3",
39
+ "@vaadin/field-base": "23.1.0-rc3",
40
+ "@vaadin/input-container": "23.1.0-rc3",
41
+ "@vaadin/vaadin-lumo-styles": "23.1.0-rc3",
42
+ "@vaadin/vaadin-material-styles": "23.1.0-rc3",
43
+ "@vaadin/vaadin-overlay": "23.1.0-rc3",
44
+ "@vaadin/vaadin-themable-mixin": "23.1.0-rc3"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@esm-bundle/chai": "^4.3.4",
48
- "@vaadin/dialog": "23.1.0-beta4",
49
- "@vaadin/polymer-legacy-adapter": "23.1.0-beta4",
50
48
  "@vaadin/testing-helpers": "^0.3.2",
51
49
  "sinon": "^13.0.2"
52
50
  },
53
- "gitHead": "06e283473964ecb3085aacf3eddb5333d052a045"
51
+ "gitHead": "49c312fbe0228adb559296d45655bbfd4eac6235"
54
52
  }
@@ -84,13 +84,10 @@ class DatePickerLight extends ThemableMixin(DatePickerMixin(PolymerElement)) {
84
84
  fullscreen$="[[_fullscreen]]"
85
85
  label="[[label]]"
86
86
  selected-date="[[_selectedDate]]"
87
- slot="dropdown-content"
88
87
  focused-date="{{_focusedDate}}"
89
88
  show-week-numbers="[[showWeekNumbers]]"
90
89
  min-date="[[_minDate]]"
91
90
  max-date="[[_maxDate]]"
92
- on-date-tap="_close"
93
- role="dialog"
94
91
  part="overlay-content"
95
92
  theme$="[[__getOverlayTheme(_theme, _overlayInitialized)]]"
96
93
  >
@@ -128,6 +125,13 @@ class DatePickerLight extends ThemableMixin(DatePickerMixin(PolymerElement)) {
128
125
  };
129
126
  }
130
127
 
128
+ /** @protected */
129
+ ready() {
130
+ super.ready();
131
+
132
+ this._initOverlay();
133
+ }
134
+
131
135
  /** @protected */
132
136
  connectedCallback() {
133
137
  super.connectedCallback();
@@ -336,7 +336,7 @@ export const DatePickerMixin = (subclass) =>
336
336
  }
337
337
 
338
338
  /**
339
- * Override a getter from `ClearButtonMixin` to make it optional
339
+ * Override a getter from `InputControlMixin` to make it optional
340
340
  * and to prevent warning when a clear button is missing,
341
341
  * for example when using <vaadin-date-picker-light>.
342
342
  * @protected
@@ -370,6 +370,7 @@ export const DatePickerMixin = (subclass) =>
370
370
  constructor() {
371
371
  super();
372
372
 
373
+ this._boundOnClick = this._onClick.bind(this);
373
374
  this._boundOnScroll = this._onScroll.bind(this);
374
375
  }
375
376
 
@@ -414,11 +415,7 @@ export const DatePickerMixin = (subclass) =>
414
415
  ready() {
415
416
  super.ready();
416
417
 
417
- this.addEventListener('click', (e) => {
418
- if (!this._isClearButton(e) && (!this.autoOpenDisabled || this._noInput)) {
419
- this.open();
420
- }
421
- });
418
+ this.addEventListener('click', this._boundOnClick);
422
419
 
423
420
  this.addController(
424
421
  new MediaQueryController(this._fullscreenMediaQuery, (matches) => {
@@ -473,13 +470,18 @@ export const DatePickerMixin = (subclass) =>
473
470
  }
474
471
  }
475
472
 
476
- /** @private */
473
+ /** @protected */
477
474
  _initOverlay() {
478
475
  this.$.overlay.removeAttribute('disable-upgrade');
479
476
  this._overlayInitialized = true;
480
477
 
481
478
  this.$.overlay.addEventListener('opened-changed', (e) => (this.opened = e.detail.value));
482
479
 
480
+ this.$.overlay.addEventListener('vaadin-overlay-escape-press', () => {
481
+ this._focusedDate = this._selectedDate;
482
+ this._close();
483
+ });
484
+
483
485
  this._overlayContent.addEventListener('close', this._close.bind(this));
484
486
  this._overlayContent.addEventListener('focus-input', this._focusAndSelect.bind(this));
485
487
 
@@ -488,6 +490,8 @@ export const DatePickerMixin = (subclass) =>
488
490
  this.__userConfirmedDate = true;
489
491
 
490
492
  this._selectDate(e.detail.date);
493
+
494
+ this._close(e);
491
495
  });
492
496
 
493
497
  // User confirmed selected date by pressing Enter or Today.
@@ -498,12 +502,10 @@ export const DatePickerMixin = (subclass) =>
498
502
  });
499
503
 
500
504
  // Keep focus attribute in focusElement for styling
501
- this._overlayContent.addEventListener('focus', () => {
505
+ this._overlayContent.addEventListener('focusin', () => {
502
506
  this._setFocused(true);
503
507
  });
504
508
 
505
- this.$.overlay.addEventListener('vaadin-overlay-close', this._onVaadinOverlayClose.bind(this));
506
-
507
509
  this.addEventListener('mousedown', () => this.__bringToFront());
508
510
  this.addEventListener('touchstart', () => this.__bringToFront());
509
511
  }
@@ -767,6 +769,7 @@ export const DatePickerMixin = (subclass) =>
767
769
 
768
770
  if (this._noInput && this.focusElement) {
769
771
  this.focusElement.blur();
772
+ this._overlayContent.focusDateElement();
770
773
  }
771
774
  }
772
775
 
@@ -853,11 +856,7 @@ export const DatePickerMixin = (subclass) =>
853
856
 
854
857
  /** @protected */
855
858
  _focus() {
856
- if (this._noInput) {
857
- if (this._overlayInitialized) {
858
- this._overlayContent.focus();
859
- }
860
- } else {
859
+ if (!this._noInput) {
861
860
  this.inputElement.focus();
862
861
  }
863
862
  }
@@ -909,7 +908,30 @@ export const DatePickerMixin = (subclass) =>
909
908
  }
910
909
 
911
910
  /**
912
- * Override an event listener from `ClearButtonMixin`
911
+ * @param {Event} event
912
+ * @private
913
+ */
914
+ _onClick(event) {
915
+ // Clear button click is handled in separate listener
916
+ // but bubbles to the host, so we need to ignore it.
917
+ if (!this._isClearButton(event)) {
918
+ this._onHostClick(event);
919
+ }
920
+ }
921
+
922
+ /**
923
+ * @param {Event} event
924
+ * @private
925
+ */
926
+ _onHostClick(event) {
927
+ if (!this.autoOpenDisabled || this._noInput) {
928
+ event.preventDefault();
929
+ this.open();
930
+ }
931
+ }
932
+
933
+ /**
934
+ * Override an event listener from `InputControlMixin`
913
935
  * to validate and dispatch change on clear.
914
936
  * @protected
915
937
  */
@@ -922,11 +944,13 @@ export const DatePickerMixin = (subclass) =>
922
944
 
923
945
  /**
924
946
  * Override an event listener from `KeyboardMixin`.
925
- * Do not call `super` to also override `ClearButtonMixin`.
947
+ * @param {KeyboardEvent} e
926
948
  * @protected
927
949
  * @override
928
950
  */
929
951
  _onKeyDown(e) {
952
+ super._onKeyDown(e);
953
+
930
954
  if (this._noInput) {
931
955
  // The input element cannot be readonly as it would conflict with
932
956
  // the required attribute. Both are not allowed on an input element.
@@ -953,45 +977,10 @@ export const DatePickerMixin = (subclass) =>
953
977
  this.open();
954
978
  }
955
979
  break;
956
- case 'Enter': {
957
- const parsedDate = this._getParsedDate();
958
- const isValidDate = this._isValidDate(parsedDate);
959
- if (this.opened) {
960
- if (this._overlayInitialized && this._overlayContent.focusedDate && isValidDate) {
961
- this._selectDate(this._overlayContent.focusedDate);
962
- }
963
- this.close();
964
- } else if (!isValidDate && this.inputElement.value !== '') {
965
- this.validate();
966
- } else {
967
- const oldValue = this.value;
968
- this._selectParsedOrFocusedDate();
969
- if (oldValue === this.value) {
970
- this.validate();
971
- }
972
- }
973
- break;
974
- }
975
- case 'Escape':
976
- if (this.opened) {
977
- this._focusedDate = this._selectedDate;
978
- this._close();
979
- } else if (this.clearButtonVisible) {
980
- this._onClearButtonClick();
981
- } else if (this.autoOpenDisabled) {
982
- // Do not restore selected date if Esc was pressed after clearing input field
983
- if (this.inputElement.value === '') {
984
- this._selectDate(null);
985
- }
986
- this._applyInputValue(this._selectedDate);
987
- } else {
988
- this._focusedDate = this._selectedDate;
989
- this._selectParsedOrFocusedDate();
990
- }
991
- break;
992
980
  case 'Tab':
993
981
  if (this.opened) {
994
982
  e.preventDefault();
983
+ e.stopPropagation();
995
984
  // Clear the selection range (remains visible on IE)
996
985
  this._setSelectionRange(0, 0);
997
986
  if (e.shiftKey) {
@@ -1006,6 +995,61 @@ export const DatePickerMixin = (subclass) =>
1006
995
  }
1007
996
  }
1008
997
 
998
+ /**
999
+ * Override an event listener from `KeyboardMixin`.
1000
+ *
1001
+ * @param {!KeyboardEvent} _event
1002
+ * @protected
1003
+ * @override
1004
+ */
1005
+ _onEnter(_event) {
1006
+ const parsedDate = this._getParsedDate();
1007
+ const isValidDate = this._isValidDate(parsedDate);
1008
+ if (this.opened) {
1009
+ if (this._overlayInitialized && this._overlayContent.focusedDate && isValidDate) {
1010
+ this._selectDate(this._overlayContent.focusedDate);
1011
+ }
1012
+ this.close();
1013
+ } else if (!isValidDate && this.inputElement.value !== '') {
1014
+ this.validate();
1015
+ } else {
1016
+ const oldValue = this.value;
1017
+ this._selectParsedOrFocusedDate();
1018
+ if (oldValue === this.value) {
1019
+ this.validate();
1020
+ }
1021
+ }
1022
+ }
1023
+
1024
+ /**
1025
+ * Override an event listener from `KeyboardMixin`.
1026
+ * Do not call `super` in order to override clear
1027
+ * button logic defined in `InputControlMixin`.
1028
+ *
1029
+ * @param {!KeyboardEvent} _event
1030
+ * @protected
1031
+ * @override
1032
+ */
1033
+ _onEscape(_event) {
1034
+ // Closing overlay is handled in vaadin-overlay-escape-press event listener.
1035
+ if (this.opened) {
1036
+ return;
1037
+ }
1038
+
1039
+ if (this.clearButtonVisible) {
1040
+ this._onClearButtonClick();
1041
+ } else if (this.autoOpenDisabled) {
1042
+ // Do not restore selected date if Esc was pressed after clearing input field
1043
+ if (this.inputElement.value === '') {
1044
+ this._selectDate(null);
1045
+ }
1046
+ this._applyInputValue(this._selectedDate);
1047
+ } else {
1048
+ this._focusedDate = this._selectedDate;
1049
+ this._selectParsedOrFocusedDate();
1050
+ }
1051
+ }
1052
+
1009
1053
  /** @private */
1010
1054
  _getParsedDate(inputValue = this._inputValue) {
1011
1055
  const dateObject = this.i18n.parseDate && this.i18n.parseDate(inputValue);
@@ -326,6 +326,9 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
326
326
 
327
327
  ready() {
328
328
  super.ready();
329
+
330
+ this.setAttribute('role', 'dialog');
331
+
329
332
  addListener(this, 'tap', this._stopPropagation);
330
333
  addListener(this.$.scrollers, 'track', this._track.bind(this));
331
334
  addListener(this.shadowRoot.querySelector('[part="clear-button"]'), 'tap', this._clear.bind(this));
@@ -686,12 +689,6 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
686
689
  }
687
690
 
688
691
  _close() {
689
- const overlayContent = this.getRootNode().host;
690
- const overlay = overlayContent ? overlayContent.getRootNode().host : null;
691
- if (overlay) {
692
- overlay.opened = false;
693
- }
694
-
695
692
  this.dispatchEvent(new CustomEvent('close', { bubbles: true, composed: true }));
696
693
  }
697
694
 
@@ -758,9 +755,8 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
758
755
  this._moveFocusByMonths(event.shiftKey ? -12 : -1);
759
756
  handled = true;
760
757
  break;
761
- case 'Escape':
762
- this._cancel();
763
- handled = true;
758
+ case 'Tab':
759
+ this._onTabKeyDown(event, 'calendar');
764
760
  break;
765
761
  default:
766
762
  break;
@@ -772,45 +768,68 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
772
768
  }
773
769
  }
774
770
 
771
+ _onTabKeyDown(event, section) {
772
+ // Stop propagation to avoid focus-trap
773
+ // listener when used in a modal dialog.
774
+ event.stopPropagation();
775
+
776
+ switch (section) {
777
+ case 'calendar':
778
+ if (event.shiftKey) {
779
+ // Return focus back to the input field.
780
+ event.preventDefault();
781
+ this.__focusInput();
782
+ }
783
+ break;
784
+ case 'today':
785
+ if (event.shiftKey) {
786
+ // Browser returns focus back to the calendar.
787
+ // We need to move the scroll to focused date.
788
+ setTimeout(() => this.revealDate(this.focusedDate), 1);
789
+ }
790
+ break;
791
+ case 'cancel':
792
+ if (!event.shiftKey) {
793
+ // Return focus back to the input field.
794
+ event.preventDefault();
795
+ this.__focusInput();
796
+ }
797
+ break;
798
+ default:
799
+ break;
800
+ }
801
+ }
802
+
775
803
  __onTodayButtonKeyDown(event) {
776
804
  if (this.hasAttribute('fullscreen')) {
777
- event.stopPropagation();
805
+ // Do not prevent closing on Esc
806
+ if (event.key !== 'Escape') {
807
+ event.stopPropagation();
808
+ }
778
809
  return;
779
810
  }
780
811
 
781
- if (event.key === 'Tab' && event.shiftKey) {
782
- event.stopPropagation();
783
-
784
- // Browser returns focus back to the calendar.
785
- // We need to move the scroll to focused date.
786
- setTimeout(() => this.revealDate(this.focusedDate), 1);
787
- }
788
-
789
- if (event.key === 'Escape') {
790
- this._cancel();
791
- event.preventDefault();
792
- event.stopPropagation();
812
+ if (event.key === 'Tab') {
813
+ this._onTabKeyDown(event, 'today');
793
814
  }
794
815
  }
795
816
 
796
817
  __onCancelButtonKeyDown(event) {
797
818
  if (this.hasAttribute('fullscreen')) {
798
- event.stopPropagation();
819
+ // Do not prevent closing on Esc
820
+ if (event.key !== 'Escape') {
821
+ event.stopPropagation();
822
+ }
799
823
  return;
800
824
  }
801
825
 
802
- if (event.key === 'Tab' && !event.shiftKey) {
803
- // Return focus back to the input field
804
- event.preventDefault();
805
- event.stopPropagation();
806
- this.dispatchEvent(new CustomEvent('focus-input', { bubbles: true, composed: true }));
826
+ if (event.key === 'Tab') {
827
+ this._onTabKeyDown(event, 'cancel');
807
828
  }
829
+ }
808
830
 
809
- if (event.key === 'Escape') {
810
- this._cancel();
811
- event.preventDefault();
812
- event.stopPropagation();
813
- }
831
+ __focusInput() {
832
+ this.dispatchEvent(new CustomEvent('focus-input', { bubbles: true, composed: true }));
814
833
  }
815
834
 
816
835
  __tryFocusDate() {
@@ -173,13 +173,10 @@ class DatePicker extends DatePickerMixin(InputControlMixin(ThemableMixin(Element
173
173
  fullscreen$="[[_fullscreen]]"
174
174
  label="[[label]]"
175
175
  selected-date="[[_selectedDate]]"
176
- slot="dropdown-content"
177
176
  focused-date="{{_focusedDate}}"
178
177
  show-week-numbers="[[showWeekNumbers]]"
179
178
  min-date="[[_minDate]]"
180
179
  max-date="[[_maxDate]]"
181
- role="dialog"
182
- on-date-tap="_close"
183
180
  part="overlay-content"
184
181
  theme$="[[__getOverlayTheme(_theme, _overlayInitialized)]]"
185
182
  ></vaadin-date-picker-overlay-content>
@@ -189,7 +186,7 @@ class DatePicker extends DatePickerMixin(InputControlMixin(ThemableMixin(Element
189
186
  }
190
187
 
191
188
  /**
192
- * Used by `ClearButtonMixin` as a reference to the clear button element.
189
+ * Used by `InputControlMixin` as a reference to the clear button element.
193
190
  * @protected
194
191
  * @return {!HTMLElement}
195
192
  */
@@ -215,6 +212,13 @@ class DatePicker extends DatePickerMixin(InputControlMixin(ThemableMixin(Element
215
212
  toggleButton.addEventListener('mousedown', (e) => e.preventDefault());
216
213
  }
217
214
 
215
+ /** @protected */
216
+ _initOverlay() {
217
+ super._initOverlay();
218
+
219
+ this.$.overlay.addEventListener('vaadin-overlay-close', this._onVaadinOverlayClose.bind(this));
220
+ }
221
+
218
222
  /** @private */
219
223
  _onVaadinOverlayClose(e) {
220
224
  if (this._openedWithFocusRing && this.hasAttribute('focused')) {
@@ -1,5 +1,6 @@
1
1
  import '@vaadin/vaadin-lumo-styles/sizing.js';
2
2
  import '@vaadin/vaadin-lumo-styles/spacing.js';
3
+ import '@vaadin/vaadin-overlay/theme/lumo/vaadin-overlay.js';
3
4
  import { menuOverlay } from '@vaadin/vaadin-lumo-styles/mixins/menu-overlay.js';
4
5
  import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
5
6
 
@@ -1,3 +1,4 @@
1
+ import '@vaadin/vaadin-overlay/theme/material/vaadin-overlay.js';
1
2
  import { overlay } from '@vaadin/vaadin-material-styles/mixins/overlay.js';
2
3
  import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
3
4