@vaadin/date-picker 23.3.0-alpha5 → 24.0.0-alpha2

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.
@@ -0,0 +1,104 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2016 - 2022 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { html } from '@polymer/polymer/lib/utils/html-tag.js';
7
+ import { InfiniteScroller } from './vaadin-infinite-scroller.js';
8
+
9
+ const stylesTemplate = html`
10
+ <style>
11
+ :host {
12
+ --vaadin-infinite-scroller-item-height: 80px;
13
+ width: 50px;
14
+ display: block;
15
+ height: 100%;
16
+ position: absolute;
17
+ right: 0;
18
+ transform: translateX(100%);
19
+ -webkit-tap-highlight-color: transparent;
20
+ -webkit-user-select: none;
21
+ -moz-user-select: none;
22
+ user-select: none;
23
+ /* Center the year scroller position. */
24
+ --vaadin-infinite-scroller-buffer-offset: 50%;
25
+ }
26
+
27
+ :host::before {
28
+ content: '';
29
+ display: block;
30
+ background: transparent;
31
+ width: 0;
32
+ height: 0;
33
+ position: absolute;
34
+ left: 0;
35
+ top: 50%;
36
+ transform: translateY(-50%);
37
+ border-width: 6px;
38
+ border-style: solid;
39
+ border-color: transparent;
40
+ border-left-color: #000;
41
+ }
42
+ </style>
43
+ `;
44
+
45
+ let memoizedTemplate;
46
+
47
+ /**
48
+ * An element used internally by `<vaadin-date-picker>`. Not intended to be used separately.
49
+ *
50
+ * @extends InfiniteScroller
51
+ * @mixes ThemableMixin
52
+ * @private
53
+ */
54
+ class DatePickerYearScroller extends InfiniteScroller {
55
+ static get is() {
56
+ return 'vaadin-date-picker-year-scroller';
57
+ }
58
+
59
+ static get template() {
60
+ if (!memoizedTemplate) {
61
+ memoizedTemplate = super.template.cloneNode(true);
62
+ memoizedTemplate.content.appendChild(stylesTemplate.content.cloneNode(true));
63
+ }
64
+
65
+ return memoizedTemplate;
66
+ }
67
+
68
+ static get properties() {
69
+ return {
70
+ bufferSize: {
71
+ type: Number,
72
+ value: 12,
73
+ },
74
+ };
75
+ }
76
+
77
+ /**
78
+ * @protected
79
+ * @override
80
+ */
81
+ _createElement() {
82
+ return document.createElement('vaadin-date-picker-year');
83
+ }
84
+
85
+ /**
86
+ * @param {HTMLElement} element
87
+ * @param {number} index
88
+ * @protected
89
+ * @override
90
+ */
91
+ _updateElement(element, index) {
92
+ element.year = this._yearAfterXYears(index);
93
+ }
94
+
95
+ /** @private */
96
+ _yearAfterXYears(index) {
97
+ const today = new Date();
98
+ const result = new Date(today);
99
+ result.setFullYear(parseInt(index) + today.getFullYear());
100
+ return result.getFullYear();
101
+ }
102
+ }
103
+
104
+ customElements.define(DatePickerYearScroller.is, DatePickerYearScroller);
@@ -0,0 +1,57 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2016 - 2022 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
7
+ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
8
+
9
+ /**
10
+ * An element used internally by `<vaadin-date-picker>`. Not intended to be used separately.
11
+ *
12
+ * @extends HTMLElement
13
+ * @mixes ThemableMixin
14
+ * @private
15
+ */
16
+ export class DatePickerYear extends ThemableMixin(PolymerElement) {
17
+ static get is() {
18
+ return 'vaadin-date-picker-year';
19
+ }
20
+
21
+ static get template() {
22
+ return html`
23
+ <style>
24
+ :host {
25
+ display: block;
26
+ height: 100%;
27
+ }
28
+ </style>
29
+ <div part="year-number">[[year]]</div>
30
+ <div part="year-separator" aria-hidden="true"></div>
31
+ `;
32
+ }
33
+
34
+ static get properties() {
35
+ return {
36
+ year: {
37
+ type: String,
38
+ },
39
+
40
+ selectedDate: {
41
+ type: Object,
42
+ },
43
+ };
44
+ }
45
+
46
+ static get observers() {
47
+ return ['__updateSelected(year, selectedDate)'];
48
+ }
49
+
50
+ /** @private */
51
+ __updateSelected(year, selectedDate) {
52
+ this.toggleAttribute('selected', selectedDate && selectedDate.getFullYear() === year);
53
+ this.toggleAttribute('current', year === new Date().getFullYear());
54
+ }
55
+ }
56
+
57
+ customElements.define(DatePickerYear.is, DatePickerYear);
@@ -79,15 +79,12 @@ export interface DatePickerEventMap extends HTMLElementEventMap, DatePickerCusto
79
79
  * Part name | Description
