@vaadin/date-picker 24.2.0-dev.e9803eea7 → 24.2.0-rc1

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": "24.2.0-dev.e9803eea7",
3
+ "version": "24.2.0-rc1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -21,6 +21,10 @@
21
21
  "type": "module",
22
22
  "files": [
23
23
  "src",
24
+ "!src/vaadin-lit-date-picker-overlay-content.js",
25
+ "!src/vaadin-lit-date-picker-overlay.js",
26
+ "!src/vaadin-lit-month-calendar.js",
27
+ "!src/vaadin-lit-date-picker.js",
24
28
  "theme",
25
29
  "vaadin-*.d.ts",
26
30
  "vaadin-*.js",
@@ -36,24 +40,24 @@
36
40
  "dependencies": {
37
41
  "@open-wc/dedupe-mixin": "^1.3.0",
38
42
  "@polymer/polymer": "^3.2.0",
39
- "@vaadin/a11y-base": "24.2.0-dev.e9803eea7",
40
- "@vaadin/button": "24.2.0-dev.e9803eea7",
41
- "@vaadin/component-base": "24.2.0-dev.e9803eea7",
42
- "@vaadin/field-base": "24.2.0-dev.e9803eea7",
43
- "@vaadin/input-container": "24.2.0-dev.e9803eea7",
44
- "@vaadin/overlay": "24.2.0-dev.e9803eea7",
45
- "@vaadin/vaadin-lumo-styles": "24.2.0-dev.e9803eea7",
46
- "@vaadin/vaadin-material-styles": "24.2.0-dev.e9803eea7",
47
- "@vaadin/vaadin-themable-mixin": "24.2.0-dev.e9803eea7"
43
+ "@vaadin/a11y-base": "24.2.0-rc1",
44
+ "@vaadin/button": "24.2.0-rc1",
45
+ "@vaadin/component-base": "24.2.0-rc1",
46
+ "@vaadin/field-base": "24.2.0-rc1",
47
+ "@vaadin/input-container": "24.2.0-rc1",
48
+ "@vaadin/overlay": "24.2.0-rc1",
49
+ "@vaadin/vaadin-lumo-styles": "24.2.0-rc1",
50
+ "@vaadin/vaadin-material-styles": "24.2.0-rc1",
51
+ "@vaadin/vaadin-themable-mixin": "24.2.0-rc1"
48
52
  },
49
53
  "devDependencies": {
50
54
  "@esm-bundle/chai": "^4.3.4",
51
- "@vaadin/testing-helpers": "^0.4.3",
55
+ "@vaadin/testing-helpers": "^0.5.0",
52
56
  "sinon": "^13.0.2"
53
57
  },
54
58
  "web-types": [
55
59
  "web-types.json",
56
60
  "web-types.lit.json"
57
61
  ],
58
- "gitHead": "a065b79b9d5a189e457fab312cc8aff0d7f2f910"
62
+ "gitHead": "012bef350bbf29865748f4c78338dd17c6f61a74"
59
63
  }
@@ -3,10 +3,11 @@
3
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
- import './vaadin-date-picker-overlay.js';
7
6
  import './vaadin-date-picker-overlay-content.js';
7
+ import './vaadin-date-picker-overlay.js';
8
8
  import { dashToCamelCase } from '@polymer/polymer/lib/utils/case-map.js';
9
9
  import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
10
+ import { defineCustomElement } from '@vaadin/component-base/src/define.js';
10
11
  import { ValidateMixin } from '@vaadin/field-base/src/validate-mixin.js';
11
12
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
12
13
  import { DatePickerMixin } from './vaadin-date-picker-mixin.js';
@@ -45,6 +46,7 @@ import { DatePickerMixin } from './vaadin-date-picker-mixin.js';
45
46
  * @fires {CustomEvent} value-changed - Fired when the `value` property changes.
46
47
  * @fires {CustomEvent} validated - Fired whenever the field is validated.
47
48
  *
49
+ * @customElement
48
50
  * @extends HTMLElement
49
51
  * @mixes ThemableMixin
50
52
  * @mixes DatePickerMixin
