@vaadin/date-picker 23.1.0-rc1 → 23.1.0

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-rc1",
3
+ "version": "23.1.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -34,19 +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-rc1",
38
- "@vaadin/component-base": "23.1.0-rc1",
39
- "@vaadin/field-base": "23.1.0-rc1",
40
- "@vaadin/input-container": "23.1.0-rc1",
41
- "@vaadin/vaadin-lumo-styles": "23.1.0-rc1",
42
- "@vaadin/vaadin-material-styles": "23.1.0-rc1",
43
- "@vaadin/vaadin-overlay": "23.1.0-rc1",
44
- "@vaadin/vaadin-themable-mixin": "23.1.0-rc1"
37
+ "@vaadin/button": "^23.1.0",
38
+ "@vaadin/component-base": "^23.1.0",
39
+ "@vaadin/field-base": "^23.1.0",
40
+ "@vaadin/input-container": "^23.1.0",
41
+ "@vaadin/vaadin-lumo-styles": "^23.1.0",
42
+ "@vaadin/vaadin-material-styles": "^23.1.0",
43
+ "@vaadin/vaadin-overlay": "^23.1.0",
44
+ "@vaadin/vaadin-themable-mixin": "^23.1.0"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@esm-bundle/chai": "^4.3.4",
48
48
  "@vaadin/testing-helpers": "^0.3.2",
49
49
  "sinon": "^13.0.2"
50
50
  },
51
- "gitHead": "5ecb85e16e938df827fefca4bd2a665a1e29913e"
51
+ "gitHead": "322bba42b83f908a78cd972b06acadc5da95a69d"
52
52
  }
@@ -125,6 +125,13 @@ class DatePickerLight extends ThemableMixin(DatePickerMixin(PolymerElement)) {
125
125
  };
126
126
  }
127
127
 
128
+ /** @protected */
129
+ ready() {
130
+ super.ready();
131
+
132
+ this._initOverlay();
133
+ }
134
+
128
135
  /** @protected */
129
136
  connectedCallback() {
130
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,7 +470,7 @@ 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;
@@ -509,8 +506,6 @@ export const DatePickerMixin = (subclass) =>
509
506
  this._setFocused(true);
510
507
  });
511
508
 
512
- this.$.overlay.addEventListener('vaadin-overlay-close', this._onVaadinOverlayClose.bind(this));
513
-
514
509
  this.addEventListener('mousedown', () => this.__bringToFront());
515
510
  this.addEventListener('touchstart', () => this.__bringToFront());
516
511
  }
@@ -913,11 +908,35 @@ export const DatePickerMixin = (subclass) =>
913
908
  }
914
909
 
915
910
  /**
916
- * 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`
917
935
  * to validate and dispatch change on clear.
918
936
  * @protected
919
937
  */