80
80
  * ----------------------|--------------------
81
81
  * `toggle-button` | Toggle button
82
- * `overlay-content` | The overlay element
83
82
  *
84
83
  * In addition to `<vaadin-text-field>` state attributes, the following state attributes are available for theming:
85
84
  *
86
85
  * Attribute | Description | Part name
87
86
  * -----------|--------------------------------------------------|-----------
88
87
  * `opened` | Set when the date selector overlay is opened | :host
89
- * `today` | Set on the date corresponding to the current day | date
90
- * `selected` | Set on the selected date | date
91
88
  *
92
89
  * If you want to replace the default `<input>` and its container with a custom implementation to get full control
93
90
  * over the input field, consider using the [`<vaadin-date-picker-light>`](#/elements/vaadin-date-picker-light) element.
@@ -99,6 +96,9 @@ export interface DatePickerEventMap extends HTMLElementEventMap, DatePickerCusto
99
96
  *
100
97
  * - `<vaadin-date-picker-overlay>` - has the same API as [`<vaadin-overlay>`](#/elements/vaadin-overlay).
101
98
  * - `<vaadin-date-picker-overlay-content>`
99
+ * - `<vaadin-date-picker-month-scroller>`
100
+ * - `<vaadin-date-picker-year-scroller>`
101
+ * - `<vaadin-date-picker-year>`
102
102
  * - `<vaadin-month-calendar>`
103
103
  * - [`<vaadin-input-container>`](#/elements/vaadin-input-container) - an internal element wrapping the input.
104
104
  *
@@ -111,14 +111,15 @@ export interface DatePickerEventMap extends HTMLElementEventMap, DatePickerCusto
111
111
  * `clear-button` | Fullscreen mode clear button
112
112
  * `toggle-button` | Fullscreen mode toggle button
113
113
  * `years-toggle-button` | Fullscreen mode years scroller toggle
114
- * `months` | Months scroller
115
- * `years` | Years scroller
116
- * `toolbar` | Footer bar with buttons
117
- * `today-button` | Today button
118
- * `cancel-button` | Cancel button
119
- * `month` | Month calendar
120
- * `year-number` | Year number
121
- * `year-separator` | Year separator
114
+ * `toolbar` | Footer bar with slotted buttons
115
+ *
116
+ * The following state attributes are available on the `<vaadin-date-picker-overlay-content>` element:
117
+ *
118
+ * Attribute | Description
119
+ * ----------------|-------------------------------------------------
120
+ * `desktop` | Set when the overlay content is in desktop mode
121
+ * `fullscreen` | Set when the overlay content is in fullscreen mode
122
+ * `years-visible` | Set when the year scroller is visible in fullscreen mode
122
123
  *
123
124
  * In order to style the month calendar, use `<vaadin-month-calendar>` shadow DOM parts:
124
125
  *
@@ -130,6 +131,17 @@ export interface DatePickerEventMap extends HTMLElementEventMap, DatePickerCusto
130
131
  * `week-numbers` | Week numbers container
131
132
  * `week-number` | Week number element
132
133
  * `date` | Date element
134
+ * `disabled` | Disabled date element
135
+ * `focused` | Focused date element
136
+ * `selected` | Selected date element
137
+ * `today` | Date element corresponding to the current day
138
+ *
139
+ * In order to style year scroller elements, use `<vaadin-date-picker-year>` shadow DOM parts:
140
+ *
141
+ * Part name | Description
142
+ * ----------------------|--------------------
143
+ * `year-number` | Year number
144
+ * `year-separator` | Year separator
133
145
  *
134
146
  * Note: the `theme` attribute value set on `<vaadin-date-picker>` is
135
147
  * propagated to the internal components listed above.
@@ -15,9 +15,8 @@ import { LabelledInputController } from '@vaadin/field-base/src/labelled-input-c
15
15
  import { inputFieldShared } from '@vaadin/field-base/src/styles/input-field-shared-styles.js';
16
16
  import { registerStyles, ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
17
17
  import { DatePickerMixin } from './vaadin-date-picker-mixin.js';
18
- import { datePickerStyles } from './vaadin-date-picker-styles.js';
19
18
 
20
- registerStyles('vaadin-date-picker', [inputFieldShared, datePickerStyles], { moduleId: 'vaadin-date-picker-styles' });
19
+ registerStyles('vaadin-date-picker', inputFieldShared, { moduleId: 'vaadin-date-picker-styles' });
21
20
 
22
21
  /**
23
22
  * `<vaadin-date-picker>` is an input field that allows to enter a date by typing or by selecting from a calendar overlay.
@@ -48,15 +47,12 @@ registerStyles('vaadin-date-picker', [inputFieldShared, datePickerStyles], { mod
48
47
  * Part name | Description
49
48
  * ----------------------|--------------------
50
49
  * `toggle-button` | Toggle button
51
- * `overlay-content` | The overlay element
52
50
  *
53
51
  * In addition to `<vaadin-text-field>` state attributes, the following state attributes are available for theming:
54
52
  *
55
53
  * Attribute | Description | Part name
56
54
  * -----------|--------------------------------------------------|-----------
57
55
  * `opened` | Set when the date selector overlay is opened | :host
58
- * `today` | Set on the date corresponding to the current day | date
59
- * `selected` | Set on the selected date | date
60
56
  *
61
57
  * If you want to replace the default `<input>` and its container with a custom implementation to get full control
62
58
  * over the input field, consider using the [`<vaadin-date-picker-light>`](#/elements/vaadin-date-picker-light) element.
@@ -68,6 +64,9 @@ registerStyles('vaadin-date-picker', [inputFieldShared, datePickerStyles], { mod
68
64
  *
69
65
  * - `<vaadin-date-picker-overlay>` - has the same API as [`<vaadin-overlay>`](#/elements/vaadin-overlay).
70
66
  * - `<vaadin-date-picker-overlay-content>`
67
+ * - `<vaadin-date-picker-month-scroller>`
68
+ * - `<vaadin-date-picker-year-scroller>`
69
+ * - `<vaadin-date-picker-year>`
71
70
  * - `<vaadin-month-calendar>`
72
71
  * - [`<vaadin-input-container>`](#/elements/vaadin-input-container) - an internal element wrapping the input.
73
72
  *
@@ -80,14 +79,15 @@ registerStyles('vaadin-date-picker', [inputFieldShared, datePickerStyles], { mod
80
79
  * `clear-button` | Fullscreen mode clear button
81
80
  * `toggle-button` | Fullscreen mode toggle button
82
81
  * `years-toggle-button` | Fullscreen mode years scroller toggle
83
- * `months` | Months scroller
84
- * `years` | Years scroller
85
- * `toolbar` | Footer bar with buttons
86
- * `today-button` | Today button
87
- * `cancel-button` | Cancel button
88
- * `month` | Month calendar
89
- * `year-number` | Year number
90
- * `year-separator` | Year separator
82
+ * `toolbar` | Footer bar with slotted buttons
83
+ *
84
+ * The following state attributes are available on the `<vaadin-date-picker-overlay-content>` element:
85
+ *
86
+ * Attribute | Description
87
+ * ----------------|-------------------------------------------------
88
+ * `desktop` | Set when the overlay content is in desktop mode
89
+ * `fullscreen` | Set when the overlay content is in fullscreen mode
90
+ * `years-visible` | Set when the year scroller is visible in fullscreen mode
91
91
  *
92
92
  * In order to style the month calendar, use `<vaadin-month-calendar>` shadow DOM parts:
93
93
  *
@@ -99,6 +99,17 @@ registerStyles('vaadin-date-picker', [inputFieldShared, datePickerStyles], { mod
99
99
  * `week-numbers` | Week numbers container
100
100
  * `week-number` | Week number element
101
101
  * `date` | Date element
102
+ * `disabled` | Disabled date element
103
+ * `focused` | Focused date element
104
+ * `selected` | Selected date element
105
+ * `today` | Date element corresponding to the current day
106
+ *
107
+ * In order to style year scroller elements, use `<vaadin-date-picker-year>` shadow DOM parts:
108
+ *
109
+ * Part name | Description
110
+ * ----------------------|--------------------
111
+ * `year-number` | Year number
112
+ * `year-separator` | Year separator
102
113
  *
103
114
  * Note: the `theme` attribute value set on `<vaadin-date-picker>` is
104
115
  * propagated to the internal components listed above.
@@ -128,6 +139,15 @@ class DatePicker extends DatePickerMixin(InputControlMixin(ThemableMixin(Element
128
139
  :host([opened]) {
129
140
  pointer-events: auto;
130
141
  }
142
+
143
+ :host([dir='rtl']) [part='input-field'] {
144
+ direction: ltr;
145
+ }
146
+
147
+ :host([dir='rtl']) [part='input-field'] ::slotted(input)::placeholder {
148
+ direction: rtl;
149
+ text-align: left;
150
+ }
131
151
  </style>
132
152
 
133
153
  <div class="vaadin-date-picker-container">
@@ -161,29 +181,14 @@ class DatePicker extends DatePickerMixin(InputControlMixin(ThemableMixin(Element
161
181
  <vaadin-date-picker-overlay
162
182
  id="overlay"
163
183
  fullscreen$="[[_fullscreen]]"
164
- theme$="[[__getOverlayTheme(_theme, _overlayInitialized)]]"
184
+ theme$="[[_theme]]"
185
+ opened="{{opened}}"
186
+ on-vaadin-overlay-escape-press="_onOverlayEscapePress"
165
187
  on-vaadin-overlay-open="_onOverlayOpened"
166
188
  on-vaadin-overlay-closing="_onOverlayClosed"
167
189
  restore-focus-on-close
168
190
  restore-focus-node="[[inputElement]]"
169
- disable-upgrade
170
- >
171
- <template>
172
- <vaadin-date-picker-overlay-content
173
- id="overlay-content"
174
- i18n="[[i18n]]"
175
- fullscreen$="[[_fullscreen]]"
176
- label="[[label]]"
177
- selected-date="[[_selectedDate]]"
178
- focused-date="{{_focusedDate}}"
179
- show-week-numbers="[[showWeekNumbers]]"
180
- min-date="[[_minDate]]"
181
- max-date="[[_maxDate]]"
182
- part="overlay-content"
183
- theme$="[[__getOverlayTheme(_theme, _overlayInitialized)]]"
184
- ></vaadin-date-picker-overlay-content>
185
- </template>
186
- </vaadin-date-picker-overlay>
191
+ ></vaadin-date-picker-overlay>
187
192
 
188
193
  <slot name="tooltip"></slot>
189
194
  `;
@@ -219,11 +224,6 @@ class DatePicker extends DatePickerMixin(InputControlMixin(ThemableMixin(Element
219
224
 
220
225
  const toggleButton = this.shadowRoot.querySelector('[part="toggle-button"]');
221
226
  toggleButton.addEventListener('mousedown', (e) => e.preventDefault());
222
- }
223
-
224
- /** @protected */
225
- _initOverlay() {
226
- super._initOverlay();
227
227
 
228
228
  this.$.overlay.addEventListener('vaadin-overlay-close', this._onVaadinOverlayClose.bind(this));
229
229
  }
@@ -238,7 +238,11 @@ class DatePicker extends DatePickerMixin(InputControlMixin(ThemableMixin(Element
238
238
  /** @private */
239
239
  _toggle(e) {
240
240
  e.stopPropagation();
241
- this[this._overlayInitialized && this.$.overlay.opened ? 'close' : 'open']();
241
+ if (this.$.overlay.opened) {
242
+ this.close();
243
+ } else {
244
+ this.open();
245
+ }
242
246
  }
243
247
 
244
248
  // Workaround https://github.com/vaadin/web-components/issues/2855
@@ -4,7 +4,6 @@
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';
7
- import { templatize } from '@polymer/polymer/lib/utils/templatize.js';
8
7
  import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
9
8
  import { timeOut } from '@vaadin/component-base/src/async.js';
10
9
  import { isFirefox } from '@vaadin/component-base/src/browser-utils.js';
@@ -14,7 +13,7 @@ import { Debouncer } from '@vaadin/component-base/src/debounce.js';
14
13
  * @extends HTMLElement
15
14
  * @private
16
15
  */
17
- class InfiniteScroller extends PolymerElement {
16
+ export class InfiniteScroller extends PolymerElement {
18
17
  static get template() {
19
18
  return html`
20
19
  <style>
@@ -69,10 +68,6 @@ class InfiniteScroller extends PolymerElement {
69
68
  `;
70
69
  }
71
70
 
72
- static get is() {
73
- return 'vaadin-infinite-scroller';
74
- }
75
-
76
71
  static get properties() {
77
72
  return {
78
73
  /**
@@ -130,19 +125,6 @@ class InfiniteScroller extends PolymerElement {
130
125
 
131
126
  this.$.fullHeight.style.height = `${this._initialScroll * 2}px`;
132
127
 
133
- const tpl = this.querySelector('template');
134
- this._TemplateClass = templatize(tpl, this, {
135
- forwardHostProp(prop, value) {
136
- if (prop !== 'index') {
137
- this._buffers.forEach((buffer) => {
138
- [...buffer.children].forEach((slot) => {
139
- slot._itemWrapper.instance[prop] = value;
140
- });
141
- });
142
- }
143
- },
144
- });
145
-
146
128
  // Firefox interprets elements with overflow:auto as focusable
147
129
  // https://bugzilla.mozilla.org/show_bug.cgi?id=1069739
148
130
  if (isFirefox) {
@@ -162,6 +144,24 @@ class InfiniteScroller extends PolymerElement {
162
144
  }
163
145
  }
164
146
 
147
+ /**
148
+ * @protected
149
+ * @override
150
+ */
151
+ _createElement() {
152
+ // To be implemented.
153
+ }
154
+
155
+ /**
156
+ * @param {HTMLElement} _element
157
+ * @param {number} _index
158
+ * @protected
159
+ * @override
160
+ */
161
+ _updateElement(_element, _index) {
162
+ // To be implemented.
163
+ }
164
+
165
165
  /** @private */
166
166
  _activated(active) {
167
167
  if (active && !this._initialized) {
@@ -185,6 +185,7 @@ class InfiniteScroller extends PolymerElement {
185
185
  }
186
186
 
187
187
  this._initDone = true;
188
+ this.dispatchEvent(new CustomEvent('init-done'));
188
189
  }
189
190
  }
190
191
 
@@ -339,18 +340,16 @@ class InfiniteScroller extends PolymerElement {
339
340
  itemWrapper.setAttribute('slot', slotName);
340
341
  this.appendChild(itemWrapper);
341
342
 
342
- setTimeout(() => {
343
- // Only stamp the visible instances first
344
- if (this._isVisible(itemWrapper, container)) {
345
- this._ensureStampedInstance(itemWrapper);
346
- }
347
- }, 1); // Wait for first reset
343
+ // Only stamp the visible instances first
344
+ if (this._isVisible(itemWrapper, container)) {
345
+ this._ensureStampedInstance(itemWrapper);
346
+ }
348
347
  }
349
348
  });
350
349
 
351
- setTimeout(() => {
352
- afterNextRender(this, this._finishInit.bind(this));
353
- }, 1);
350
+ afterNextRender(this, () => {
351
+ this._finishInit();
352
+ });
354
353
  }
355
354
 
356
355
  /** @private */
@@ -361,8 +360,8 @@ class InfiniteScroller extends PolymerElement {
361
360
 
362
361
  const tmpInstance = itemWrapper.instance;
363
362
 
364
- itemWrapper.instance = new this._TemplateClass({});
365
- itemWrapper.appendChild(itemWrapper.instance.root);
363
+ itemWrapper.instance = this._createElement();
364
+ itemWrapper.appendChild(itemWrapper.instance);
366
365
 
367
366
  Object.keys(tmpInstance).forEach((prop) => {
368
367
  itemWrapper.instance.set(prop, tmpInstance[prop]);
@@ -381,7 +380,7 @@ class InfiniteScroller extends PolymerElement {
381
380
  [...buffer.children].forEach((slot, index) => {
382
381
  const itemWrapper = slot._itemWrapper;
383
382
  if (!viewPortOnly || this._isVisible(itemWrapper, scrollerRect)) {
384
- itemWrapper.instance.index = firstIndex + index;
383
+ this._updateElement(itemWrapper.instance, firstIndex + index);
385
384
  }
386
385
  });
387
386
  buffer.updated = true;
@@ -395,5 +394,3 @@ class InfiniteScroller extends PolymerElement {
395
394
  return rect.bottom > container.top && rect.top < container.bottom;
396
395
  }
397
396
  }
398
-
399
- customElements.define(InfiniteScroller.is, InfiniteScroller);
@@ -32,17 +32,21 @@ class MonthCalendar extends FocusMixin(ThemableMixin(PolymerElement)) {
32
32
  display: flex;
33
33
  }
34
34
 
35
- [part='date'] {
35
+ [part~='date'] {
36
36
  outline: none;
37
37
  }
38
38
 
39
+ [part~='disabled'] {
40
+ pointer-events: none;
41
+ }
42
+
39
43
  [part='week-number'][hidden],
40
44
  [part='weekday'][hidden] {
41
45
  display: none;
42
46
  }
43
47
 
44
48
  [part='weekday'],
45
- [part='date'] {
49
+ [part~='date'] {
46
50
  width: calc(100% / 7);
47
51
  padding: 0;
48
52
  font-weight: normal;
@@ -56,7 +60,7 @@ class MonthCalendar extends FocusMixin(ThemableMixin(PolymerElement)) {
56
60
  }
57
61
 
58
62
  :host([week-numbers]) [part='weekday']:not(:empty),
59
- :host([week-numbers]) [part='date'] {
63
+ :host([week-numbers]) [part~='date'] {
60
64
  width: 12.5%;
61
65
  }
62
66
  </style>
@@ -99,12 +103,9 @@ class MonthCalendar extends FocusMixin(ThemableMixin(PolymerElement)) {
99
103
  <template is="dom-repeat" items="[[week]]">
100
104
  <td
101
105
  role="gridcell"
102
- part="date"
106
+ part$="[[__getDatePart(item, focusedDate, selectedDate, minDate, maxDate)]]"
103
107
  date="[[item]]"
104
- today$="[[_isToday(item)]]"
105
- focused$="[[__isDayFocused(item, focusedDate)]]"
106
108
  tabindex$="[[__getDayTabindex(item, focusedDate)]]"
107
- selected$="[[__isDaySelected(item, selectedDate)]]"
108
109
  disabled$="[[__isDayDisabled(item, minDate, maxDate)]]"
109
110
  aria-selected$="[[__getDayAriaSelected(item, selectedDate)]]"
110
111
  aria-disabled$="[[__getDayAriaDisabled(item, minDate, maxDate)]]"
@@ -211,7 +212,7 @@ class MonthCalendar extends FocusMixin(ThemableMixin(PolymerElement)) {
211
212
  }
212
213
 
213
214
  get focusableDateElement() {
214
- return [...this.shadowRoot.querySelectorAll('[part=date]')].find((datePart) => {
215
+ return [...this.shadowRoot.querySelectorAll('[part~=date]')].find((datePart) => {
215
216
  return dateEquals(datePart.date, this.focusedDate);
216
217
  });
217
218
  }
@@ -369,6 +370,28 @@ class MonthCalendar extends FocusMixin(ThemableMixin(PolymerElement)) {
369
370
  e.preventDefault();
370
371
  }
371
372
 
373
+ __getDatePart(date, focusedDate, selectedDate, minDate, maxDate) {
374
+ const result = ['date'];
375
+
376
+ if (this.__isDayDisabled(date, minDate, maxDate)) {
377
+ result.push('disabled');
378
+ }
379
+
380
+ if (this.__isDayFocused(date, focusedDate)) {
381
+ result.push('focused');
382
+ }
383
+
384
+ if (this.__isDaySelected(date, selectedDate)) {
385
+ result.push('selected');
386
+ }
387
+
388
+ if (this._isToday(date)) {
389
+ result.push('today');
390
+ }
391
+
392
+ return result.join(' ');
393
+ }
394
+
372
395
  __getWeekNumber(days) {
373
396
  const date = days.reduce((acc, d) => {
374
397
  return !acc && d ? d : acc;