@@ -126,6 +128,6 @@ class DatePickerLight extends ThemableMixin(DatePickerMixin(ValidateMixin(Polyme
126
128
  }
127
129
  }
128
130
 
129
- customElements.define(DatePickerLight.is, DatePickerLight);
131
+ defineCustomElement(DatePickerLight);
130
132
 
131
133
  export { DatePickerLight };
@@ -42,14 +42,18 @@ export const DatePickerMixin = (subclass) =>
42
42
  * @protected
43
43
  */
44
44
  _selectedDate: {
45
- type: Date,
45
+ type: Object,
46
+ sync: true,
46
47
  },
47
48
 
48
49
  /**
49
50
  * @type {Date | undefined}
50
51
  * @protected
51
52
  */
52
- _focusedDate: Date,
53
+ _focusedDate: {
54
+ type: Object,
55
+ sync: true,
56
+ },
53
57
 
54
58
  /**
55
59
  * Selected date.
@@ -64,6 +68,7 @@ export const DatePickerMixin = (subclass) =>
64
68
  type: String,
65
69
  notify: true,
66
70
  value: '',
71
+ sync: true,
67
72
  },
68
73
 
69
74
  /**
@@ -82,6 +87,7 @@ export const DatePickerMixin = (subclass) =>
82
87
  reflectToAttribute: true,
83
88
  notify: true,
84
89
  observer: '_openedChanged',
90
+ sync: true,
85
91
  },
86
92
 
87
93
  /**
@@ -99,6 +105,7 @@ export const DatePickerMixin = (subclass) =>
99
105
  showWeekNumbers: {
100
106
  type: Boolean,
101
107
  value: false,
108
+ sync: true,
102
109
  },
103
110
 
104
111
  /**
@@ -108,6 +115,7 @@ export const DatePickerMixin = (subclass) =>
108
115
  _fullscreen: {
109
116
  type: Boolean,
110
117
  value: false,
118
+ sync: true,
111
119
  },
112
120
 
113
121
  /**
@@ -206,6 +214,7 @@ export const DatePickerMixin = (subclass) =>
206
214
  */
207
215
  i18n: {
208
216
  type: Object,
217
+ sync: true,
209
218
  value: () => {
210
219
  return {
211
220
  monthNames: [
@@ -276,6 +285,7 @@ export const DatePickerMixin = (subclass) =>
276
285
  */
277
286
  min: {
278
287
  type: String,
288
+ sync: true,
279
289
  },
280
290
 
281
291
  /**
@@ -289,6 +299,7 @@ export const DatePickerMixin = (subclass) =>
289
299
  */
290
300
  max: {
291
301
  type: String,
302
+ sync: true,
292
303
  },
293
304
 
294
305
  /**
@@ -299,6 +310,7 @@ export const DatePickerMixin = (subclass) =>
299
310
  _minDate: {
300
311
  type: Date,
301
312
  computed: '__computeMinOrMaxDate(min)',
313
+ sync: true,
302
314
  },
303
315
 
304
316
  /**
@@ -309,6 +321,7 @@ export const DatePickerMixin = (subclass) =>
309
321
  _maxDate: {
310
322
  type: Date,
311
323
  computed: '__computeMinOrMaxDate(max)',
324
+ sync: true,
312
325
  },
313
326
 
314
327
  /** @private */
@@ -327,7 +340,10 @@ export const DatePickerMixin = (subclass) =>
327
340
  _focusOverlayOnOpen: Boolean,
328
341
 
329
342
  /** @private */
330
- _overlayContent: Object,
343
+ _overlayContent: {
344
+ type: Object,
345
+ sync: true,
346
+ },
331
347
 
332
348
  /**
333
349
  * In date-picker, unlike other components extending `InputMixin`,
@@ -347,8 +363,8 @@ export const DatePickerMixin = (subclass) =>
347
363
 
348
364
  static get observers() {
349
365
  return [
350
- '_selectedDateChanged(_selectedDate, i18n.formatDate)',
351
- '_focusedDateChanged(_focusedDate, i18n.formatDate)',
366
+ '_selectedDateChanged(_selectedDate, i18n)',
367
+ '_focusedDateChanged(_focusedDate, i18n)',
352
368
  '__updateOverlayContent(_overlayContent, i18n, label, _minDate, _maxDate, _focusedDate, _selectedDate, showWeekNumbers)',
353
369
  '__updateOverlayContentTheme(_overlayContent, _theme)',
354
370
  '__updateOverlayContentFullScreen(_overlayContent, _fullscreen)',
@@ -431,19 +447,13 @@ export const DatePickerMixin = (subclass) =>
431
447
  super._onBlur(event);
432
448
 
433
449
  if (!this.opened) {
434
- if (this.autoOpenDisabled) {
435
- this._selectParsedOrFocusedDate();
436
- }
450
+ this._selectParsedOrFocusedDate();
437
451
 
438
452
  // Do not validate when focusout is caused by document
439
453
  // losing focus, which happens on browser tab switch.
440
454
  if (document.hasFocus()) {
441
455
  this.validate();
442
456
  }
443
-
444
- if (this._inputElementValue === '' && this.value !== '') {
445
- this.value = '';
446
- }
447
457
  }
448
458
  }
449
459
 
@@ -477,25 +487,6 @@ export const DatePickerMixin = (subclass) =>
477
487
  this.opened = false;
478
488
  }
479
489
 
480
- /**
481
- * Override Polymer lifecycle callback to dispatch `change` event if needed.
482
- * This is necessary to ensure `change` is fired after `value-changed`.
483
- *
484
- * @param {!Object} currentProps Current accessor values
485
- * @param {?Object} changedProps Properties changed since the last call
486
- * @param {?Object} oldProps Previous values for each changed property
487
- * @protected
488
- * @override
489
- */
490
- _propertiesChanged(currentProps, changedProps, oldProps) {
491
- super._propertiesChanged(currentProps, changedProps, oldProps);
492
-
493
- if ('value' in changedProps && this.__dispatchChange) {
494
- this.dispatchEvent(new CustomEvent('change', { bubbles: true }));
495
- this.__dispatchChange = false;
496
- }
497
- }
498
-
499
490
  /**
500
491
  * Opens the dropdown.
501
492
  */
@@ -561,6 +552,34 @@ export const DatePickerMixin = (subclass) =>
561
552
  });
562
553
  }
563
554
 
555
+ /**
556
+ * @param {string} dateString
557
+ * @private
558
+ */
559
+ __parseDate(dateString) {
560
+ if (!this.i18n.parseDate) {
561
+ return;
562
+ }
563
+
564
+ let dateObject = this.i18n.parseDate(dateString);
565
+ if (dateObject) {
566
+ dateObject = parseDate(`${dateObject.year}-${dateObject.month + 1}-${dateObject.day}`);
567
+ }
568
+ if (dateObject && !isNaN(dateObject.getTime())) {
569
+ return dateObject;
570
+ }
571
+ }
572
+
573
+ /**
574
+ * @param {Date} dateObject
575
+ * @private
576
+ */
577
+ __formatDate(dateObject) {
578
+ if (this.i18n.formatDate) {
579
+ return this.i18n.formatDate(extractDateParts(dateObject));
580
+ }
581
+ }
582
+
564
583
  /**
565
584
  * Returns true if the current input value satisfies all constraints (if any)
566
585
  *
@@ -570,9 +589,7 @@ export const DatePickerMixin = (subclass) =>
570
589
  */
571
590
  checkValidity() {
572
591
  const inputValue = this._inputElementValue;
573
- const inputValid =
574
- !inputValue ||
575
- (!!this._selectedDate && inputValue === this._getFormattedDate(this.i18n.formatDate, this._selectedDate));
592
+ const inputValid = !inputValue || (!!this._selectedDate && inputValue === this.__formatDate(this._selectedDate));
576
593
  const minMaxValid = !this._selectedDate || dateAllowed(this._selectedDate, this._minDate, this._maxDate);
577
594
 
578
595
  let inputValidity = true;
@@ -633,6 +650,12 @@ export const DatePickerMixin = (subclass) =>
633
650
  this._shouldKeepFocusRing = focused && this._keyboardActive;
634
651
  }
635
652
 
653
+ /** @private */
654
+ __dispatchChange() {
655
+ this.validate();
656
+ this.dispatchEvent(new CustomEvent('change', { bubbles: true }));
657
+ }
658
+
636
659
  /**
637
660
  * Select date on user interaction and set the flag
638
661
  * to fire change event if necessary.
@@ -641,14 +664,13 @@ export const DatePickerMixin = (subclass) =>
641
664
  * @protected
642
665
  */
643
666
  _selectDate(dateToSelect) {
644
- const value = this._formatISO(dateToSelect);
645
-
646
- // Only set flag if the value will change.
647
- if (this.value !== value) {
648
- this.__dispatchChange = true;
649
- }
667
+ const prevValue = this.value;
650
668
 
651
669
  this._selectedDate = dateToSelect;
670
+
671
+ if (prevValue !== this.value) {
672
+ this.__dispatchChange();
673
+ }
652
674
  }
653
675
 
654
676
  /** @private */
@@ -724,28 +746,24 @@ export const DatePickerMixin = (subclass) =>
724
746
  }
725
747
 
726
748
  /** @private */
727
- _selectedDateChanged(selectedDate, formatDate) {
728
- if (selectedDate === undefined || formatDate === undefined) {
749
+ _selectedDateChanged(selectedDate, i18n) {
750
+ if (selectedDate === undefined || i18n === undefined) {
729
751
  return;
730
752
  }
731
- const value = this._formatISO(selectedDate);
732
753
 
733
754
  if (!this.__keepInputValue) {
734
755
  this._applyInputValue(selectedDate);
735
756
  }
736
757
 
737
- if (value !== this.value) {
738
- this.validate();
739
- this.value = value;
740
- }
758
+ this.value = this._formatISO(selectedDate);
741
759
  this._ignoreFocusedDateChange = true;
742
760
  this._focusedDate = selectedDate;
743
761
  this._ignoreFocusedDateChange = false;
744
762
  }
745
763
 
746
764
  /** @private */
747
- _focusedDateChanged(focusedDate, formatDate) {
748
- if (focusedDate === undefined || formatDate === undefined) {
765
+ _focusedDateChanged(focusedDate, i18n) {
766
+ if (focusedDate === undefined || i18n === undefined) {
749
767
  return;
750
768
  }
751
769
  if (!this._ignoreFocusedDateChange && !this._noInput) {
@@ -795,15 +813,13 @@ export const DatePickerMixin = (subclass) =>
795
813
  // eslint-disable-next-line max-params
796
814
  __updateOverlayContent(overlayContent, i18n, label, minDate, maxDate, focusedDate, selectedDate, showWeekNumbers) {
797
815
  if (overlayContent) {
798
- overlayContent.setProperties({
799
- i18n,
800
- label,
801
- minDate,
802
- maxDate,
803
- focusedDate,
804
- selectedDate,
805
- showWeekNumbers,
806
- });
816
+ overlayContent.i18n = i18n;
817
+ overlayContent.label = label;
818
+ overlayContent.minDate = minDate;
819
+ overlayContent.maxDate = maxDate;
820
+ overlayContent.focusedDate = focusedDate;
821
+ overlayContent.selectedDate = selectedDate;
822
+ overlayContent.showWeekNumbers = showWeekNumbers;
807
823
  }
808
824
  }
809
825
 
@@ -834,6 +850,7 @@ export const DatePickerMixin = (subclass) =>
834
850
  /** @protected */
835
851
  _onOverlayOpened() {
836
852
  const content = this._overlayContent;
853
+ content.reset();
837
854
 
838
855
  // Detect which date to show
839
856
  const initialPosition = this._getInitialPosition();
@@ -885,9 +902,9 @@ export const DatePickerMixin = (subclass) =>
885
902
  this._ignoreFocusedDateChange = true;
886
903
  if (this.i18n.parseDate) {
887
904
  const inputValue = this._inputElementValue || '';
888
- const parsedDate = this._getParsedDate(inputValue);
905
+ const parsedDate = this.__parseDate(inputValue);
889
906
 
890
- if (this._isValidDate(parsedDate)) {
907
+ if (parsedDate) {
891
908
  this._selectDate(parsedDate);
892
909
  } else {
893
910
  this.__keepInputValue = true;
@@ -922,8 +939,9 @@ export const DatePickerMixin = (subclass) =>
922
939
  this._nativeInput.selectionStart = this._nativeInput.selectionEnd;
923
940
  }
924
941
  // No need to revalidate the value after `_selectedDateChanged`
925
- // Needed in case the value was not changed: open and close dropdown.
926
- if (!this.value) {
942
+ // Needed in case the value was not changed: open and close dropdown,
943
+ // especially on outside click. On Esc key press, do not validate.
944
+ if (!this.value && !this._keyboardActive) {
927
945
  this.validate();
928
946
  }
929
947
  }
@@ -950,12 +968,7 @@ export const DatePickerMixin = (subclass) =>
950
968
 
951
969
  /** @private */
952
970
  _applyInputValue(date) {
953
- this._inputElementValue = date ? this._getFormattedDate(this.i18n.formatDate, date) : '';
954
- }
955
-
956
- /** @private */
957
- _getFormattedDate(formatDate, date) {
958
- return formatDate(extractDateParts(date));
971
+ this._inputElementValue = date ? this.__formatDate(date) : '';
959
972
  }
960
973
 
961
974
  /** @private */
@@ -965,23 +978,14 @@ export const DatePickerMixin = (subclass) =>
965
978
  }
966
979
  }
967
980
 
968
- /** @private */
969
- _isValidDate(d) {
970
- return d && !isNaN(d.getTime());
971
- }
972
-
973
981
  /**
974
982
  * Override an event listener from `InputConstraintsMixin`
975
- * to have date-picker fully control when to fire a change event.
983
+ * to have date-picker fully control when to fire a change event
984
+ * and trigger validation.
985
+ *
976
986
  * @protected
977
987
  */
978
988
  _onChange(event) {
979
- // For change event on the native <input> blur, after the input is cleared,
980
- // we schedule change event to be dispatched on date-picker blur.
981
- if (this._inputElementValue === '') {
982
- this.__dispatchChange = true;
983
- }
984
-
985
989
  event.stopPropagation();
986
990
  }
987
991
 
@@ -1017,8 +1021,7 @@ export const DatePickerMixin = (subclass) =>
1017
1021
  event.preventDefault();
1018
1022
  this._inputElementValue = '';
1019
1023
  this.value = '';
1020
- this.validate();
1021
- this.dispatchEvent(new CustomEvent('change', { bubbles: true }));
1024
+ this.__dispatchChange();
1022
1025
  }
1023
1026
 
1024
1027
  /**
@@ -1129,13 +1132,6 @@ export const DatePickerMixin = (subclass) =>
1129
1132
  }
1130
1133
  }
1131
1134
 
1132
- /** @private */
1133
- _getParsedDate(inputValue = this._inputElementValue) {
1134
- const dateObject = this.i18n.parseDate && this.i18n.parseDate(inputValue);
1135
- const parsedDate = dateObject && parseDate(`${dateObject.year}-${dateObject.month + 1}-${dateObject.day}`);
1136
- return parsedDate;
1137
- }
1138
-
1139
1135
  /** @protected */
1140
1136
  _isClearButton(event) {
1141
1137
  return event.composedPath()[0] === this.clearElement;
@@ -1146,18 +1142,13 @@ export const DatePickerMixin = (subclass) =>
1146
1142
  * @protected
1147
1143
  */
1148
1144
  _onInput() {
1149
- if (!this.opened && this.inputElement.value && !this.autoOpenDisabled) {
1145
+ if (!this.opened && this._inputElementValue && !this.autoOpenDisabled) {
1150
1146
  this.open();
1151
1147
  }
1152
- this._userInputValueChanged();
1153
- }
1154
1148
 
1155
- /** @private */
1156
- _userInputValueChanged() {
1157
1149
  if (this._inputElementValue) {
1158
- const parsedDate = this._getParsedDate();
1159
-
1160
- if (this._isValidDate(parsedDate)) {
1150
+ const parsedDate = this.__parseDate(this._inputElementValue);
1151
+ if (parsedDate) {
1161
1152
  this._ignoreFocusedDateChange = true;
1162
1153
  if (!dateEquals(parsedDate, this._focusedDate)) {
1163
1154
  this._focusedDate = parsedDate;
@@ -3,11 +3,12 @@
3
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
- import { html } from '@polymer/polymer/lib/utils/html-tag.js';
6
+ import { defineCustomElement } from '@vaadin/component-base/src/define.js';
7
7
  import { dateAfterXMonths } from './vaadin-date-picker-helper.js';
8
8
  import { InfiniteScroller } from './vaadin-infinite-scroller.js';
9
9
 
10
- const stylesTemplate = html`
10
+ const stylesTemplate = document.createElement('template');
11
+ stylesTemplate.innerHTML = `
11
12
  <style>
12
13
  :host {
13
14
  --vaadin-infinite-scroller-item-height: 270px;
@@ -21,11 +22,10 @@ const stylesTemplate = html`
21
22
  </style>
22
23
  `;
23
24
 
24
- let memoizedTemplate;
25
-
26
25
  /**
27
26
  * An element used internally by `<vaadin-date-picker>`. Not intended to be used separately.
28
27
  *
28
+ * @customElement
29
29
  * @extends InfiniteScroller
30
30
  * @private
31
31
  */
@@ -34,22 +34,11 @@ class DatePickerMonthScroller extends InfiniteScroller {
34
34
  return 'vaadin-date-picker-month-scroller';
35
35
  }
36
36
 
37
- static get template() {
38
- if (!memoizedTemplate) {
39
- memoizedTemplate = super.template.cloneNode(true);
40
- memoizedTemplate.content.appendChild(stylesTemplate.content.cloneNode(true));
41
- }
42
-
43
- return memoizedTemplate;
44
- }
37
+ constructor() {
38
+ super();
45
39
 
46
- static get properties() {
47
- return {
48
- bufferSize: {
49
- type: Number,
50
- value: 3,
51
- },
52
- };
40
+ this.bufferSize = 3;
41
+ this.shadowRoot.appendChild(stylesTemplate.content.cloneNode(true));
53
42
  }
54
43
 
55
44
  /**
@@ -71,4 +60,4 @@ class DatePickerMonthScroller extends InfiniteScroller {
71
60
  }
72
61
  }
73
62
 
74
- customElements.define(DatePickerMonthScroller.is, DatePickerMonthScroller);
63
+ defineCustomElement(DatePickerMonthScroller);