diff --git a/packages/date-picker/package.json b/packages/date-picker/package.json index 91508cdd5bf..dc70283f6fc 100644 --- a/packages/date-picker/package.json +++ b/packages/date-picker/package.json @@ -23,6 +23,7 @@ "src", "!src/vaadin-lit-date-picker-overlay-content.js", "!src/vaadin-lit-month-calendar.js", + "!src/vaadin-lit-date-picker.js", "theme", "vaadin-*.d.ts", "vaadin-*.js", diff --git a/packages/date-picker/src/vaadin-date-picker-mixin.js b/packages/date-picker/src/vaadin-date-picker-mixin.js index 62008d08e1e..f75c0284c26 100644 --- a/packages/date-picker/src/vaadin-date-picker-mixin.js +++ b/packages/date-picker/src/vaadin-date-picker-mixin.js @@ -42,14 +42,18 @@ export const DatePickerMixin = (subclass) => * @protected */ _selectedDate: { - type: Date, + type: Object, + sync: true, }, /** * @type {Date | undefined} * @protected */ - _focusedDate: Date, + _focusedDate: { + type: Object, + sync: true, + }, /** * Selected date. @@ -64,6 +68,7 @@ export const DatePickerMixin = (subclass) => type: String, notify: true, value: '', + sync: true, }, /** @@ -82,6 +87,7 @@ export const DatePickerMixin = (subclass) => reflectToAttribute: true, notify: true, observer: '_openedChanged', + sync: true, }, /** @@ -99,6 +105,7 @@ export const DatePickerMixin = (subclass) => showWeekNumbers: { type: Boolean, value: false, + sync: true, }, /** @@ -108,6 +115,7 @@ export const DatePickerMixin = (subclass) => _fullscreen: { type: Boolean, value: false, + sync: true, }, /** @@ -206,6 +214,7 @@ export const DatePickerMixin = (subclass) => */ i18n: { type: Object, + sync: true, value: () => { return { monthNames: [ @@ -276,6 +285,7 @@ export const DatePickerMixin = (subclass) => */ min: { type: String, + sync: true, }, /** @@ -289,6 +299,7 @@ export const DatePickerMixin = (subclass) => */ max: { type: String, + sync: true, }, /** @@ -299,6 +310,7 @@ export const DatePickerMixin = (subclass) => _minDate: { type: Date, computed: '__computeMinOrMaxDate(min)', + sync: true, }, /** @@ -309,6 +321,7 @@ export const DatePickerMixin = (subclass) => _maxDate: { type: Date, computed: '__computeMinOrMaxDate(max)', + sync: true, }, /** @private */ @@ -327,7 +340,10 @@ export const DatePickerMixin = (subclass) => _focusOverlayOnOpen: Boolean, /** @private */ - _overlayContent: Object, + _overlayContent: { + type: Object, + sync: true, + }, /** * In date-picker, unlike other components extending `InputMixin`, @@ -490,6 +506,22 @@ export const DatePickerMixin = (subclass) => } } + /** + * Override LitElement lifecycle callback to dispatch `change` event if needed. + * This is necessary to ensure `change` is fired after `value-changed`. + * + * @protected + * @override + */ + updated(props) { + super.updated(props); + + if (props.has('value') && this.__dispatchChange) { + this.dispatchEvent(new CustomEvent('change', { bubbles: true })); + this.__dispatchChange = false; + } + } + /** * Opens the dropdown. */ diff --git a/packages/date-picker/src/vaadin-lit-date-picker.js b/packages/date-picker/src/vaadin-lit-date-picker.js new file mode 100644 index 00000000000..a107d7ea5f6 --- /dev/null +++ b/packages/date-picker/src/vaadin-lit-date-picker.js @@ -0,0 +1,160 @@ +/** + * @license + * Copyright (c) 2016 - 2023 Vaadin Ltd. + * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ + */ +import '@vaadin/input-container/src/vaadin-input-container.js'; +import './vaadin-date-picker-overlay.js'; +import './vaadin-lit-date-picker-overlay-content.js'; +import { html, LitElement } from 'lit'; +import { ifDefined } from 'lit/directives/if-defined.js'; +import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js'; +import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js'; +import { TooltipController } from '@vaadin/component-base/src/tooltip-controller.js'; +import { InputControlMixin } from '@vaadin/field-base/src/input-control-mixin.js'; +import { InputController } from '@vaadin/field-base/src/input-controller.js'; +import { LabelledInputController } from '@vaadin/field-base/src/labelled-input-controller.js'; +import { inputFieldShared } from '@vaadin/field-base/src/styles/input-field-shared-styles.js'; +import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js'; +import { DatePickerMixin } from './vaadin-date-picker-mixin.js'; +import { datePickerStyles } from './vaadin-date-picker-styles.js'; + +/** + * LitElement based version of `` web component. + * + * ## Disclaimer + * + * This component is an experiment not intended for publishing to npm. + * There is no ETA regarding specific Vaadin version where it'll land. + * Feel free to try this code in your apps as per Apache 2.0 license. + */ +class DatePicker extends DatePickerMixin(InputControlMixin(ThemableMixin(ElementMixin(PolylitMixin(LitElement))))) { + static get is() { + return 'vaadin-date-picker'; + } + + static get styles() { + return [inputFieldShared, datePickerStyles]; + } + + static get properties() { + return { + /** @private */ + _positionTarget: { + type: Object, + sync: true, + }, + }; + } + + /** + * Used by `InputControlMixin` as a reference to the clear button element. + * @protected + * @return {!HTMLElement} + */ + get clearElement() { + return this.$.clearButton; + } + + /** @protected */ + render() { + return html` +
+
+ + +
+ + + + + + + + +
+ +
+ +
+ +
+
+ + + + + `; + } + + /** @protected */ + firstUpdated() { + super.firstUpdated(); + + this.addController( + new InputController(this, (input) => { + this._setInputElement(input); + this._setFocusElement(input); + this.stateTarget = input; + this.ariaTarget = input; + }), + ); + this.addController(new LabelledInputController(this.inputElement, this._labelController)); + + this._tooltipController = new TooltipController(this); + this.addController(this._tooltipController); + this._tooltipController.setPosition('top'); + this._tooltipController.setShouldShow((target) => !target.opened); + + this._positionTarget = this.shadowRoot.querySelector('[part="input-field"]'); + + const toggleButton = this.shadowRoot.querySelector('[part="toggle-button"]'); + toggleButton.addEventListener('mousedown', (e) => e.preventDefault()); + } + + /** @private */ + _onOpenedChanged(event) { + this.opened = event.detail.value; + } + + /** @private */ + _onVaadinOverlayClose(e) { + if (e.detail.sourceEvent && e.detail.sourceEvent.composedPath().includes(this)) { + e.preventDefault(); + } + } + + /** @private */ + _toggle(e) { + e.stopPropagation(); + if (this.$.overlay.opened) { + this.close(); + } else { + this.open(); + } + } +} + +customElements.define(DatePicker.is, DatePicker); + +export { DatePicker }; diff --git a/packages/date-picker/test/basic-lit.test.js b/packages/date-picker/test/basic-lit.test.js new file mode 100644 index 00000000000..dbeab50d7f7 --- /dev/null +++ b/packages/date-picker/test/basic-lit.test.js @@ -0,0 +1,2 @@ +import '../src/vaadin-lit-date-picker.js'; +import './basic.common.js'; diff --git a/packages/date-picker/test/basic-polymer.test.js b/packages/date-picker/test/basic-polymer.test.js new file mode 100644 index 00000000000..c95b07878f1 --- /dev/null +++ b/packages/date-picker/test/basic-polymer.test.js @@ -0,0 +1,2 @@ +import '../src/vaadin-date-picker.js'; +import './basic.common.js'; diff --git a/packages/date-picker/test/basic.test.js b/packages/date-picker/test/basic.common.js similarity index 99% rename from packages/date-picker/test/basic.test.js rename to packages/date-picker/test/basic.common.js index 632220e277d..c20991de4d2 100644 --- a/packages/date-picker/test/basic.test.js +++ b/packages/date-picker/test/basic.common.js @@ -2,7 +2,6 @@ import { expect } from '@esm-bundle/chai'; import { click, escKeyDown, fixtureSync, keyboardEventFor, nextRender, oneEvent, tap } from '@vaadin/testing-helpers'; import { sendKeys } from '@web/test-runner-commands'; import sinon from 'sinon'; -import '../src/vaadin-date-picker.js'; import { parseDate } from '../src/vaadin-date-picker-helper.js'; import { close, open, touchTap, waitForOverlayRender } from './helpers.js'; diff --git a/packages/date-picker/test/dropdown-lit.test.js b/packages/date-picker/test/dropdown-lit.test.js new file mode 100644 index 00000000000..24074f3a837 --- /dev/null +++ b/packages/date-picker/test/dropdown-lit.test.js @@ -0,0 +1,2 @@ +import '../src/vaadin-lit-date-picker.js'; +import './dropdown.common.js'; diff --git a/packages/date-picker/test/dropdown-polymer.test.js b/packages/date-picker/test/dropdown-polymer.test.js new file mode 100644 index 00000000000..d2e20970c4f --- /dev/null +++ b/packages/date-picker/test/dropdown-polymer.test.js @@ -0,0 +1,2 @@ +import '../src/vaadin-date-picker.js'; +import './dropdown.common.js'; diff --git a/packages/date-picker/test/dropdown.test.js b/packages/date-picker/test/dropdown.common.js similarity index 99% rename from packages/date-picker/test/dropdown.test.js rename to packages/date-picker/test/dropdown.common.js index 9d225a74e4b..d8f2609fad2 100644 --- a/packages/date-picker/test/dropdown.test.js +++ b/packages/date-picker/test/dropdown.common.js @@ -12,7 +12,6 @@ import { } from '@vaadin/testing-helpers'; import { sendKeys } from '@web/test-runner-commands'; import sinon from 'sinon'; -import '../src/vaadin-date-picker.js'; import { getFocusedCell, monthsEqual, open, waitForOverlayRender } from './helpers.js'; describe('dropdown', () => { diff --git a/packages/date-picker/test/events-lit.test.js b/packages/date-picker/test/events-lit.test.js new file mode 100644 index 00000000000..83c87985695 --- /dev/null +++ b/packages/date-picker/test/events-lit.test.js @@ -0,0 +1,3 @@ +import './not-animated-styles.js'; +import '../src/vaadin-lit-date-picker.js'; +import './events.common.js'; diff --git a/packages/date-picker/test/events-polymer.test.js b/packages/date-picker/test/events-polymer.test.js new file mode 100644 index 00000000000..b5ede5101ea --- /dev/null +++ b/packages/date-picker/test/events-polymer.test.js @@ -0,0 +1,3 @@ +import './not-animated-styles.js'; +import '../src/vaadin-date-picker.js'; +import './events.common.js'; diff --git a/packages/date-picker/test/events.test.js b/packages/date-picker/test/events.common.js similarity index 99% rename from packages/date-picker/test/events.test.js rename to packages/date-picker/test/events.common.js index 3c94f1c7797..8171c8c84a6 100644 --- a/packages/date-picker/test/events.test.js +++ b/packages/date-picker/test/events.common.js @@ -2,8 +2,6 @@ import { expect } from '@esm-bundle/chai'; import { fixtureSync, nextRender } from '@vaadin/testing-helpers'; import { sendKeys } from '@web/test-runner-commands'; import sinon from 'sinon'; -import './not-animated-styles.js'; -import '../vaadin-date-picker.js'; import { close, open, waitForOverlayRender, waitForScrollToFinish } from './helpers.js'; describe('events', () => { diff --git a/packages/date-picker/test/fullscreen-lit.test.js b/packages/date-picker/test/fullscreen-lit.test.js new file mode 100644 index 00000000000..f2c2b576134 --- /dev/null +++ b/packages/date-picker/test/fullscreen-lit.test.js @@ -0,0 +1,3 @@ +import './not-animated-styles.js'; +import '../src/vaadin-lit-date-picker.js'; +import './fullscreen.common.js'; diff --git a/packages/date-picker/test/fullscreen-polymer.test.js b/packages/date-picker/test/fullscreen-polymer.test.js new file mode 100644 index 00000000000..a9612da5f4f --- /dev/null +++ b/packages/date-picker/test/fullscreen-polymer.test.js @@ -0,0 +1,3 @@ +import './not-animated-styles.js'; +import '../src/vaadin-date-picker.js'; +import './fullscreen.common.js'; diff --git a/packages/date-picker/test/fullscreen.test.js b/packages/date-picker/test/fullscreen.common.js similarity index 99% rename from packages/date-picker/test/fullscreen.test.js rename to packages/date-picker/test/fullscreen.common.js index 880ba67dd21..21a3160cf35 100644 --- a/packages/date-picker/test/fullscreen.test.js +++ b/packages/date-picker/test/fullscreen.common.js @@ -2,7 +2,6 @@ import { expect } from '@esm-bundle/chai'; import { fixtureSync, nextRender, nextUpdate, tap } from '@vaadin/testing-helpers'; import { sendKeys, setViewport } from '@web/test-runner-commands'; import sinon from 'sinon'; -import '../src/vaadin-date-picker.js'; import { getFocusedCell, open, touchTap, waitForOverlayRender } from './helpers.js'; describe('fullscreen mode', () => { diff --git a/packages/date-picker/test/keyboard-input-lit.test.js b/packages/date-picker/test/keyboard-input-lit.test.js new file mode 100644 index 00000000000..a6997c884a9 --- /dev/null +++ b/packages/date-picker/test/keyboard-input-lit.test.js @@ -0,0 +1,3 @@ +import './not-animated-styles.js'; +import '../src/vaadin-lit-date-picker.js'; +import './keyboard-input.common.js'; diff --git a/packages/date-picker/test/keyboard-input-polymer.test.js b/packages/date-picker/test/keyboard-input-polymer.test.js new file mode 100644 index 00000000000..8f6857b8cd3 --- /dev/null +++ b/packages/date-picker/test/keyboard-input-polymer.test.js @@ -0,0 +1,3 @@ +import './not-animated-styles.js'; +import '../src/vaadin-date-picker.js'; +import './keyboard-input.common.js'; diff --git a/packages/date-picker/test/keyboard-input.test.js b/packages/date-picker/test/keyboard-input.common.js similarity index 99% rename from packages/date-picker/test/keyboard-input.test.js rename to packages/date-picker/test/keyboard-input.common.js index 34c8dbe50f5..8b6cbcb9f22 100644 --- a/packages/date-picker/test/keyboard-input.test.js +++ b/packages/date-picker/test/keyboard-input.common.js @@ -2,8 +2,6 @@ import { expect } from '@esm-bundle/chai'; import { aTimeout, enter, fixtureSync, nextRender, tap } from '@vaadin/testing-helpers'; import { sendKeys } from '@web/test-runner-commands'; import sinon from 'sinon'; -import './not-animated-styles.js'; -import '../vaadin-date-picker.js'; import { getAdjustedYear } from '../src/vaadin-date-picker-helper.js'; import { close, getFocusedCell, idleCallback, open, waitForOverlayRender, waitForScrollToFinish } from './helpers.js'; diff --git a/packages/date-picker/test/keyboard-navigation-lit.test.js b/packages/date-picker/test/keyboard-navigation-lit.test.js new file mode 100644 index 00000000000..ef37b63eb00 --- /dev/null +++ b/packages/date-picker/test/keyboard-navigation-lit.test.js @@ -0,0 +1,3 @@ +import './not-animated-styles.js'; +import '../src/vaadin-lit-date-picker.js'; +import './keyboard-navigation.common.js'; diff --git a/packages/date-picker/test/keyboard-navigation-polymer.test.js b/packages/date-picker/test/keyboard-navigation-polymer.test.js new file mode 100644 index 00000000000..99ac31093cf --- /dev/null +++ b/packages/date-picker/test/keyboard-navigation-polymer.test.js @@ -0,0 +1,3 @@ +import './not-animated-styles.js'; +import '../src/vaadin-date-picker.js'; +import './keyboard-navigation.common.js'; diff --git a/packages/date-picker/test/keyboard-navigation.test.js b/packages/date-picker/test/keyboard-navigation.common.js similarity index 99% rename from packages/date-picker/test/keyboard-navigation.test.js rename to packages/date-picker/test/keyboard-navigation.common.js index c747a6b63a6..6b8bc01adf3 100644 --- a/packages/date-picker/test/keyboard-navigation.test.js +++ b/packages/date-picker/test/keyboard-navigation.common.js @@ -2,8 +2,6 @@ import { expect } from '@esm-bundle/chai'; import { aTimeout, fixtureSync, nextRender } from '@vaadin/testing-helpers'; import { sendKeys } from '@web/test-runner-commands'; import sinon from 'sinon'; -import './not-animated-styles.js'; -import '../vaadin-date-picker.js'; import { getDefaultI18n, getFocusedCell, diff --git a/packages/date-picker/test/theme-propagation-lit.test.js b/packages/date-picker/test/theme-propagation-lit.test.js new file mode 100644 index 00000000000..9ed2766f617 --- /dev/null +++ b/packages/date-picker/test/theme-propagation-lit.test.js @@ -0,0 +1,3 @@ +import './not-animated-styles.js'; +import '../src/vaadin-lit-date-picker.js'; +import './theme-propagation.common.js'; diff --git a/packages/date-picker/test/theme-propagation-polymer.test.js b/packages/date-picker/test/theme-propagation-polymer.test.js new file mode 100644 index 00000000000..916a792706a --- /dev/null +++ b/packages/date-picker/test/theme-propagation-polymer.test.js @@ -0,0 +1,3 @@ +import './not-animated-styles.js'; +import '../src/vaadin-date-picker.js'; +import './theme-propagation.common.js'; diff --git a/packages/date-picker/test/theme-propagation.test.js b/packages/date-picker/test/theme-propagation.common.js similarity index 97% rename from packages/date-picker/test/theme-propagation.test.js rename to packages/date-picker/test/theme-propagation.common.js index 92adb573545..dde776041de 100644 --- a/packages/date-picker/test/theme-propagation.test.js +++ b/packages/date-picker/test/theme-propagation.common.js @@ -1,6 +1,5 @@ import { expect } from '@esm-bundle/chai'; import { fixtureSync, nextRender } from '@vaadin/testing-helpers'; -import '../src/vaadin-date-picker.js'; import { open, waitForScrollToFinish } from './helpers.js'; describe('theme attribute', () => { diff --git a/packages/date-picker/test/validation-lit-test.js b/packages/date-picker/test/validation-lit-test.js new file mode 100644 index 00000000000..0f5e3ba4a07 --- /dev/null +++ b/packages/date-picker/test/validation-lit-test.js @@ -0,0 +1,3 @@ +import './not-animated-styles.js'; +import '../src/vaadin-lit-date-picker.js'; +import './validation.common.js'; diff --git a/packages/date-picker/test/validation-pollymer.test.js b/packages/date-picker/test/validation-pollymer.test.js new file mode 100644 index 00000000000..0c4753f3c1b --- /dev/null +++ b/packages/date-picker/test/validation-pollymer.test.js @@ -0,0 +1,3 @@ +import './not-animated-styles.js'; +import '../src/vaadin-date-picker.js'; +import './validation.common.js'; diff --git a/packages/date-picker/test/validation.test.js b/packages/date-picker/test/validation.common.js similarity index 99% rename from packages/date-picker/test/validation.test.js rename to packages/date-picker/test/validation.common.js index 5ac71ca2ad8..f085c3147d1 100644 --- a/packages/date-picker/test/validation.test.js +++ b/packages/date-picker/test/validation.common.js @@ -2,11 +2,9 @@ import { expect } from '@esm-bundle/chai'; import { enter, fixtureSync, nextRender, nextUpdate, outsideClick } from '@vaadin/testing-helpers'; import { sendKeys } from '@web/test-runner-commands'; import sinon from 'sinon'; -import './not-animated-styles.js'; -import { DatePicker } from '../vaadin-date-picker.js'; import { close, open, setInputValue, waitForOverlayRender, waitForScrollToFinish } from './helpers.js'; -class DatePicker2016 extends DatePicker { +class DatePicker2016 extends customElements.get('vaadin-date-picker') { checkValidity() { return new Date(this.value).getFullYear() === 2016; } diff --git a/packages/date-picker/test/wai-aria-lit.test.js b/packages/date-picker/test/wai-aria-lit.test.js new file mode 100644 index 00000000000..88fce0df87a --- /dev/null +++ b/packages/date-picker/test/wai-aria-lit.test.js @@ -0,0 +1,3 @@ +import './not-animated-styles.js'; +import '../src/vaadin-lit-date-picker.js'; +import './wai-aria.common.js'; diff --git a/packages/date-picker/test/wai-aria-polymer.test.js b/packages/date-picker/test/wai-aria-polymer.test.js new file mode 100644 index 00000000000..25da066e140 --- /dev/null +++ b/packages/date-picker/test/wai-aria-polymer.test.js @@ -0,0 +1,3 @@ +import './not-animated-styles.js'; +import '../src/vaadin-date-picker.js'; +import './wai-aria.common.js'; diff --git a/packages/date-picker/test/wai-aria.test.js b/packages/date-picker/test/wai-aria.common.js similarity index 98% rename from packages/date-picker/test/wai-aria.test.js rename to packages/date-picker/test/wai-aria.common.js index ece76387903..53382b282e0 100644 --- a/packages/date-picker/test/wai-aria.test.js +++ b/packages/date-picker/test/wai-aria.common.js @@ -1,7 +1,5 @@ import { expect } from '@esm-bundle/chai'; import { fixtureSync, nextFrame, nextRender } from '@vaadin/testing-helpers'; -import './not-animated-styles.js'; -import '../vaadin-date-picker.js'; import { activateScroller, close, getDefaultI18n, open } from './helpers.js'; describe('WAI-ARIA', () => {