@vaadin/date-picker 24.8.4 → 25.0.0-alpha10

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.
Files changed (63) hide show
  1. package/README.md +0 -23
  2. package/package.json +15 -15
  3. package/src/styles/vaadin-date-picker-base-styles.d.ts +8 -0
  4. package/src/styles/vaadin-date-picker-base-styles.js +30 -0
  5. package/src/styles/vaadin-date-picker-core-styles.d.ts +8 -0
  6. package/src/styles/vaadin-date-picker-overlay-base-styles.js +48 -0
  7. package/src/styles/vaadin-date-picker-overlay-content-base-styles.js +107 -0
  8. package/src/styles/vaadin-date-picker-overlay-content-core-styles.js +54 -0
  9. package/src/styles/vaadin-date-picker-year-base-styles.js +26 -0
  10. package/src/styles/vaadin-date-picker-year-core-styles.js +13 -0
  11. package/src/styles/vaadin-month-calendar-base-styles.js +140 -0
  12. package/src/vaadin-date-picker-helper.d.ts +5 -0
  13. package/src/vaadin-date-picker-mixin.js +34 -45
  14. package/src/vaadin-date-picker-month-scroller.js +2 -6
  15. package/src/vaadin-date-picker-overlay-content-mixin.js +5 -135
  16. package/src/vaadin-date-picker-overlay-content.js +28 -31
  17. package/src/vaadin-date-picker-overlay.js +27 -11
  18. package/src/vaadin-date-picker-year-scroller.js +3 -4
  19. package/src/vaadin-date-picker-year.js +39 -11
  20. package/src/vaadin-date-picker.d.ts +11 -14
  21. package/src/vaadin-date-picker.js +73 -54
  22. package/src/vaadin-infinite-scroller.js +1 -22
  23. package/src/vaadin-month-calendar.js +69 -47
  24. package/theme/lumo/vaadin-date-picker-overlay-content-styles.js +19 -46
  25. package/theme/lumo/vaadin-date-picker-overlay-styles.js +0 -1
  26. package/web-types.json +2 -369
  27. package/web-types.lit.json +2 -156
  28. package/src/vaadin-date-picker-light.d.ts +0 -112
  29. package/src/vaadin-date-picker-light.js +0 -136
  30. package/src/vaadin-date-picker-overlay-content-styles.js +0 -68
  31. package/src/vaadin-date-picker-year-mixin.js +0 -35
  32. package/src/vaadin-lit-date-picker-overlay-content.js +0 -70
  33. package/src/vaadin-lit-date-picker-overlay.js +0 -46
  34. package/src/vaadin-lit-date-picker-year.js +0 -41
  35. package/src/vaadin-lit-date-picker.js +0 -172
  36. package/src/vaadin-lit-month-calendar.js +0 -98
  37. package/theme/lumo/vaadin-date-picker-light.d.ts +0 -4
  38. package/theme/lumo/vaadin-date-picker-light.js +0 -4
  39. package/theme/lumo/vaadin-lit-date-picker.d.ts +0 -5
  40. package/theme/lumo/vaadin-lit-date-picker.js +0 -5
  41. package/theme/material/vaadin-date-picker-light.d.ts +0 -4
  42. package/theme/material/vaadin-date-picker-light.js +0 -4
  43. package/theme/material/vaadin-date-picker-overlay-content-styles.d.ts +0 -6
  44. package/theme/material/vaadin-date-picker-overlay-content-styles.js +0 -132
  45. package/theme/material/vaadin-date-picker-overlay-styles.d.ts +0 -1
  46. package/theme/material/vaadin-date-picker-overlay-styles.js +0 -47
  47. package/theme/material/vaadin-date-picker-styles.d.ts +0 -3
  48. package/theme/material/vaadin-date-picker-styles.js +0 -22
  49. package/theme/material/vaadin-date-picker-year-styles.d.ts +0 -1
  50. package/theme/material/vaadin-date-picker-year-styles.js +0 -28
  51. package/theme/material/vaadin-date-picker.d.ts +0 -5
  52. package/theme/material/vaadin-date-picker.js +0 -5
  53. package/theme/material/vaadin-lit-date-picker.d.ts +0 -5
  54. package/theme/material/vaadin-lit-date-picker.js +0 -5
  55. package/theme/material/vaadin-month-calendar-styles.d.ts +0 -2
  56. package/theme/material/vaadin-month-calendar-styles.js +0 -120
  57. package/vaadin-date-picker-light.d.ts +0 -1
  58. package/vaadin-date-picker-light.js +0 -2
  59. package/vaadin-lit-date-picker.d.ts +0 -1
  60. package/vaadin-lit-date-picker.js +0 -2
  61. /package/src/{vaadin-date-picker-styles.js → styles/vaadin-date-picker-core-styles.js} +0 -0
  62. /package/src/{vaadin-date-picker-overlay-styles.js → styles/vaadin-date-picker-overlay-core-styles.js} +0 -0
  63. /package/src/{vaadin-month-calendar-styles.js → styles/vaadin-month-calendar-core-styles.js} +0 -0
