From 869d32d14b2810b1a3358fe80fb35a2f16242998 Mon Sep 17 00:00:00 2001 From: Serhii Kulykov Date: Fri, 1 Nov 2024 16:04:15 +0200 Subject: [PATCH] experiment: add LitElement based version of vaadin-time-picker (#8080) --- .../src/vaadin-lit-time-picker-combo-box.js | 113 ++++++++++++ .../src/vaadin-lit-time-picker-item.js | 50 ++++++ .../src/vaadin-lit-time-picker-overlay.js | 76 +++++++++ .../src/vaadin-lit-time-picker-scroller.js | 59 +++++++ .../time-picker/src/vaadin-lit-time-picker.js | 161 ++++++++++++++++++ .../src/vaadin-time-picker-mixin.js | 9 + packages/time-picker/test/aria-lit.test.js | 2 + .../time-picker/test/aria-polymer.test.js | 2 + .../test/{aria.test.js => aria.common.js} | 10 +- .../time-picker/test/combo-box-lit.test.js | 2 + .../test/combo-box-polymer.test.js | 2 + ...{combo-box.test.js => combo-box.common.js} | 10 +- packages/time-picker/test/events-lit.test.js | 2 + .../time-picker/test/events-polymer.test.js | 2 + .../test/{events.test.js => events.common.js} | 7 +- .../test/keyboard-navigation-lit.test.js | 2 + .../test/keyboard-navigation-polymer.test.js | 2 + ....test.js => keyboard-navigation.common.js} | 9 +- .../time-picker/test/time-picker-lit.test.js | 2 + .../test/time-picker-polymer.test.js | 2 + ...e-picker.test.js => time-picker.common.js} | 20 ++- .../time-picker/test/validation-lit.test.js | 2 + .../test/validation-polymer.test.js | 2 + ...alidation.test.js => validation.common.js} | 29 ++-- .../time-picker/test/value-commit-lit.test.js | 2 + .../test/value-commit-polymer.test.js | 2 + ...-commit.test.js => value-commit.common.js} | 1 - .../theme/lumo/vaadin-lit-time-picker.js | 7 + .../theme/material/vaadin-lit-time-picker.js | 7 + .../time-picker/vaadin-lit-time-picker.d.ts | 1 + .../time-picker/vaadin-lit-time-picker.js | 2 + 31 files changed, 561 insertions(+), 38 deletions(-) create mode 100644 packages/time-picker/src/vaadin-lit-time-picker-combo-box.js create mode 100644 packages/time-picker/src/vaadin-lit-time-picker-item.js create mode 100644 packages/time-picker/src/vaadin-lit-time-picker-overlay.js create mode 100644 packages/time-picker/src/vaadin-lit-time-picker-scroller.js create mode 100644 packages/time-picker/src/vaadin-lit-time-picker.js create mode 100644 packages/time-picker/test/aria-lit.test.js create mode 100644 packages/time-picker/test/aria-polymer.test.js rename packages/time-picker/test/{aria.test.js => aria.common.js} (91%) create mode 100644 packages/time-picker/test/combo-box-lit.test.js create mode 100644 packages/time-picker/test/combo-box-polymer.test.js rename packages/time-picker/test/{combo-box.test.js => combo-box.common.js} (96%) create mode 100644 packages/time-picker/test/events-lit.test.js create mode 100644 packages/time-picker/test/events-polymer.test.js rename packages/time-picker/test/{events.test.js => events.common.js} (95%) create mode 100644 packages/time-picker/test/keyboard-navigation-lit.test.js create mode 100644 packages/time-picker/test/keyboard-navigation-polymer.test.js rename packages/time-picker/test/{keyboard-navigation.test.js => keyboard-navigation.common.js} (96%) create mode 100644 packages/time-picker/test/time-picker-lit.test.js create mode 100644 packages/time-picker/test/time-picker-polymer.test.js rename packages/time-picker/test/{time-picker.test.js => time-picker.common.js} (97%) create mode 100644 packages/time-picker/test/validation-lit.test.js create mode 100644 packages/time-picker/test/validation-polymer.test.js rename packages/time-picker/test/{validation.test.js => validation.common.js} (92%) create mode 100644 packages/time-picker/test/value-commit-lit.test.js create mode 100644 packages/time-picker/test/value-commit-polymer.test.js rename packages/time-picker/test/{value-commit.test.js => value-commit.common.js} (99%) create mode 100644 packages/time-picker/theme/lumo/vaadin-lit-time-picker.js create mode 100644 packages/time-picker/theme/material/vaadin-lit-time-picker.js create mode 100644 packages/time-picker/vaadin-lit-time-picker.d.ts create mode 100644 packages/time-picker/vaadin-lit-time-picker.js diff --git a/packages/time-picker/src/vaadin-lit-time-picker-combo-box.js b/packages/time-picker/src/vaadin-lit-time-picker-combo-box.js new file mode 100644 index 0000000000..bb6f692882 --- /dev/null +++ b/packages/time-picker/src/vaadin-lit-time-picker-combo-box.js @@ -0,0 +1,113 @@ +/** + * @license + * Copyright (c) 2018 - 2024 Vaadin Ltd. + * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ + */ +import './vaadin-lit-time-picker-item.js'; +import './vaadin-lit-time-picker-overlay.js'; +import './vaadin-lit-time-picker-scroller.js'; +import { css, html, LitElement } from 'lit'; +import { ifDefined } from 'lit/directives/if-defined.js'; +import { ComboBoxMixin } from '@vaadin/combo-box/src/vaadin-combo-box-mixin.js'; +import { defineCustomElement } from '@vaadin/component-base/src/define.js'; +import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js'; +import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js'; + +/** + * An element used internally by ``. Not intended to be used separately. + * + * @customElement + * @extends HTMLElement + * @mixes ComboBoxMixin + * @mixes ThemableMixin + * @private + */ +class TimePickerComboBox extends ComboBoxMixin(ThemableMixin(PolylitMixin(LitElement))) { + static get is() { + return 'vaadin-time-picker-combo-box'; + } + + static get styles() { + return css` + :host([opened]) { + pointer-events: auto; + } + `; + } + + static get properties() { + return { + positionTarget: { + type: Object, + }, + }; + } + + /** + * Tag name prefix used by scroller and items. + * @protected + * @return {string} + */ + get _tagNamePrefix() { + return 'vaadin-time-picker'; + } + + /** + * Reference to the clear button element. + * @protected + * @return {!HTMLElement} + */ + get clearElement() { + return this.querySelector('[part="clear-button"]'); + } + + /** + * @override + * @protected + */ + get _inputElementValue() { + return super._inputElementValue; + } + + /** + * The setter is overridden to ensure the `_hasInputValue` property + * doesn't wrongly indicate true after the input element's value + * is reverted or cleared programmatically. + * + * @override + * @protected + */ + set _inputElementValue(value) { + super._inputElementValue = value; + this._hasInputValue = value && value.length > 0; + } + + /** @protected */ + render() { + return html` + + + + `; + } + /** @protected */ + ready() { + super.ready(); + + this.allowCustomValue = true; + this._toggleElement = this.querySelector('.toggle-button'); + + // See https://github.com/vaadin/vaadin-time-picker/issues/145 + this.setAttribute('dir', 'ltr'); + } +} + +defineCustomElement(TimePickerComboBox); diff --git a/packages/time-picker/src/vaadin-lit-time-picker-item.js b/packages/time-picker/src/vaadin-lit-time-picker-item.js new file mode 100644 index 0000000000..5059c119e0 --- /dev/null +++ b/packages/time-picker/src/vaadin-lit-time-picker-item.js @@ -0,0 +1,50 @@ +/** + * @license + * Copyright (c) 2018 - 2024 Vaadin Ltd. + * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ + */ +import { css, html, LitElement } from 'lit'; +import { ComboBoxItemMixin } from '@vaadin/combo-box/src/vaadin-combo-box-item-mixin.js'; +import { defineCustomElement } from '@vaadin/component-base/src/define.js'; +import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js'; +import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js'; +import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js'; + +/** + * LitElement based version of `` web component. + * + * ## Disclaimer + * + * This component is an experiment and not yet a part of Vaadin platform. + * 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. + */ +export class TimePickerItem extends ComboBoxItemMixin(ThemableMixin(DirMixin(PolylitMixin(LitElement)))) { + static get is() { + return 'vaadin-time-picker-item'; + } + + static get styles() { + return css` + :host { + display: block; + } + + :host([hidden]) { + display: none !important; + } + `; + } + + /** @protected */ + render() { + return html` + +
+ +
+ `; + } +} + +defineCustomElement(TimePickerItem); diff --git a/packages/time-picker/src/vaadin-lit-time-picker-overlay.js b/packages/time-picker/src/vaadin-lit-time-picker-overlay.js new file mode 100644 index 0000000000..b15139f4d0 --- /dev/null +++ b/packages/time-picker/src/vaadin-lit-time-picker-overlay.js @@ -0,0 +1,76 @@ +/** + * @license + * Copyright (c) 2018 - 2024 Vaadin Ltd. + * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ + */ +import { css, html, LitElement } from 'lit'; +import { ComboBoxOverlayMixin } from '@vaadin/combo-box/src/vaadin-combo-box-overlay-mixin.js'; +import { defineCustomElement } from '@vaadin/component-base/src/define.js'; +import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js'; +import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js'; +import { OverlayMixin } from '@vaadin/overlay/src/vaadin-overlay-mixin.js'; +import { overlayStyles } from '@vaadin/overlay/src/vaadin-overlay-styles.js'; +import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js'; + +const timePickerOverlayStyles = css` + #overlay { + width: var(--vaadin-time-picker-overlay-width, var(--_vaadin-time-picker-overlay-default-width, auto)); + } + + [part='content'] { + display: flex; + flex-direction: column; + height: 100%; + } +`; + +/** + * An element used internally by ``. Not intended to be used separately. + * + * @extends HTMLElement + * @mixes ComboBoxOverlayMixin + * @mixes DirMixin + * @mixes OverlayMixin + * @mixes ThemableMixin + * @private + */ +export class TimePickerOverlay extends ComboBoxOverlayMixin( + OverlayMixin(DirMixin(ThemableMixin(PolylitMixin(LitElement)))), +) { + static get is() { + return 'vaadin-time-picker-overlay'; + } + + static get styles() { + return [overlayStyles, timePickerOverlayStyles]; + } + + static get properties() { + return { + /** + * When true, the overlay is visible and attached to body. + * This property config is overridden to set `sync: true`. + */ + opened: { + type: Boolean, + notify: true, + observer: '_openedChanged', + reflectToAttribute: true, + sync: true, + }, + }; + } + + /** @protected */ + render() { + return html` + +
+
+
+
+ `; + } +} + +defineCustomElement(TimePickerOverlay); diff --git a/packages/time-picker/src/vaadin-lit-time-picker-scroller.js b/packages/time-picker/src/vaadin-lit-time-picker-scroller.js new file mode 100644 index 0000000000..15c36023aa --- /dev/null +++ b/packages/time-picker/src/vaadin-lit-time-picker-scroller.js @@ -0,0 +1,59 @@ +/** + * @license + * Copyright (c) 2015 - 2024 Vaadin Ltd. + * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ + */ +import { css, html, LitElement } from 'lit'; +import { ComboBoxScrollerMixin } from '@vaadin/combo-box/src/vaadin-combo-box-scroller-mixin.js'; +import { defineCustomElement } from '@vaadin/component-base/src/define.js'; +import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js'; + +/** + * An element used internally by ``. Not intended to be used separately. + * + * @extends HTMLElement + * @mixes ComboBoxScrollerMixin + * @private + */ +export class TimePickerScroller extends ComboBoxScrollerMixin(PolylitMixin(LitElement)) { + static get is() { + return 'vaadin-time-picker-scroller'; + } + + static get styles() { + return css` + :host { + display: block; + min-height: 1px; + overflow: auto; + + /* Fixes item background from getting on top of scrollbars on Safari */ + transform: translate3d(0, 0, 0); + + /* Enable momentum scrolling on iOS */ + -webkit-overflow-scrolling: touch; + + /* Fixes scrollbar disappearing when 'Show scroll bars: Always' enabled in Safari */ + box-shadow: 0 0 0 white; + } + + #selector { + border-width: var(--_vaadin-time-picker-items-container-border-width); + border-style: var(--_vaadin-time-picker-items-container-border-style); + border-color: var(--_vaadin-time-picker-items-container-border-color, transparent); + position: relative; + } + `; + } + + /** @protected */ + render() { + return html` +
+ +
+ `; + } +} + +defineCustomElement(TimePickerScroller); diff --git a/packages/time-picker/src/vaadin-lit-time-picker.js b/packages/time-picker/src/vaadin-lit-time-picker.js new file mode 100644 index 0000000000..b86e58ea34 --- /dev/null +++ b/packages/time-picker/src/vaadin-lit-time-picker.js @@ -0,0 +1,161 @@ +/** + * @license + * Copyright (c) 2018 - 2024 Vaadin Ltd. + * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ + */ +import '@vaadin/input-container/src/vaadin-lit-input-container.js'; +import './vaadin-lit-time-picker-combo-box.js'; +import { css, html, LitElement } from 'lit'; +import { ifDefined } from 'lit/directives/if-defined.js'; +import { defineCustomElement } from '@vaadin/component-base/src/define.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 { 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 { TimePickerMixin } from './vaadin-time-picker-mixin.js'; + +/** + * LitElement based version of `` web component. + * + * ## Disclaimer + * + * This component is an experiment and not yet a part of Vaadin platform. + * 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 TimePicker extends TimePickerMixin(ThemableMixin(ElementMixin(PolylitMixin(LitElement)))) { + static get is() { + return 'vaadin-time-picker'; + } + + static get styles() { + return [ + inputFieldShared, + css` + /* See https://github.com/vaadin/vaadin-time-picker/issues/145 */ + :host([dir='rtl']) [part='input-field'] { + direction: ltr; + } + + :host([dir='rtl']) [part='input-field'] ::slotted(input)::placeholder { + direction: rtl; + text-align: left; + } + + [part~='toggle-button'] { + cursor: pointer; + } + `, + ]; + } + + static get properties() { + return { + /** @private */ + _inputContainer: { + type: Object, + }, + }; + } + + /** @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; + }, + { + // The "search" word is a trick to prevent Safari from enabling AutoFill, + // which is causing click issues: + // https://github.com/vaadin/web-components/issues/6817#issuecomment-2268229567 + uniqueIdPrefix: 'search-input', + }, + ), + ); + this.addController(new LabelledInputController(this.inputElement, this._labelController)); + this._inputContainer = this.shadowRoot.querySelector('[part~="input-field"]'); + + this._tooltipController = new TooltipController(this); + this._tooltipController.setShouldShow((timePicker) => !timePicker.opened); + this._tooltipController.setPosition('top'); + this._tooltipController.setAriaTarget(this.inputElement); + this.addController(this._tooltipController); + } + + /** @private */ + __onComboBoxOpenedChanged(event) { + this.opened = event.detail.value; + } + + /** @private */ + __onComboBoxValueChanged(event) { + this._comboBoxValue = event.detail.value; + } +} + +defineCustomElement(TimePicker); + +export { TimePicker }; diff --git a/packages/time-picker/src/vaadin-time-picker-mixin.js b/packages/time-picker/src/vaadin-time-picker-mixin.js index 40e9d42593..492ef1458a 100644 --- a/packages/time-picker/src/vaadin-time-picker-mixin.js +++ b/packages/time-picker/src/vaadin-time-picker-mixin.js @@ -34,6 +34,7 @@ export const TimePickerMixin = (superClass) => type: String, notify: true, value: '', + sync: true, }, /** @@ -44,6 +45,7 @@ export const TimePickerMixin = (superClass) => notify: true, value: false, reflectToAttribute: true, + sync: true, }, /** @@ -58,6 +60,7 @@ export const TimePickerMixin = (superClass) => min: { type: String, value: '', + sync: true, }, /** @@ -72,6 +75,7 @@ export const TimePickerMixin = (superClass) => max: { type: String, value: '', + sync: true, }, /** @@ -92,6 +96,7 @@ export const TimePickerMixin = (superClass) => */ step: { type: Number, + sync: true, }, /** @@ -100,6 +105,7 @@ export const TimePickerMixin = (superClass) => */ autoOpenDisabled: { type: Boolean, + sync: true, }, /** @@ -144,6 +150,7 @@ export const TimePickerMixin = (superClass) => */ i18n: { type: Object, + sync: true, value: () => { return { formatTime: formatISOTime, @@ -155,12 +162,14 @@ export const TimePickerMixin = (superClass) => /** @private */ _comboBoxValue: { type: String, + sync: true, observer: '__comboBoxValueChanged', }, /** @private */ __dropdownItems: { type: Array, + sync: true, }, }; } diff --git a/packages/time-picker/test/aria-lit.test.js b/packages/time-picker/test/aria-lit.test.js new file mode 100644 index 0000000000..bf96336948 --- /dev/null +++ b/packages/time-picker/test/aria-lit.test.js @@ -0,0 +1,2 @@ +import '../src/vaadin-lit-time-picker.js'; +import './aria.common.js'; diff --git a/packages/time-picker/test/aria-polymer.test.js b/packages/time-picker/test/aria-polymer.test.js new file mode 100644 index 0000000000..1d70cd3b3a --- /dev/null +++ b/packages/time-picker/test/aria-polymer.test.js @@ -0,0 +1,2 @@ +import '../src/vaadin-time-picker.js'; +import './aria.common.js'; diff --git a/packages/time-picker/test/aria.test.js b/packages/time-picker/test/aria.common.js similarity index 91% rename from packages/time-picker/test/aria.test.js rename to packages/time-picker/test/aria.common.js index c0bbfaba41..1636a5d4b3 100644 --- a/packages/time-picker/test/aria.test.js +++ b/packages/time-picker/test/aria.common.js @@ -1,12 +1,12 @@ import { expect } from '@vaadin/chai-plugins'; -import { arrowDownKeyDown, escKeyDown, fixtureSync, nextFrame } from '@vaadin/testing-helpers'; -import '../src/vaadin-time-picker.js'; +import { arrowDownKeyDown, escKeyDown, fixtureSync, nextFrame, nextRender } from '@vaadin/testing-helpers'; describe('ARIA', () => { let timePicker, comboBox, input; - beforeEach(() => { + beforeEach(async () => { timePicker = fixtureSync(``); + await nextRender(); comboBox = timePicker.$.comboBox; input = timePicker.inputElement; }); @@ -41,12 +41,14 @@ describe('ARIA', () => { expect(input.getAttribute('aria-activedescendant')).to.equal(items[1].id); }); - it('should set aria-selected on item elements depending on the selected item', () => { + it('should set aria-selected on item elements depending on the selected item', async () => { timePicker.value = '00:00'; + await nextFrame(); expect(items[0].getAttribute('aria-selected')).to.equal('true'); expect(items[1].getAttribute('aria-selected')).to.equal('false'); timePicker.value = '01:00'; + await nextFrame(); expect(items[0].getAttribute('aria-selected')).to.equal('false'); expect(items[1].getAttribute('aria-selected')).to.equal('true'); }); diff --git a/packages/time-picker/test/combo-box-lit.test.js b/packages/time-picker/test/combo-box-lit.test.js new file mode 100644 index 0000000000..94252f2821 --- /dev/null +++ b/packages/time-picker/test/combo-box-lit.test.js @@ -0,0 +1,2 @@ +import '../src/vaadin-lit-time-picker.js'; +import './combo-box.common.js'; diff --git a/packages/time-picker/test/combo-box-polymer.test.js b/packages/time-picker/test/combo-box-polymer.test.js new file mode 100644 index 0000000000..2945d12405 --- /dev/null +++ b/packages/time-picker/test/combo-box-polymer.test.js @@ -0,0 +1,2 @@ +import '../src/vaadin-time-picker.js'; +import './combo-box.common.js'; diff --git a/packages/time-picker/test/combo-box.test.js b/packages/time-picker/test/combo-box.common.js similarity index 96% rename from packages/time-picker/test/combo-box.test.js rename to packages/time-picker/test/combo-box.common.js index d100e97130..9d3d866a8a 100644 --- a/packages/time-picker/test/combo-box.test.js +++ b/packages/time-picker/test/combo-box.common.js @@ -1,14 +1,13 @@ import { expect } from '@vaadin/chai-plugins'; -import { enter, fixtureSync } from '@vaadin/testing-helpers'; -import './not-animated-styles.js'; -import '../vaadin-time-picker.js'; +import { enter, fixtureSync, nextRender } from '@vaadin/testing-helpers'; import { setInputValue } from './helpers.js'; describe('combo-box', () => { let timePicker, comboBox; - beforeEach(() => { + beforeEach(async () => { timePicker = fixtureSync(``); + await nextRender(); comboBox = timePicker.$.comboBox; }); @@ -111,8 +110,9 @@ describe('combo-box', () => { describe('autoOpenDisabled', () => { let timePicker, inputElement; - beforeEach(() => { + beforeEach(async () => { timePicker = fixtureSync(``); + await nextRender(); inputElement = timePicker.inputElement; }); diff --git a/packages/time-picker/test/events-lit.test.js b/packages/time-picker/test/events-lit.test.js new file mode 100644 index 0000000000..10f6e586c4 --- /dev/null +++ b/packages/time-picker/test/events-lit.test.js @@ -0,0 +1,2 @@ +import '../src/vaadin-lit-time-picker.js'; +import './events.common.js'; diff --git a/packages/time-picker/test/events-polymer.test.js b/packages/time-picker/test/events-polymer.test.js new file mode 100644 index 0000000000..b8f43c65f4 --- /dev/null +++ b/packages/time-picker/test/events-polymer.test.js @@ -0,0 +1,2 @@ +import '../src/vaadin-time-picker.js'; +import './events.common.js'; diff --git a/packages/time-picker/test/events.test.js b/packages/time-picker/test/events.common.js similarity index 95% rename from packages/time-picker/test/events.test.js rename to packages/time-picker/test/events.common.js index 466d8f9f74..5dadd69c55 100644 --- a/packages/time-picker/test/events.test.js +++ b/packages/time-picker/test/events.common.js @@ -1,9 +1,7 @@ import { expect } from '@vaadin/chai-plugins'; -import { fixtureSync } from '@vaadin/testing-helpers'; +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-time-picker.js'; describe('events', () => { let timePicker; @@ -11,10 +9,11 @@ describe('events', () => { describe('has-input-value-changed event', () => { let clearButton, hasInputValueChangedSpy, valueChangedSpy; - beforeEach(() => { + beforeEach(async () => { hasInputValueChangedSpy = sinon.spy(); valueChangedSpy = sinon.spy(); timePicker = fixtureSync(''); + await nextRender(); clearButton = timePicker.shadowRoot.querySelector('[part=clear-button]'); timePicker.addEventListener('has-input-value-changed', hasInputValueChangedSpy); timePicker.addEventListener('value-changed', valueChangedSpy); diff --git a/packages/time-picker/test/keyboard-navigation-lit.test.js b/packages/time-picker/test/keyboard-navigation-lit.test.js new file mode 100644 index 0000000000..4bfc38ce0c --- /dev/null +++ b/packages/time-picker/test/keyboard-navigation-lit.test.js @@ -0,0 +1,2 @@ +import '../src/vaadin-lit-time-picker.js'; +import './keyboard-navigation.common.js'; diff --git a/packages/time-picker/test/keyboard-navigation-polymer.test.js b/packages/time-picker/test/keyboard-navigation-polymer.test.js new file mode 100644 index 0000000000..039cd310ea --- /dev/null +++ b/packages/time-picker/test/keyboard-navigation-polymer.test.js @@ -0,0 +1,2 @@ +import '../src/vaadin-time-picker.js'; +import './keyboard-navigation.common.js'; diff --git a/packages/time-picker/test/keyboard-navigation.test.js b/packages/time-picker/test/keyboard-navigation.common.js similarity index 96% rename from packages/time-picker/test/keyboard-navigation.test.js rename to packages/time-picker/test/keyboard-navigation.common.js index ba76966286..d52b05d3cd 100644 --- a/packages/time-picker/test/keyboard-navigation.test.js +++ b/packages/time-picker/test/keyboard-navigation.common.js @@ -1,14 +1,13 @@ import { expect } from '@vaadin/chai-plugins'; -import { arrowDown, arrowUp, fixtureSync } from '@vaadin/testing-helpers'; +import { arrowDown, arrowUp, fixtureSync, nextRender } from '@vaadin/testing-helpers'; import sinon from 'sinon'; -import './not-animated-styles.js'; -import '../vaadin-time-picker.js'; describe('keyboard navigation', () => { let timePicker, comboBox, inputElement; - beforeEach(() => { + beforeEach(async () => { timePicker = fixtureSync(``); + await nextRender(); comboBox = timePicker.$.comboBox; inputElement = timePicker.inputElement; }); @@ -219,7 +218,7 @@ describe('keyboard navigation', () => { it('should not open the overlay on arrow up', () => { timePicker.step = 0.5; arrowUp(inputElement); - expect(document.querySelector('vaadin-combo-box-overlay')).not.to.be.ok; + expect(document.querySelector('vaadin-time-picker-overlay')).not.to.be.ok; }); }); }); diff --git a/packages/time-picker/test/time-picker-lit.test.js b/packages/time-picker/test/time-picker-lit.test.js new file mode 100644 index 0000000000..e1162380ef --- /dev/null +++ b/packages/time-picker/test/time-picker-lit.test.js @@ -0,0 +1,2 @@ +import '../src/vaadin-lit-time-picker.js'; +import './time-picker.common.js'; diff --git a/packages/time-picker/test/time-picker-polymer.test.js b/packages/time-picker/test/time-picker-polymer.test.js new file mode 100644 index 0000000000..15f104887f --- /dev/null +++ b/packages/time-picker/test/time-picker-polymer.test.js @@ -0,0 +1,2 @@ +import '../src/vaadin-time-picker.js'; +import './time-picker.common.js'; diff --git a/packages/time-picker/test/time-picker.test.js b/packages/time-picker/test/time-picker.common.js similarity index 97% rename from packages/time-picker/test/time-picker.test.js rename to packages/time-picker/test/time-picker.common.js index fde2be6ef4..ad6b6b47cc 100644 --- a/packages/time-picker/test/time-picker.test.js +++ b/packages/time-picker/test/time-picker.common.js @@ -1,16 +1,15 @@ import { expect } from '@vaadin/chai-plugins'; -import { enter, fixtureSync, nextFrame } from '@vaadin/testing-helpers'; +import { enter, fixtureSync, nextFrame, nextRender } from '@vaadin/testing-helpers'; import sinon from 'sinon'; -import './not-animated-styles.js'; -import '../vaadin-time-picker.js'; import { isTouch } from '@vaadin/component-base/src/browser-utils.js'; import { setInputValue } from './helpers.js'; describe('time-picker', () => { let timePicker, comboBox, inputElement; - beforeEach(() => { + beforeEach(async () => { timePicker = fixtureSync(``); + await nextRender(); comboBox = timePicker.$.comboBox; inputElement = timePicker.inputElement; }); @@ -174,16 +173,19 @@ describe('time-picker', () => { }); describe('properties and attributes', () => { - it('should propagate required property to input', () => { + it('should propagate required property to input', async () => { timePicker.required = true; + await nextFrame(); expect(inputElement.required).to.be.true; timePicker.required = false; + await nextFrame(); expect(inputElement.required).to.be.false; }); - it('should reflect readonly property to attribute', () => { + it('should reflect readonly property to attribute', async () => { timePicker.readonly = true; + await nextFrame(); expect(timePicker.hasAttribute('readonly')).to.be.true; }); }); @@ -191,9 +193,10 @@ describe('time-picker', () => { describe('clear button', () => { let clearButton; - beforeEach(() => { + beforeEach(async () => { clearButton = timePicker.$.clearButton; timePicker.clearButtonVisible = true; + await nextFrame(); }); it('should not show clear button when disabled', () => { @@ -221,10 +224,11 @@ describe('time-picker', () => { expect(event.defaultPrevented).to.be.true; }); - it('should propagate clear button to the internal combo-box', () => { + it('should propagate clear button to the internal combo-box', async () => { expect(comboBox.clearButtonVisible).to.be.true; timePicker.clearButtonVisible = false; + await nextFrame(); expect(comboBox.clearButtonVisible).to.be.false; }); }); diff --git a/packages/time-picker/test/validation-lit.test.js b/packages/time-picker/test/validation-lit.test.js new file mode 100644 index 0000000000..a169eaef8f --- /dev/null +++ b/packages/time-picker/test/validation-lit.test.js @@ -0,0 +1,2 @@ +import '../src/vaadin-lit-time-picker.js'; +import './validation.common.js'; diff --git a/packages/time-picker/test/validation-polymer.test.js b/packages/time-picker/test/validation-polymer.test.js new file mode 100644 index 0000000000..23e7453e64 --- /dev/null +++ b/packages/time-picker/test/validation-polymer.test.js @@ -0,0 +1,2 @@ +import '../src/vaadin-time-picker.js'; +import './validation.common.js'; diff --git a/packages/time-picker/test/validation.test.js b/packages/time-picker/test/validation.common.js similarity index 92% rename from packages/time-picker/test/validation.test.js rename to packages/time-picker/test/validation.common.js index ff657d4698..c8d65277fa 100644 --- a/packages/time-picker/test/validation.test.js +++ b/packages/time-picker/test/validation.common.js @@ -1,10 +1,9 @@ import { expect } from '@vaadin/chai-plugins'; -import { enter, fixtureSync, nextRender } from '@vaadin/testing-helpers'; +import { enter, fixtureSync, nextFrame, nextRender } from '@vaadin/testing-helpers'; import sinon from 'sinon'; -import { TimePicker } from '../src/vaadin-time-picker.js'; import { setInputValue } from './helpers.js'; -class TimePicker20Element extends TimePicker { +class TimePicker20Element extends customElements.get('vaadin-time-picker') { checkValidity() { return this.value === '20:00'; } @@ -70,8 +69,9 @@ describe('validation', () => { describe('basic', () => { let validateSpy, changeSpy, valueChangedSpy; - beforeEach(() => { + beforeEach(async () => { timePicker = fixtureSync(``); + await nextRender(); validateSpy = sinon.spy(timePicker, 'validate'); changeSpy = sinon.spy(); timePicker.addEventListener('change', changeSpy); @@ -118,10 +118,11 @@ describe('validation', () => { expect(event.detail.valid).to.be.true; }); - it('should fire a validated event on validation failure', () => { + it('should fire a validated event on validation failure', async () => { const validatedSpy = sinon.spy(); timePicker.addEventListener('validated', validatedSpy); timePicker.required = true; + await nextFrame(); timePicker.validate(); expect(validatedSpy.calledOnce).to.be.true; @@ -131,8 +132,9 @@ describe('validation', () => { }); describe('input value', () => { - beforeEach(() => { + beforeEach(async () => { timePicker = fixtureSync(``); + await nextRender(); }); it('should be valid when committing a valid time', () => { @@ -156,8 +158,9 @@ describe('validation', () => { }); describe('required', () => { - beforeEach(() => { + beforeEach(async () => { timePicker = fixtureSync(``); + await nextRender(); }); it('should fail validation without value', () => { @@ -171,8 +174,9 @@ describe('validation', () => { }); describe('min', () => { - beforeEach(() => { + beforeEach(async () => { timePicker = fixtureSync(``); + await nextRender(); }); it('should pass validation without value', () => { @@ -196,8 +200,9 @@ describe('validation', () => { }); describe('max', () => { - beforeEach(() => { + beforeEach(async () => { timePicker = fixtureSync(``); + await nextRender(); }); it('should pass validation without value', () => { @@ -221,8 +226,9 @@ describe('validation', () => { }); describe('pattern', () => { - beforeEach(() => { + beforeEach(async () => { timePicker = fixtureSync(``); + await nextRender(); }); it('should pass validation without value', () => { @@ -241,8 +247,9 @@ describe('validation', () => { }); describe('custom validator', () => { - beforeEach(() => { + beforeEach(async () => { timePicker = fixtureSync(``); + await nextRender(); }); it('should validate correctly with custom validator', () => { diff --git a/packages/time-picker/test/value-commit-lit.test.js b/packages/time-picker/test/value-commit-lit.test.js new file mode 100644 index 0000000000..a6c3a78fff --- /dev/null +++ b/packages/time-picker/test/value-commit-lit.test.js @@ -0,0 +1,2 @@ +import '../src/vaadin-lit-time-picker.js'; +import './value-commit.common.js'; diff --git a/packages/time-picker/test/value-commit-polymer.test.js b/packages/time-picker/test/value-commit-polymer.test.js new file mode 100644 index 0000000000..a51e05c312 --- /dev/null +++ b/packages/time-picker/test/value-commit-polymer.test.js @@ -0,0 +1,2 @@ +import '../src/vaadin-time-picker.js'; +import './value-commit.common.js'; diff --git a/packages/time-picker/test/value-commit.test.js b/packages/time-picker/test/value-commit.common.js similarity index 99% rename from packages/time-picker/test/value-commit.test.js rename to packages/time-picker/test/value-commit.common.js index 106c8add7b..7480f5180b 100644 --- a/packages/time-picker/test/value-commit.test.js +++ b/packages/time-picker/test/value-commit.common.js @@ -2,7 +2,6 @@ import { expect } from '@vaadin/chai-plugins'; import { fixtureSync, nextRender, outsideClick } from '@vaadin/testing-helpers'; import { sendKeys } from '@web/test-runner-commands'; import sinon from 'sinon'; -import '../src/vaadin-time-picker.js'; import { getAllItems } from './helpers.js'; describe('value commit', () => { diff --git a/packages/time-picker/theme/lumo/vaadin-lit-time-picker.js b/packages/time-picker/theme/lumo/vaadin-lit-time-picker.js new file mode 100644 index 0000000000..c3b4dbb5b4 --- /dev/null +++ b/packages/time-picker/theme/lumo/vaadin-lit-time-picker.js @@ -0,0 +1,7 @@ +/** + * @license + * Copyright (c) 2018 - 2024 Vaadin Ltd. + * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ + */ +import './vaadin-time-picker-styles.js'; +import '../../src/vaadin-lit-time-picker.js'; diff --git a/packages/time-picker/theme/material/vaadin-lit-time-picker.js b/packages/time-picker/theme/material/vaadin-lit-time-picker.js new file mode 100644 index 0000000000..c3b4dbb5b4 --- /dev/null +++ b/packages/time-picker/theme/material/vaadin-lit-time-picker.js @@ -0,0 +1,7 @@ +/** + * @license + * Copyright (c) 2018 - 2024 Vaadin Ltd. + * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ + */ +import './vaadin-time-picker-styles.js'; +import '../../src/vaadin-lit-time-picker.js'; diff --git a/packages/time-picker/vaadin-lit-time-picker.d.ts b/packages/time-picker/vaadin-lit-time-picker.d.ts new file mode 100644 index 0000000000..44fd694c6c --- /dev/null +++ b/packages/time-picker/vaadin-lit-time-picker.d.ts @@ -0,0 +1 @@ +export * from './src/vaadin-time-picker.js'; diff --git a/packages/time-picker/vaadin-lit-time-picker.js b/packages/time-picker/vaadin-lit-time-picker.js new file mode 100644 index 0000000000..85c80e7628 --- /dev/null +++ b/packages/time-picker/vaadin-lit-time-picker.js @@ -0,0 +1,2 @@ +import './theme/lumo/vaadin-lit-time-picker.js'; +export * from './src/vaadin-lit-time-picker.js';