From 60a83fb7f6818ce75f3cdf8de3d76e2d86ae5a5e Mon Sep 17 00:00:00 2001 From: Serhii Kulykov Date: Mon, 24 Oct 2022 12:47:59 +0300 Subject: [PATCH] refactor!: move date-picker scrollers to light DOM (#4770) --- .../src/vaadin-date-picker-helper.d.ts | 7 + .../src/vaadin-date-picker-helper.js | 14 + .../src/vaadin-date-picker-mixin.js | 1 + .../src/vaadin-date-picker-month-scroller.js | 74 ++++ .../src/vaadin-date-picker-overlay-content.js | 332 ++++++++++-------- .../src/vaadin-date-picker-year-scroller.js | 104 ++++++ .../src/vaadin-date-picker-year.js | 57 +++ .../date-picker/src/vaadin-date-picker.d.ts | 23 +- .../date-picker/src/vaadin-date-picker.js | 23 +- .../src/vaadin-infinite-scroller.js | 63 ++-- packages/date-picker/test/basic.test.js | 19 +- packages/date-picker/test/common.js | 37 +- .../date-picker/test/custom-input.test.js | 2 +- packages/date-picker/test/dropdown.test.js | 9 +- .../date-picker/test/keyboard-input.test.js | 25 +- .../test/keyboard-navigation.test.js | 8 +- packages/date-picker/test/overlay.test.js | 63 ++-- packages/date-picker/test/scroller.test.js | 24 +- .../test/theme-propagation.test.js | 2 +- packages/date-picker/test/wai-aria.test.js | 17 +- ...adin-date-picker-overlay-content-styles.js | 61 +--- .../lumo/vaadin-date-picker-year-styles.js | 32 ++ ...adin-date-picker-overlay-content-styles.js | 34 +- .../vaadin-date-picker-year-styles.js | 28 ++ .../src/vaadin-date-time-picker.js | 3 +- 25 files changed, 691 insertions(+), 371 deletions(-) create mode 100644 packages/date-picker/src/vaadin-date-picker-month-scroller.js create mode 100644 packages/date-picker/src/vaadin-date-picker-year-scroller.js create mode 100644 packages/date-picker/src/vaadin-date-picker-year.js create mode 100644 packages/date-picker/theme/lumo/vaadin-date-picker-year-styles.js create mode 100644 packages/date-picker/theme/material/vaadin-date-picker-year-styles.js diff --git a/packages/date-picker/src/vaadin-date-picker-helper.d.ts b/packages/date-picker/src/vaadin-date-picker-helper.d.ts index 5619ad3c825..4b389e15634 100644 --- a/packages/date-picker/src/vaadin-date-picker-helper.d.ts +++ b/packages/date-picker/src/vaadin-date-picker-helper.d.ts @@ -41,3 +41,10 @@ export { extractDateParts }; * to the expected format. */ declare function extractDateParts(date: Date): { day: number; month: number; year: number }; + +/** + * Get difference in months between today and given months value. + */ +declare function dateAfterXMonths(months: number): number; + +export { dateAfterXMonths }; diff --git a/packages/date-picker/src/vaadin-date-picker-helper.js b/packages/date-picker/src/vaadin-date-picker-helper.js index 9fb6f09d798..6142cecd0ed 100644 --- a/packages/date-picker/src/vaadin-date-picker-helper.js +++ b/packages/date-picker/src/vaadin-date-picker-helper.js @@ -103,3 +103,17 @@ export function extractDateParts(date) { year: date.getFullYear(), }; } + +/** + * Get difference in months between today and given months value. + * + * @param {number} months + * @return {number} + */ +export function dateAfterXMonths(months) { + const today = new Date(); + const result = new Date(today); + result.setDate(1); + result.setMonth(parseInt(months) + today.getMonth()); + return result; +} diff --git a/packages/date-picker/src/vaadin-date-picker-mixin.js b/packages/date-picker/src/vaadin-date-picker-mixin.js index 1ccef98125d..e0788790514 100644 --- a/packages/date-picker/src/vaadin-date-picker-mixin.js +++ b/packages/date-picker/src/vaadin-date-picker-mixin.js @@ -84,6 +84,7 @@ export const DatePickerMixin = (subclass) => */ showWeekNumbers: { type: Boolean, + value: false, }, /** diff --git a/packages/date-picker/src/vaadin-date-picker-month-scroller.js b/packages/date-picker/src/vaadin-date-picker-month-scroller.js new file mode 100644 index 00000000000..41036f1cdc1 --- /dev/null +++ b/packages/date-picker/src/vaadin-date-picker-month-scroller.js @@ -0,0 +1,74 @@ +/** + * @license + * Copyright (c) 2016 - 2022 Vaadin Ltd. + * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ + */ +import { html } from '@polymer/polymer/lib/utils/html-tag.js'; +import { dateAfterXMonths } from './vaadin-date-picker-helper.js'; +import { InfiniteScroller } from './vaadin-infinite-scroller.js'; + +const stylesTemplate = html` + +`; + +let memoizedTemplate; + +/** + * An element used internally by ``. Not intended to be used separately. + * + * @extends InfiniteScroller + * @private + */ +class DatePickerMonthScroller extends InfiniteScroller { + static get is() { + return 'vaadin-date-picker-month-scroller'; + } + + static get template() { + if (!memoizedTemplate) { + memoizedTemplate = super.template.cloneNode(true); + memoizedTemplate.content.appendChild(stylesTemplate.content.cloneNode(true)); + } + + return memoizedTemplate; + } + + static get properties() { + return { + bufferSize: { + type: Number, + value: 3, + }, + }; + } + + /** + * @protected + * @override + */ + _createElement() { + return document.createElement('vaadin-month-calendar'); + } + + /** + * @param {HTMLElement} element + * @param {number} index + * @protected + * @override + */ + _updateElement(element, index) { + element.month = dateAfterXMonths(index); + } +} + +customElements.define(DatePickerMonthScroller.is, DatePickerMonthScroller); diff --git a/packages/date-picker/src/vaadin-date-picker-overlay-content.js b/packages/date-picker/src/vaadin-date-picker-overlay-content.js index 9702b9dd8a2..ad8c9ef20cc 100644 --- a/packages/date-picker/src/vaadin-date-picker-overlay-content.js +++ b/packages/date-picker/src/vaadin-date-picker-overlay-content.js @@ -5,7 +5,11 @@ */ import '@vaadin/button/src/vaadin-button.js'; import './vaadin-month-calendar.js'; -import './vaadin-infinite-scroller.js'; +import './vaadin-date-picker-month-scroller.js'; +import './vaadin-date-picker-year-scroller.js'; +import './vaadin-date-picker-year.js'; +import { flush } from '@polymer/polymer/lib/utils/flush.js'; +import { afterNextRender } from '@polymer/polymer/lib/utils/render-status.js'; import { html, PolymerElement } from '@polymer/polymer/polymer-element.js'; import { timeOut } from '@vaadin/component-base/src/async.js'; import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js'; @@ -15,7 +19,7 @@ import { addListener, setTouchAction } from '@vaadin/component-base/src/gestures import { MediaQueryController } from '@vaadin/component-base/src/media-query-controller.js'; import { SlotController } from '@vaadin/component-base/src/slot-controller.js'; import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js'; -import { dateEquals, extractDateParts, getClosestDate } from './vaadin-date-picker-helper.js'; +import { dateAfterXMonths, dateEquals, extractDateParts, getClosestDate } from './vaadin-date-picker-helper.js'; /** * @extends HTMLElement @@ -64,62 +68,17 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po overflow: hidden; } - [part='months'], - [part='years'] { - height: 100%; - } - - [part='months'] { - --vaadin-infinite-scroller-item-height: 270px; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - } - - #scrollers[desktop] [part='months'] { + :host([desktop]) ::slotted([slot='months']) { right: 50px; transform: none !important; } - [part='years'] { - --vaadin-infinite-scroller-item-height: 80px; - width: 50px; - position: absolute; - right: 0; - transform: translateX(100%); - -webkit-tap-highlight-color: transparent; - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; - /* Center the year scroller position. */ - --vaadin-infinite-scroller-buffer-offset: 50%; - } - - #scrollers[desktop] [part='years'] { - position: absolute; + :host([desktop]) ::slotted([slot='years']) { transform: none !important; } - [part='years']::before { - content: ''; - display: block; - background: transparent; - width: 0; - height: 0; - position: absolute; - left: 0; - top: 50%; - transform: translateY(-50%); - border-width: 6px; - border-style: solid; - border-color: transparent; - border-left-color: #000; - } - - :host(.animate) [part='months'], - :host(.animate) [part='years'] { + :host(.animate) ::slotted([slot='months']), + :host(.animate) ::slotted([slot='years']) { transition: all 200ms; } @@ -131,7 +90,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po } - -
- - - - +
+ +
@@ -240,7 +156,10 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po _visibleMonthIndex: Number, - _desktopMode: Boolean, + _desktopMode: { + type: Boolean, + observer: '_desktopModeChanged', + }, _desktopMediaQuery: { type: String, @@ -261,6 +180,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po showWeekNumbers: { type: Boolean, + value: false, }, _ignoreTaps: Boolean, @@ -289,11 +209,26 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po _todayButton: { type: Object, }, + + calendars: { + type: Array, + value: () => [], + }, + + years: { + type: Array, + value: () => [], + }, }; } static get observers() { - return ['__updateCancelButton(_cancelButton, i18n)', '__updateTodayButton(_todayButton, i18n, minDate, maxDate)']; + return [ + '__updateCalendars(calendars, i18n, minDate, maxDate, selectedDate, focusedDate, showWeekNumbers, _ignoreTaps, _theme)', + '__updateCancelButton(_cancelButton, i18n)', + '__updateTodayButton(_todayButton, i18n, minDate, maxDate)', + '__updateYears(years, selectedDate, _theme)', + ]; } get __isRTL() { @@ -309,11 +244,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po * @private */ get __useSubMonthScrolling() { - return this.$.monthScroller.clientHeight < this.$.monthScroller.itemHeight + this.$.monthScroller.bufferOffset; - } - - get calendars() { - return [...this.shadowRoot.querySelectorAll('vaadin-month-calendar')]; + return this._monthScroller.clientHeight < this._monthScroller.itemHeight + this._monthScroller.bufferOffset; } get focusableDateElement() { @@ -328,7 +259,6 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po addListener(this.$.scrollers, 'track', this._track.bind(this)); addListener(this.shadowRoot.querySelector('[part="clear-button"]'), 'tap', this._clear.bind(this)); addListener(this.shadowRoot.querySelector('[part="toggle-button"]'), 'tap', this._cancel.bind(this)); - addListener(this.shadowRoot.querySelector('[part="years"]'), 'tap', this._onYearTap.bind(this)); addListener( this.shadowRoot.querySelector('[part="years-toggle-button"]'), 'tap', @@ -368,6 +298,9 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po }, ), ); + + this.__initMonthScroller(); + this.__initYearScroller(); } /** @@ -397,7 +330,76 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po scrollToDate(date, animate) { const offset = this.__useSubMonthScrolling ? this._calculateWeekScrollOffset(date) : 0; this._scrollToPosition(this._differenceInMonths(date, this._originDate) + offset, animate); - this.$.monthScroller.forceUpdate(); + this._monthScroller.forceUpdate(); + } + + __initMonthScroller() { + this.addController( + new SlotController( + this, + 'months', + () => document.createElement('vaadin-date-picker-month-scroller'), + (_, scroller) => { + scroller.addEventListener('custom-scroll', () => { + this._onMonthScroll(); + }); + + scroller.addEventListener('touchstart', () => { + this._onMonthScrollTouchStart(); + }); + + scroller.addEventListener('keydown', (e) => { + this.__onMonthCalendarKeyDown(e); + }); + + scroller.addEventListener('init-done', () => { + const calendars = [...this.querySelectorAll('vaadin-month-calendar')]; + + // Two-way binding for selectedDate property + calendars.forEach((calendar) => { + calendar.addEventListener('selected-date-changed', (e) => { + this.selectedDate = e.detail.value; + }); + }); + + this.calendars = calendars; + }); + + this._monthScroller = scroller; + }, + ), + ); + } + + __initYearScroller() { + this.addController( + new SlotController( + this, + 'years', + () => document.createElement('vaadin-date-picker-year-scroller'), + (_, scroller) => { + scroller.setAttribute('aria-hidden', 'true'); + + addListener(scroller, 'tap', (e) => { + this._onYearTap(e); + }); + + scroller.addEventListener('custom-scroll', () => { + this._onYearScroll(); + }); + + scroller.addEventListener('touchstart', () => { + this._onYearScrollTouchStart(); + }); + + scroller.addEventListener('init-done', () => { + this.years = [...this.querySelectorAll('vaadin-date-picker-year')]; + }); + + this._yearScroller = scroller; + }, + ), + ); } __updateCancelButton(cancelButton, i18n) { @@ -413,6 +415,43 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po } } + // eslint-disable-next-line max-params + __updateCalendars(calendars, i18n, minDate, maxDate, selectedDate, focusedDate, showWeekNumbers, ignoreTaps, theme) { + if (calendars && calendars.length) { + calendars.forEach((calendar) => { + calendar.setProperties({ + i18n, + minDate, + maxDate, + focusedDate, + selectedDate, + showWeekNumbers, + ignoreTaps, + }); + + if (theme) { + calendar.setAttribute('theme', theme); + } else { + calendar.removeAttribute('theme'); + } + }); + } + } + + __updateYears(years, selectedDate, theme) { + if (years && years.length) { + years.forEach((year) => { + year.selectedDate = selectedDate; + + if (theme) { + year.setAttribute('theme', theme); + } else { + year.removeAttribute('theme'); + } + }); + } + } + /** * Select a date and fire event indicating user interaction. * @protected @@ -424,18 +463,12 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po ); } - _focusedDateChanged(focusedDate) { - this.revealDate(focusedDate); - } - - _isCurrentYear(yearsFromNow) { - return yearsFromNow === 0; + _desktopModeChanged(desktopMode) { + this.toggleAttribute('desktop', desktopMode); } - _isSelectedYear(yearsFromNow, selectedDate) { - if (selectedDate) { - return selectedDate.getFullYear() === this._originDate.getFullYear() + yearsFromNow; - } + _focusedDateChanged(focusedDate) { + this.revealDate(focusedDate); } /** @@ -455,14 +488,14 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po } // Otherwise determine if we need to scroll to make the month of the date visible - const scrolledAboveViewport = this.$.monthScroller.position > diff; + const scrolledAboveViewport = this._monthScroller.position > diff; const visibleArea = Math.max( - this.$.monthScroller.itemHeight, - this.$.monthScroller.clientHeight - this.$.monthScroller.bufferOffset * 2, + this._monthScroller.itemHeight, + this._monthScroller.clientHeight - this._monthScroller.bufferOffset * 2, ); - const visibleItems = visibleArea / this.$.monthScroller.itemHeight; - const scrolledBelowViewport = this.$.monthScroller.position + visibleItems - 1 < diff; + const visibleItems = visibleArea / this._monthScroller.itemHeight; + const scrolledBelowViewport = this._monthScroller.position + visibleItems - 1 < diff; if (scrolledAboveViewport) { this._scrollToPosition(diff, animate); @@ -502,17 +535,23 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po } _initialPositionChanged(initialPosition) { + if (this._monthScroller && this._yearScroller) { + this._monthScroller.active = true; + this._yearScroller.active = true; + } + this.scrollToDate(initialPosition); } _repositionYearScroller() { - this._visibleMonthIndex = Math.floor(this.$.monthScroller.position); - this.$.yearScroller.position = (this.$.monthScroller.position + this._originDate.getMonth()) / 12; + const monthPosition = this._monthScroller.position; + this._visibleMonthIndex = Math.floor(monthPosition); + this._yearScroller.position = (monthPosition + this._originDate.getMonth()) / 12; } _repositionMonthScroller() { - this.$.monthScroller.position = this.$.yearScroller.position * 12 - this._originDate.getMonth(); - this._visibleMonthIndex = Math.floor(this.$.monthScroller.position); + this._monthScroller.position = this._yearScroller.position * 12 - this._originDate.getMonth(); + this._visibleMonthIndex = Math.floor(this._monthScroller.position); } _onMonthScroll() { @@ -555,7 +594,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po _onTodayTap() { const today = new Date(); - if (Math.abs(this.$.monthScroller.position - this._differenceInMonths(today, this._originDate)) < 0.001) { + if (Math.abs(this._monthScroller.position - this._differenceInMonths(today, this._originDate)) < 0.001) { // Select today only if the month scroller is positioned approximately // at the beginning of the current month this._selectDate(today); @@ -576,9 +615,9 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po _onYearTap(e) { if (!this._ignoreTaps && !this._notTapping) { const scrollDelta = - e.detail.y - (this.$.yearScroller.getBoundingClientRect().top + this.$.yearScroller.clientHeight / 2); - const yearDelta = scrollDelta / this.$.yearScroller.itemHeight; - this._scrollToPosition(this.$.monthScroller.position + yearDelta * 12, true); + e.detail.y - (this._yearScroller.getBoundingClientRect().top + this._yearScroller.clientHeight / 2); + const yearDelta = scrollDelta / this._yearScroller.itemHeight; + this._scrollToPosition(this._monthScroller.position + yearDelta * 12, true); } } @@ -589,7 +628,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po } if (!animate) { - this.$.monthScroller.position = targetPosition; + this._monthScroller.position = targetPosition; this._targetPosition = undefined; this._repositionYearScroller(); this.__tryFocusDate(); @@ -614,7 +653,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po }; let start = 0; - const initialPosition = this.$.monthScroller.position; + const initialPosition = this._monthScroller.position; const smoothScroll = (timestamp) => { start = start || timestamp; @@ -627,7 +666,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po this._targetPosition - initialPosition, this.scrollDuration, ); - this.$.monthScroller.position = currentPos; + this._monthScroller.position = currentPos; window.requestAnimationFrame(smoothScroll); } else { this.dispatchEvent( @@ -641,7 +680,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po }), ); - this.$.monthScroller.position = this._targetPosition; + this._monthScroller.position = this._targetPosition; this._targetPosition = undefined; revealResolve(); @@ -736,26 +775,13 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po _translateXChanged(x) { if (!this._desktopMode) { - this.$.monthScroller.style.transform = `translateX(${x - this._yearScrollerWidth}px)`; - this.$.yearScroller.style.transform = `translateX(${x}px)`; + this._monthScroller.style.transform = `translateX(${x - this._yearScrollerWidth}px)`; + this._yearScroller.style.transform = `translateX(${x}px)`; } } - _yearAfterXYears(index) { - const result = new Date(this._originDate); - result.setFullYear(parseInt(index) + this._originDate.getFullYear()); - return result.getFullYear(); - } - _yearAfterXMonths(months) { - return this._dateAfterXMonths(months).getFullYear(); - } - - _dateAfterXMonths(months) { - const result = new Date(this._originDate); - result.setDate(1); - result.setMonth(parseInt(months) + this._originDate.getMonth()); - return result; + return dateAfterXMonths(months).getFullYear(); } _differenceInMonths(date1, date2) { @@ -932,7 +958,11 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po // Wait for `vaadin-month-calendar` elements to be rendered if (!this.calendars.length) { await new Promise((resolve) => { - setTimeout(resolve); + afterNextRender(this, () => { + // Force dom-repeat elements to render + flush(); + resolve(); + }); }); } diff --git a/packages/date-picker/src/vaadin-date-picker-year-scroller.js b/packages/date-picker/src/vaadin-date-picker-year-scroller.js new file mode 100644 index 00000000000..4fbe9faccf2 --- /dev/null +++ b/packages/date-picker/src/vaadin-date-picker-year-scroller.js @@ -0,0 +1,104 @@ +/** + * @license + * Copyright (c) 2016 - 2022 Vaadin Ltd. + * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ + */ +import { html } from '@polymer/polymer/lib/utils/html-tag.js'; +import { InfiniteScroller } from './vaadin-infinite-scroller.js'; + +const stylesTemplate = html` + +`; + +let memoizedTemplate; + +/** + * An element used internally by ``. Not intended to be used separately. + * + * @extends InfiniteScroller + * @mixes ThemableMixin + * @private + */ +class DatePickerYearScroller extends InfiniteScroller { + static get is() { + return 'vaadin-date-picker-year-scroller'; + } + + static get template() { + if (!memoizedTemplate) { + memoizedTemplate = super.template.cloneNode(true); + memoizedTemplate.content.appendChild(stylesTemplate.content.cloneNode(true)); + } + + return memoizedTemplate; + } + + static get properties() { + return { + bufferSize: { + type: Number, + value: 12, + }, + }; + } + + /** + * @protected + * @override + */ + _createElement() { + return document.createElement('vaadin-date-picker-year'); + } + + /** + * @param {HTMLElement} element + * @param {number} index + * @protected + * @override + */ + _updateElement(element, index) { + element.year = this._yearAfterXYears(index); + } + + /** @private */ + _yearAfterXYears(index) { + const today = new Date(); + const result = new Date(today); + result.setFullYear(parseInt(index) + today.getFullYear()); + return result.getFullYear(); + } +} + +customElements.define(DatePickerYearScroller.is, DatePickerYearScroller); diff --git a/packages/date-picker/src/vaadin-date-picker-year.js b/packages/date-picker/src/vaadin-date-picker-year.js new file mode 100644 index 00000000000..efce7a15903 --- /dev/null +++ b/packages/date-picker/src/vaadin-date-picker-year.js @@ -0,0 +1,57 @@ +/** + * @license + * Copyright (c) 2016 - 2022 Vaadin Ltd. + * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ + */ +import { html, PolymerElement } from '@polymer/polymer/polymer-element.js'; +import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js'; + +/** + * An element used internally by ``. Not intended to be used separately. + * + * @extends HTMLElement + * @mixes ThemableMixin + * @private + */ +export class DatePickerYear extends ThemableMixin(PolymerElement) { + static get is() { + return 'vaadin-date-picker-year'; + } + + static get template() { + return html` + +
[[year]]
+ + `; + } + + static get properties() { + return { + year: { + type: String, + }, + + selectedDate: { + type: Object, + }, + }; + } + + static get observers() { + return ['__updateSelected(year, selectedDate)']; + } + + /** @private */ + __updateSelected(year, selectedDate) { + this.toggleAttribute('selected', selectedDate && selectedDate.getFullYear() === year); + this.toggleAttribute('current', year === new Date().getFullYear()); + } +} + +customElements.define(DatePickerYear.is, DatePickerYear); diff --git a/packages/date-picker/src/vaadin-date-picker.d.ts b/packages/date-picker/src/vaadin-date-picker.d.ts index 0551ca2899e..f5b2eaf6c58 100644 --- a/packages/date-picker/src/vaadin-date-picker.d.ts +++ b/packages/date-picker/src/vaadin-date-picker.d.ts @@ -98,6 +98,9 @@ export interface DatePickerEventMap extends HTMLElementEventMap, DatePickerCusto * * - `` - has the same API as [``](#/elements/vaadin-overlay). * - `` + * - `` + * - `` + * - `` * - `` * - [``](#/elements/vaadin-input-container) - an internal element wrapping the input. * @@ -110,12 +113,15 @@ export interface DatePickerEventMap extends HTMLElementEventMap, DatePickerCusto * `clear-button` | Fullscreen mode clear button * `toggle-button` | Fullscreen mode toggle button * `years-toggle-button` | Fullscreen mode years scroller toggle - * `months` | Months scroller - * `years` | Years scroller * `toolbar` | Footer bar with slotted buttons - * `month` | Month calendar - * `year-number` | Year number - * `year-separator` | Year separator + * + * The following state attributes are available on the `` element: + * + * Attribute | Description + * ----------------|------------------------------------------------- + * `desktop` | Set when the overlay content is in desktop mode + * `fullscreen` | Set when the overlay content is in fullscreen mode + * `years-visible` | Set when the year scroller is visible in fullscreen mode * * In order to style the month calendar, use `` shadow DOM parts: * @@ -128,6 +134,13 @@ export interface DatePickerEventMap extends HTMLElementEventMap, DatePickerCusto * `week-number` | Week number element * `date` | Date element * + * In order to style year scroller elements, use `` shadow DOM parts: + * + * Part name | Description + * ----------------------|-------------------- + * `year-number` | Year number + * `year-separator` | Year separator + * * Note: the `theme` attribute value set on `` is * propagated to the internal components listed above. * diff --git a/packages/date-picker/src/vaadin-date-picker.js b/packages/date-picker/src/vaadin-date-picker.js index 5073a8775f4..2a31ed8001c 100644 --- a/packages/date-picker/src/vaadin-date-picker.js +++ b/packages/date-picker/src/vaadin-date-picker.js @@ -66,6 +66,9 @@ registerStyles('vaadin-date-picker', inputFieldShared, { moduleId: 'vaadin-date- * * - `` - has the same API as [``](#/elements/vaadin-overlay). * - `` + * - `` + * - `` + * - `` * - `` * - [``](#/elements/vaadin-input-container) - an internal element wrapping the input. * @@ -78,12 +81,15 @@ registerStyles('vaadin-date-picker', inputFieldShared, { moduleId: 'vaadin-date- * `clear-button` | Fullscreen mode clear button * `toggle-button` | Fullscreen mode toggle button * `years-toggle-button` | Fullscreen mode years scroller toggle - * `months` | Months scroller - * `years` | Years scroller * `toolbar` | Footer bar with slotted buttons - * `month` | Month calendar - * `year-number` | Year number - * `year-separator` | Year separator + * + * The following state attributes are available on the `` element: + * + * Attribute | Description + * ----------------|------------------------------------------------- + * `desktop` | Set when the overlay content is in desktop mode + * `fullscreen` | Set when the overlay content is in fullscreen mode + * `years-visible` | Set when the year scroller is visible in fullscreen mode * * In order to style the month calendar, use `` shadow DOM parts: * @@ -96,6 +102,13 @@ registerStyles('vaadin-date-picker', inputFieldShared, { moduleId: 'vaadin-date- * `week-number` | Week number element * `date` | Date element * + * In order to style year scroller elements, use `` shadow DOM parts: + * + * Part name | Description + * ----------------------|-------------------- + * `year-number` | Year number + * `year-separator` | Year separator + * * Note: the `theme` attribute value set on `` is * propagated to the internal components listed above. * diff --git a/packages/date-picker/src/vaadin-infinite-scroller.js b/packages/date-picker/src/vaadin-infinite-scroller.js index b4f8336c924..412883a42ba 100644 --- a/packages/date-picker/src/vaadin-infinite-scroller.js +++ b/packages/date-picker/src/vaadin-infinite-scroller.js @@ -4,7 +4,6 @@ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ */ import { afterNextRender } from '@polymer/polymer/lib/utils/render-status.js'; -import { templatize } from '@polymer/polymer/lib/utils/templatize.js'; import { html, PolymerElement } from '@polymer/polymer/polymer-element.js'; import { timeOut } from '@vaadin/component-base/src/async.js'; import { isFirefox } from '@vaadin/component-base/src/browser-utils.js'; @@ -14,7 +13,7 @@ import { Debouncer } from '@vaadin/component-base/src/debounce.js'; * @extends HTMLElement * @private */ -class InfiniteScroller extends PolymerElement { +export class InfiniteScroller extends PolymerElement { static get template() { return html`