@@ -8,7 +8,6 @@ import { DelegateFocusMixin } from '@vaadin/a11y-base/src/delegate-focus-mixin.j
8
8
  import { isKeyboardActive } from '@vaadin/a11y-base/src/focus-utils.js';
9
9
  import { KeyboardMixin } from '@vaadin/a11y-base/src/keyboard-mixin.js';
10
10
  import { isIOS } from '@vaadin/component-base/src/browser-utils.js';
11
- import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
12
11
  import { I18nMixin } from '@vaadin/component-base/src/i18n-mixin.js';
13
12
  import { MediaQueryController } from '@vaadin/component-base/src/media-query-controller.js';
14
13
  import { OverlayClassMixin } from '@vaadin/component-base/src/overlay-class-mixin.js';
@@ -82,7 +81,6 @@ export const datePickerI18nDefaults = Object.freeze({
82
81
 
83
82
  /**
84
83
  * @polymerMixin
85
- * @mixes ControllerMixin
86
84
  * @mixes DelegateFocusMixin
87
85
  * @mixes I18nMixin
88
86
  * @mixes InputConstraintsMixin
@@ -93,7 +91,7 @@ export const datePickerI18nDefaults = Object.freeze({
93
91
  export const DatePickerMixin = (subclass) =>
94
92
  class DatePickerMixinClass extends I18nMixin(
95
93
  datePickerI18nDefaults,
96
- OverlayClassMixin(ControllerMixin(DelegateFocusMixin(InputConstraintsMixin(KeyboardMixin(subclass))))),
94
+ OverlayClassMixin(DelegateFocusMixin(InputConstraintsMixin(KeyboardMixin(subclass)))),
97
95
  ) {
98
96
  static get properties() {
99
97
  return {
@@ -297,7 +295,6 @@ export const DatePickerMixin = (subclass) =>
297
295
 
298
296
  this._boundOnClick = this._onClick.bind(this);
299
297
  this._boundOnScroll = this._onScroll.bind(this);
300
- this._boundOverlayRenderer = this._overlayRenderer.bind(this);
301
298
  }
302
299
 
303
300
  /**
@@ -397,26 +394,6 @@ export const DatePickerMixin = (subclass) =>
397
394
  this.__setEnteredDate(parsedDate);
398
395
  }
399
396
 
400
- /**
401
- * Override a getter from `InputControlMixin` to make it optional
402
- * and to prevent warning when a clear button is missing,
403
- * for example when using <vaadin-date-picker-light>.
404
- * @protected
405
- * @return {Element | null | undefined}
406
- */
407
- get clearElement() {
408
- return null;
409
- }
410
-
411
- /** @private */
412
- get _nativeInput() {
413
- if (this.inputElement) {
414
- // TODO: support focusElement for backwards compatibility
415
- return this.inputElement.focusElement || this.inputElement;
416
- }
417
- return null;
418
- }
419
-
420
397
  /**
421
398
  * The input element's value when it cannot be parsed as a date, and an empty string otherwise.
422
399
  *
@@ -475,13 +452,17 @@ export const DatePickerMixin = (subclass) =>
475
452
 
476
453
  this.addController(new VirtualKeyboardController(this));
477
454
 
478
- const overlay = this.$.overlay;
479
- this._overlayElement = overlay;
455
+ this._overlayElement = this.$.overlay;
456
+ }
480
457
 
481
- overlay.renderer = this._boundOverlayRenderer;
458
+ /** @protected */
459
+ updated(props) {
460
+ super.updated(props);
482
461
 
483
- this.addEventListener('mousedown', () => this.__bringToFront());
484
- this.addEventListener('touchstart', () => this.__bringToFront());
462
+ if (props.has('showWeekNumbers') || props.has('__effectiveI18n')) {
463
+ // Currently only supported for locales that start the week on Monday.
464
+ this.toggleAttribute('week-numbers', this.showWeekNumbers && this.__effectiveI18n.firstDayOfWeek === 1);
465
+ }
485
466
  }
486
467
 
487
468
  /** @protected */
@@ -520,14 +501,15 @@ export const DatePickerMixin = (subclass) =>
520
501
  }
521
502
 
522
503
  /** @private */
523
- _overlayRenderer(root) {
524
- if (root.firstChild) {
504
+ __ensureContent() {
505
+ if (this._overlayContent) {
525
506
  return;
526
507
  }
527
508
 
528
509
  // Create and store document content element
529
510
  const content = document.createElement('vaadin-date-picker-overlay-content');
530
- root.appendChild(content);
511
+ content.setAttribute('slot', 'overlay');
512
+ this.appendChild(content);
531
513
 
532
514
  this._overlayContent = content;
533
515
 
@@ -734,13 +716,6 @@ export const DatePickerMixin = (subclass) =>
734
716
  this.close();
735
717
  }
736
718
 
737
- /** @private */
738
- __bringToFront() {
739
- requestAnimationFrame(() => {
740
- this.$.overlay.bringToFront();
741
- });
742
- }
743
-
744
719
  /** @private */
745
720
  // eslint-disable-next-line @typescript-eslint/max-params
746
721
  _isNoInput(inputElement, fullscreen, ios, effectiveI18n, opened, autoOpenDisabled) {
@@ -774,6 +749,10 @@ export const DatePickerMixin = (subclass) =>
774
749
 
775
750
  /** @protected */
776
751
  _openedChanged(opened) {
752
+ if (opened) {
753
+ this.__ensureContent();
754
+ }
755
+
777
756
  if (this.inputElement) {
778
757
  this.inputElement.setAttribute('aria-expanded', opened);
779
758
  }
@@ -928,7 +907,7 @@ export const DatePickerMixin = (subclass) =>
928
907
  this._focus();
929
908
  }
930
909
 
931
- const input = this._nativeInput;
910
+ const input = this.inputElement;
932
911
  if (this._noInput && input) {
933
912
  input.blur();
934
913
  this._overlayContent.focusDateElement();
@@ -994,8 +973,8 @@ export const DatePickerMixin = (subclass) =>
994
973
  }
995
974
  this.__commitParsedOrFocusedDate();
996
975
 
997
- if (this._nativeInput && this._nativeInput.selectionStart) {
998
- this._nativeInput.selectionStart = this._nativeInput.selectionEnd;
976
+ if (this.inputElement && this.inputElement.selectionStart) {
977
+ this.inputElement.selectionStart = this.inputElement.selectionEnd;
999
978
  }
1000
979
  // No need to revalidate the value after `_selectedDateChanged`
1001
980
  // Needed in case the value was not changed: open and close dropdown,
@@ -1032,8 +1011,8 @@ export const DatePickerMixin = (subclass) =>
1032
1011
 
1033
1012
  /** @private */
1034
1013
  _setSelectionRange(a, b) {
1035
- if (this._nativeInput && this._nativeInput.setSelectionRange) {
1036
- this._nativeInput.setSelectionRange(a, b);
1014
+ if (this.inputElement) {
1015
+ this.inputElement.setSelectionRange(a, b);
1037
1016
  }
1038
1017
  }
1039
1018
 
@@ -1053,6 +1032,11 @@ export const DatePickerMixin = (subclass) =>
1053
1032
  * @private
1054
1033
  */
1055
1034
  _onClick(event) {
1035
+ // Ignore click events bubbling from the overlay
1036
+ if (event.composedPath().includes(this._overlayContent)) {
1037
+ return;
1038
+ }
1039
+
1056
1040
  // Clear button click is handled in separate listener
1057
1041
  // but bubbles to the host, so we need to ignore it.
1058
1042
  if (!this._isClearButton(event)) {
@@ -1141,7 +1125,12 @@ export const DatePickerMixin = (subclass) =>
1141
1125
  * @protected
1142
1126
  * @override
1143
1127
  */
1144
- _onEnter(_event) {
1128
+ _onEnter(event) {
1129
+ // Ignore Enter keydown event bubbling from the overlay
1130
+ if (event.composedPath().includes(this._overlayContent)) {
1131
+ return;
1132
+ }
1133
+
1145
1134
  if (this.opened) {
1146
1135
  // Closing will implicitly select parsed or focused date
1147
1136
  this.close();
@@ -12,12 +12,8 @@ stylesTemplate.innerHTML = `
12
12
  <style>
13
13
  :host {
14
14
  --vaadin-infinite-scroller-item-height: 270px;
15
- position: absolute;
16
- top: 0;
17
- left: 0;
18
- right: 0;
19
- bottom: 0;
20
- height: 100%;
15
+ grid-area: months;
16
+ height: auto;
21
17
  }
22
18
  </style>
23
19
  `;
@@ -3,19 +3,12 @@
3
3
  * Copyright (c) 2016 - 2025 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { flush } from '@polymer/polymer/lib/utils/flush.js';
7
6
  import { timeOut } from '@vaadin/component-base/src/async.js';
8
7
  import { Debouncer } from '@vaadin/component-base/src/debounce.js';
9
- import { addListener, setTouchAction } from '@vaadin/component-base/src/gestures.js';
8
+ import { addListener } from '@vaadin/component-base/src/gestures.js';
10
9
  import { MediaQueryController } from '@vaadin/component-base/src/media-query-controller.js';
11
10
  import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
12
- import {
13
- dateAfterXMonths,
14
- dateAllowed,
15
- dateEquals,
16
- extractDateParts,
17
- getClosestDate,
18
- } from './vaadin-date-picker-helper.js';
11
+ import { dateAfterXMonths, dateAllowed, dateEquals, getClosestDate } from './vaadin-date-picker-helper.js';
19
12
 
20
13
  /**
21
14
  * @polymerMixin
@@ -76,14 +69,6 @@ export const DatePickerOverlayContentMixin = (superClass) =>
76
69
  value: '(min-width: 375px)',
77
70
  },
78
71
 
79
- _translateX: {
80
- observer: '_translateXChanged',
81
- },
82
-
83
- _yearScrollerWidth: {
84
- value: 50,
85
- },
86
-
87
72
  i18n: {
88
73
  type: Object,
89
74
  },
@@ -179,20 +164,6 @@ export const DatePickerOverlayContentMixin = (superClass) =>
179
164
  return this.calendars.map((calendar) => calendar.focusableDateElement).find(Boolean);
180
165
  }
181
166
 
182
- /** @protected */
183
- _addListeners() {
184
- setTouchAction(this.$.scrollers, 'pan-y');
185
-
186
- addListener(this.$.scrollers, 'track', this._track.bind(this));
187
- addListener(this.shadowRoot.querySelector('[part="clear-button"]'), 'tap', this._clear.bind(this));
188
- addListener(this.shadowRoot.querySelector('[part="toggle-button"]'), 'tap', this._cancel.bind(this));
189
- addListener(
190
- this.shadowRoot.querySelector('[part="years-toggle-button"]'),
191
- 'tap',
192
- this._toggleYearScroller.bind(this),
193
- );
194
- }
195
-
196
167
  /** @protected */
197
168
  _initControllers() {
198
169
  this.addController(
@@ -207,7 +178,7 @@ export const DatePickerOverlayContentMixin = (superClass) =>
207
178
  initializer: (btn) => {
208
179
  btn.setAttribute('theme', 'tertiary');
209
180
  btn.addEventListener('keydown', (e) => this.__onTodayButtonKeyDown(e));
210
- addListener(btn, 'tap', this._onTodayTap.bind(this));
181
+ btn.addEventListener('click', this._onTodayTap.bind(this));
211
182
  this._todayButton = btn;
212
183
  },
213
184
  }),
@@ -219,7 +190,7 @@ export const DatePickerOverlayContentMixin = (superClass) =>
219
190
  initializer: (btn) => {
220
191
  btn.setAttribute('theme', 'tertiary');
221
192
  btn.addEventListener('keydown', (e) => this.__onCancelButtonKeyDown(e));
222
- addListener(btn, 'tap', this._cancel.bind(this));
193
+ btn.addEventListener('click', this._cancel.bind(this));
223
194
  this._cancelButton = btn;
224
195
  },
225
196
  }),
@@ -231,7 +202,6 @@ export const DatePickerOverlayContentMixin = (superClass) =>
231
202
 
232
203
  reset() {
233
204
  this._closeYearScroller();
234
- this._toggleAnimateClass(true);
235
205
  }
236
206
 
237
207
  /**
@@ -528,14 +498,6 @@ export const DatePickerOverlayContentMixin = (superClass) =>
528
498
  });
529
499
  }
530
500
 
531
- /** @protected */
532
- _formatDisplayed(date, i18n, label) {
533
- if (date && i18n && typeof i18n.formatDate === 'function') {
534
- return i18n.formatDate(extractDateParts(date));
535
- }
536
- return label;
537
- }
538
-
539
501
  /** @private */
540
502
  _onTodayTap() {
541
503
  const today = this._getTodayMidnight();
@@ -648,99 +610,14 @@ export const DatePickerOverlayContentMixin = (superClass) =>
648
610
  window.requestAnimationFrame(smoothScroll);
649
611
  }
650
612
 
651
- /** @private */
652
- _limit(value, range) {
653
- return Math.min(range.max, Math.max(range.min, value));
654
- }
655
-
656
- /** @private */
657
- _handleTrack(e) {
658
- // Check if horizontal movement threshold (dx) not exceeded or
659
- // scrolling fast vertically (ddy).
660
- if (Math.abs(e.detail.dx) < 10 || Math.abs(e.detail.ddy) > 10) {
661
- return;
662
- }
663
-
664
- // If we're flinging quickly -> start animating already.
665
- if (Math.abs(e.detail.ddx) > this._yearScrollerWidth / 3) {
666
- this._toggleAnimateClass(true);
667
- }
668
-
669
- const newTranslateX = this._translateX + e.detail.ddx;
670
- this._translateX = this._limit(newTranslateX, {
671
- min: 0,
672
- max: this._yearScrollerWidth,
673
- });
674
- }
675
-
676
- /** @private */
677
- _track(e) {
678
- if (this._desktopMode) {
679
- // No need to track for swipe gestures on desktop.
680
- return;
681
- }
682
-
683
- switch (e.detail.state) {
684
- case 'start':
685
- this._toggleAnimateClass(false);
686
- break;
687
- case 'track':
688
- this._handleTrack(e);
689
- break;
690
- case 'end':
691
- this._toggleAnimateClass(true);
692
- if (this._translateX >= this._yearScrollerWidth / 2) {
693
- this._closeYearScroller();
694
- } else {
695
- this._openYearScroller();
696
- }
697
- break;
698
- default:
699
- break;
700
- }
701
- }
702
-
703
- /** @private */
704
- _toggleAnimateClass(enable) {
705
- if (enable) {
706
- this.classList.add('animate');
707
- } else {
708
- this.classList.remove('animate');
709
- }
710
- }
711
-
712
613
  /** @private */
713
614
  _toggleYearScroller() {
714
- if (this._isYearScrollerVisible()) {
715
- this._closeYearScroller();
716
- } else {
717
- this._openYearScroller();
718
- }
719
- }
720
-
721
- /** @private */
722
- _openYearScroller() {
723
- this._translateX = 0;
724
- this.setAttribute('years-visible', '');
615
+ this.toggleAttribute('years-visible');
725
616
  }
726
617
 
727
618
  /** @private */
728
619
  _closeYearScroller() {
729
620
  this.removeAttribute('years-visible');
730
- this._translateX = this._yearScrollerWidth;
731
- }
732
-
733
- /** @private */
734
- _isYearScrollerVisible() {
735
- return this._translateX < this._yearScrollerWidth / 2;
736
- }
737
-
738
- /** @private */
739
- _translateXChanged(x) {
740
- if (!this._desktopMode) {
741
- this._monthScroller.style.transform = `translateX(${x - this._yearScrollerWidth}px)`;
742
- this._yearScroller.style.transform = `translateX(${x}px)`;
743
- }
744
621
  }
745
622
 
746
623
  /** @private */
@@ -770,11 +647,6 @@ export const DatePickerOverlayContentMixin = (superClass) =>
770
647
  this._close();
771
648
  }
772
649
 
773
- /** @protected */
774
- _preventDefault(e) {
775
- e.preventDefault();
776
- }
777
-
778
650
  /** @private */
779
651
  __toggleDate(date) {
780
652
  if (dateEquals(date, this.selectedDate)) {
@@ -937,8 +809,6 @@ export const DatePickerOverlayContentMixin = (superClass) =>
937
809
  await new Promise((resolve) => {
938
810
  requestAnimationFrame(() => {
939
811
  setTimeout(() => {
940
- // Force dom-repeat elements to render
941
- flush();
942
812
  resolve();
943
813
  });
944
814
  });
@@ -8,17 +8,14 @@ import './vaadin-date-picker-month-scroller.js';
8
8
  import './vaadin-date-picker-year-scroller.js';
9
9
  import './vaadin-date-picker-year.js';
10
10
  import './vaadin-month-calendar.js';
11
- import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
12
- import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
11
+ import { html, LitElement } from 'lit';
13
12
  import { defineCustomElement } from '@vaadin/component-base/src/define.js';
14
13
  import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
15
- import { registerStyles, ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
14
+ import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
15
+ import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
16
+ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
17
+ import { overlayContentStyles } from './styles/vaadin-date-picker-overlay-content-core-styles.js';
16
18
  import { DatePickerOverlayContentMixin } from './vaadin-date-picker-overlay-content-mixin.js';
17
- import { overlayContentStyles } from './vaadin-date-picker-overlay-content-styles.js';
18
-
19
- registerStyles('vaadin-date-picker-overlay-content', overlayContentStyles, {
20
- moduleId: 'vaadin-date-picker-overlay-content-styles',
21
- });
22
19
 
23
20
  /**
24
21
  * @customElement
@@ -26,43 +23,43 @@ registerStyles('vaadin-date-picker-overlay-content', overlayContentStyles, {
26
23
  * @private
27
24
  */
28
25
  class DatePickerOverlayContent extends DatePickerOverlayContentMixin(
29
- ControllerMixin(ThemableMixin(DirMixin(PolymerElement))),
26
+ ThemableMixin(DirMixin(PolylitMixin(LumoInjectionMixin(LitElement)))),
30
27
  ) {
31
- static get template() {
32
- return html`
33
- <div part="overlay-header" on-touchend="_preventDefault" aria-hidden="true">
34
- <div part="label">[[_formatDisplayed(selectedDate, i18n, label)]]</div>
35
- <div part="clear-button" hidden$="[[!selectedDate]]"></div>
36
- <div part="toggle-button"></div>
28
+ static get is() {
29
+ return 'vaadin-date-picker-overlay-content';
30
+ }
37
31
 
38
- <div part="years-toggle-button" hidden$="[[_desktopMode]]" aria-hidden="true">
39
- [[_yearAfterXMonths(_visibleMonthIndex)]]
40
- </div>
41
- </div>
32
+ static get styles() {
33
+ return overlayContentStyles;
34
+ }
42
35
 
43
- <div id="scrollers">
44
- <slot name="months"></slot>
45
- <slot name="years"></slot>
46
- </div>
36
+ /** @protected */
37
+ render() {
38
+ return html`
39
+ <slot name="months"></slot>
40
+ <slot name="years"></slot>
47
41
 
48
- <div on-touchend="_preventDefault" role="toolbar" part="toolbar">
42
+ <div role="toolbar" part="toolbar">
49
43
  <slot name="today-button"></slot>
44
+ <div
45
+ part="years-toggle-button"
46
+ ?hidden="${this._desktopMode}"
47
+ aria-hidden="true"
48
+ @click="${this._toggleYearScroller}"
49
+ >
50
+ ${this._yearAfterXMonths(this._visibleMonthIndex)}
51
+ </div>
50
52
  <slot name="cancel-button"></slot>
51
53
  </div>
52
54
  `;
53
55
  }
54
56
 
55
- static get is() {
56
- return 'vaadin-date-picker-overlay-content';
57
- }
58
-
59
57
  /** @protected */
60
- ready() {
61
- super.ready();
58
+ firstUpdated() {
59
+ super.firstUpdated();
62
60
 
63
61
  this.setAttribute('role', 'dialog');
64
62
 
65
- this._addListeners();
66
63
  this._initControllers();
67
64
  }
68
65
  }
@@ -3,17 +3,15 @@
3
3
  * Copyright (c) 2016 - 2025 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, PolymerElement } from '@polymer/polymer/polymer-element.js';
6
+ import { html, LitElement } from 'lit';
7
7
  import { defineCustomElement } from '@vaadin/component-base/src/define.js';
8
8
  import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
9
- import { overlayStyles } from '@vaadin/overlay/src/vaadin-overlay-styles.js';
10
- import { registerStyles, ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
9
+ import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
10
+ import { overlayStyles } from '@vaadin/overlay/src/styles/vaadin-overlay-core-styles.js';
11
+ import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
12
+ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
13
+ import { datePickerOverlayStyles } from './styles/vaadin-date-picker-overlay-core-styles.js';
11
14
  import { DatePickerOverlayMixin } from './vaadin-date-picker-overlay-mixin.js';
12
- import { datePickerOverlayStyles } from './vaadin-date-picker-overlay-styles.js';
13
-
14
- registerStyles('vaadin-date-picker-overlay', [overlayStyles, datePickerOverlayStyles], {
15
- moduleId: 'vaadin-date-picker-overlay-styles',
16
- });
17
15
 
18
16
  /**
19
17
  * An element used internally by `<vaadin-date-picker>`. Not intended to be used separately.
@@ -25,14 +23,21 @@ registerStyles('vaadin-date-picker-overlay', [overlayStyles, datePickerOverlaySt
25
23
  * @mixes ThemableMixin
26
24
  * @private
27
25
  */
28
- class DatePickerOverlay extends DatePickerOverlayMixin(DirMixin(ThemableMixin(PolymerElement))) {
26
+ class DatePickerOverlay extends DatePickerOverlayMixin(
27
+ DirMixin(ThemableMixin(PolylitMixin(LumoInjectionMixin(LitElement)))),
28
+ ) {
29
29
  static get is() {
30
30
  return 'vaadin-date-picker-overlay';
31
31
  }
32
32
 
33
- static get template() {
33
+ static get styles() {
34
+ return [overlayStyles, datePickerOverlayStyles];
35
+ }
36
+
37
+ /** @protected */
38
+ render() {
34
39
  return html`
35
- <div id="backdrop" part="backdrop" hidden$="[[!withBackdrop]]"></div>
40
+ <div id="backdrop" part="backdrop" ?hidden="${!this.withBackdrop}"></div>
36
41
  <div part="overlay" id="overlay">
37
42
  <div part="content" id="content">
38
43
  <slot></slot>
@@ -40,6 +45,17 @@ class DatePickerOverlay extends DatePickerOverlayMixin(DirMixin(ThemableMixin(Po
40
45
  </div>
41
46
  `;
42
47
  }
48
+
49
+ /**
50
+ * Override method from `OverlayFocusMixin` to specify content root
51
+ * used to detect whether focus should be restored on overlay close.
52
+ *
53
+ * @protected
54
+ * @override
55
+ */
56
+ get _contentRoot() {
57
+ return this.owner._overlayContent;
58
+ }
43
59
  }
44
60
 
45
61
  defineCustomElement(DatePickerOverlay);
@@ -13,10 +13,9 @@ stylesTemplate.innerHTML = `
13
13
  --vaadin-infinite-scroller-item-height: 80px;
14
14
  width: 50px;
15
15
  display: block;
16
- height: 100%;
17
- position: absolute;
18
- right: 0;
19
- transform: translateX(100%);
16
+ position: relative;
17
+ grid-area: years;
18
+ height: auto;
20
19
  -webkit-tap-highlight-color: transparent;
21
20
  -webkit-user-select: none;
22
21
  user-select: none;
@@ -3,10 +3,12 @@
3
3
  * Copyright (c) 2016 - 2025 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, PolymerElement } from '@polymer/polymer/polymer-element.js';
6
+ import { html, LitElement } from 'lit';
7
7
  import { defineCustomElement } from '@vaadin/component-base/src/define.js';
8
+ import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
9
+ import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
8
10
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
9
- import { DatePickerYearMixin } from './vaadin-date-picker-year-mixin.js';
11
+ import { datePickerYearStyles } from './styles/vaadin-date-picker-year-core-styles.js';
10
12
 
11
13
  /**
12
14
  * An element used internally by `<vaadin-date-picker>`. Not intended to be used separately.
@@ -17,23 +19,49 @@ import { DatePickerYearMixin } from './vaadin-date-picker-year-mixin.js';
17
19
  * @mixes DatePickerYearMixin
18
20
  * @private
19
21
  */
20
- export class DatePickerYear extends ThemableMixin(DatePickerYearMixin(PolymerElement)) {
22
+ export class DatePickerYear extends ThemableMixin(PolylitMixin(LumoInjectionMixin(LitElement))) {
21
23
  static get is() {
22
24
  return 'vaadin-date-picker-year';
23
25
  }
24
26
 
25
- static get template() {
27
+ static get styles() {
28
+ return datePickerYearStyles;
29
+ }
30
+
31
+ static get properties() {
32
+ return {
33
+ year: {
34
+ type: String,
35
+ sync: true,
36
+ },
37
+
38
+ selectedDate: {
39
+ type: Object,
40
+ sync: true,
41
+ },
42
+ };
43
+ }
44
+
45
+ /** @protected */
46
+ render() {
26
47
  return html`
27
- <style>
28
- :host {
29
- display: block;
30
- height: 100%;
31
- }
32
- </style>
33
- <div part="year-number">[[year]]</div>
48
+ <div part="year-number">${this.year}</div>
34
49
  <div part="year-separator" aria-hidden="true"></div>
35
50
  `;
36
51
  }
52
+
53
+ /** @protected */
54
+ updated(props) {
55
+ super.updated(props);
56
+
57
+ if (props.has('year')) {
58
+ this.toggleAttribute('current', this.year === new Date().getFullYear());
59
+ }
60
+
61
+ if (props.has('year') || props.has('selectedDate')) {
62
+ this.toggleAttribute('selected', this.selectedDate && this.selectedDate.getFullYear() === this.year);
63
+ }
64
+ }
37
65
  }
38
66
 
39
67
  defineCustomElement(DatePickerYear);