920
- _onClearButtonClick() {
938
+ _onClearButtonClick(event) {
939
+ event.preventDefault();
921
940
  this.value = '';
922
941
  this._inputValue = '';
923
942
  this.validate();
@@ -926,11 +945,13 @@ export const DatePickerMixin = (subclass) =>
926
945
 
927
946
  /**
928
947
  * Override an event listener from `KeyboardMixin`.
929
- * Do not call `super` to also override `ClearButtonMixin`.
948
+ * @param {KeyboardEvent} e
930
949
  * @protected
931
950
  * @override
932
951
  */
933
952
  _onKeyDown(e) {
953
+ super._onKeyDown(e);
954
+
934
955
  if (this._noInput) {
935
956
  // The input element cannot be readonly as it would conflict with
936
957
  // the required attribute. Both are not allowed on an input element.
@@ -957,31 +978,10 @@ export const DatePickerMixin = (subclass) =>
957
978
  this.open();
958
979
  }
959
980
  break;
960
- case 'Enter': {
961
- const parsedDate = this._getParsedDate();
962
- const isValidDate = this._isValidDate(parsedDate);
963
- if (this.opened) {
964
- if (this._overlayInitialized && this._overlayContent.focusedDate && isValidDate) {
965
- this._selectDate(this._overlayContent.focusedDate);
966
- }
967
- this.close();
968
- } else if (!isValidDate && this.inputElement.value !== '') {
969
- this.validate();
970
- } else {
971
- const oldValue = this.value;
972
- this._selectParsedOrFocusedDate();
973
- if (oldValue === this.value) {
974
- this.validate();
975
- }
976
- }
977
- break;
978
- }
979
- case 'Escape':
980
- this._onEscape();
981
- break;
982
981
  case 'Tab':
983
982
  if (this.opened) {
984
983
  e.preventDefault();
984
+ e.stopPropagation();
985
985
  // Clear the selection range (remains visible on IE)
986
986
  this._setSelectionRange(0, 0);
987
987
  if (e.shiftKey) {
@@ -996,16 +996,56 @@ export const DatePickerMixin = (subclass) =>
996
996
  }
997
997
  }
998
998
 
999
- /** @private */
1000
- _onEscape() {
999
+ /**
1000
+ * Override an event listener from `KeyboardMixin`.
1001
+ *
1002
+ * @param {!KeyboardEvent} _event
1003
+ * @protected
1004
+ * @override
1005
+ */
1006
+ _onEnter(_event) {
1007
+ const parsedDate = this._getParsedDate();
1008
+ const isValidDate = this._isValidDate(parsedDate);
1009
+ if (this.opened) {
1010
+ if (this._overlayInitialized && this._overlayContent.focusedDate && isValidDate) {
1011
+ this._selectDate(this._overlayContent.focusedDate);
1012
+ }
1013
+ this.close();
1014
+ } else if (!isValidDate && this.inputElement.value !== '') {
1015
+ this.validate();
1016
+ } else {
1017
+ const oldValue = this.value;
1018
+ this._selectParsedOrFocusedDate();
1019
+ if (oldValue === this.value) {
1020
+ this.validate();
1021
+ }
1022
+ }
1023
+ }
1024
+
1025
+ /**
1026
+ * Override an event listener from `KeyboardMixin`.
1027
+ * Do not call `super` in order to override clear
1028
+ * button logic defined in `InputControlMixin`.
1029
+ *
1030
+ * @param {!KeyboardEvent} event
1031
+ * @protected
1032
+ * @override
1033
+ */
1034
+ _onEscape(event) {
1001
1035
  // Closing overlay is handled in vaadin-overlay-escape-press event listener.
1002
1036
  if (this.opened) {
1003
1037
  return;
1004
1038
  }
1005
1039
 
1006
- if (this.clearButtonVisible) {
1007
- this._onClearButtonClick();
1008
- } else if (this.autoOpenDisabled) {
1040
+ if (this.clearButtonVisible && !!this.value) {
1041
+ // Stop event from propagating to the host element
1042
+ // to avoid closing dialog when clearing on Esc
1043
+ event.stopPropagation();
1044
+ this._onClearButtonClick(event);
1045
+ return;
1046
+ }
1047
+
1048
+ if (this.autoOpenDisabled) {
1009
1049
  // Do not restore selected date if Esc was pressed after clearing input field
1010
1050
  if (this.inputElement.value === '') {
1011
1051
  this._selectDate(null);
@@ -755,6 +755,9 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
755
755
  this._moveFocusByMonths(event.shiftKey ? -12 : -1);
756
756
  handled = true;
757
757
  break;
758
+ case 'Tab':
759
+ this._onTabKeyDown(event, 'calendar');
760
+ break;
758
761
  default:
759
762
  break;
760
763
  }
@@ -765,35 +768,70 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
765
768
  }
766
769
  }
767
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
+
768
803
  __onTodayButtonKeyDown(event) {
769
804
  if (this.hasAttribute('fullscreen')) {
770
- event.stopPropagation();
805
+ // Do not prevent closing on Esc
806
+ if (event.key !== 'Escape') {
807
+ event.stopPropagation();
808
+ }
771
809
  return;
772
810
  }
773
811
 
774
- if (event.key === 'Tab' && event.shiftKey) {
775
- event.stopPropagation();
776
-
777
- // Browser returns focus back to the calendar.
778
- // We need to move the scroll to focused date.
779
- setTimeout(() => this.revealDate(this.focusedDate), 1);
812
+ if (event.key === 'Tab') {
813
+ this._onTabKeyDown(event, 'today');
780
814
  }
781
815
  }
782
816
 
783
817
  __onCancelButtonKeyDown(event) {
784
818
  if (this.hasAttribute('fullscreen')) {
785
- event.stopPropagation();
819
+ // Do not prevent closing on Esc
820
+ if (event.key !== 'Escape') {
821
+ event.stopPropagation();
822
+ }
786
823
  return;
787
824
  }
788
825
 
789
- if (event.key === 'Tab' && !event.shiftKey) {
790
- // Return focus back to the input field
791
- event.preventDefault();
792
- event.stopPropagation();
793
- this.dispatchEvent(new CustomEvent('focus-input', { bubbles: true, composed: true }));
826
+ if (event.key === 'Tab') {
827
+ this._onTabKeyDown(event, 'cancel');
794
828
  }
795
829
  }
796
830
 
831
+ __focusInput() {
832
+ this.dispatchEvent(new CustomEvent('focus-input', { bubbles: true, composed: true }));
833
+ }
834
+
797
835
  __tryFocusDate() {
798
836
  const dateToFocus = this.__pendingDateFocus;
799
837
  if (dateToFocus) {
@@ -186,7 +186,7 @@ class DatePicker extends DatePickerMixin(InputControlMixin(ThemableMixin(Element
186
186
  }
187
187
 
188
188
  /**
189
- * Used by `ClearButtonMixin` as a reference to the clear button element.
189
+ * Used by `InputControlMixin` as a reference to the clear button element.
190
190
  * @protected
191
191
  * @return {!HTMLElement}
192
192
  */
@@ -212,6 +212,13 @@ class DatePicker extends DatePickerMixin(InputControlMixin(ThemableMixin(Element
212
212
  toggleButton.addEventListener('mousedown', (e) => e.preventDefault());
213
213
  }
214
214
 
215
+ /** @protected */
216
+ _initOverlay() {
217
+ super._initOverlay();
218
+
219
+ this.$.overlay.addEventListener('vaadin-overlay-close', this._onVaadinOverlayClose.bind(this));
220
+ }
221
+
215
222
  /** @private */
216
223
  _onVaadinOverlayClose(e) {
217
224
  if (this._openedWithFocusRing && this.hasAttribute('focused')) {