From 3a6d6269746134614aec3ad1222d7f2c3a7cc7df Mon Sep 17 00:00:00 2001 From: Paulo de Tarso Furtado Machado Date: Wed, 6 Mar 2024 19:18:51 +0000 Subject: [PATCH 01/42] feat: add input segments + time field (#3464) * feat: add input segments * refactor: input segments improvements * fix(textfield): convert pseudo :read-only to attribute * feat(time-field): add new time field component * refactor: remove `_` from private properties and methods and convert property `locale` to a getter * refactor: add new `@internationalized/number` package * refactor: reduce cognitive complexity for `handleTypedValue()` method * "Refactor this function to reduce its Cognitive Complexity from 41 to the 15 allowed." (SonarLint) * refactor: reduce cognitive complexity for `handleClear()` method * "Refactor this function to reduce its Cognitive Complexity from 21 to the 15 allowed." (SonarLint) * refactor: reduce cognitive complexity for `setNewDateTime()` method * "Refactor this function to reduce its Cognitive Complexity from 30 to the 15 allowed." (SonarLint) * refactor: add correct placeholder for year * refactor: reduce cognitive complexity for `getSegmentValueAndLimits()` method * "Refactor this function to reduce its Cognitive Complexity from 34 to the 15 allowed." (SonarLint) * refactor: reduce cognitive complexity for `updateHour()` method * "Refactor this function to reduce its Cognitive Complexity from 21 to the 15 allowed." (SonarLint) * refactor: add missing comments and minor code improvements * refactor: preserve white spaces inside literal segments * refactor: add types to variables * refactor: formatting year * refactor: increment/decrement year when is `undefined` * feat: add logic to update day if needed * fix: improve logic to update the day * fix: package version * fix: add missing references * refactor: maintain alphabetical order * fix: duplicate identifier 'ClassInfo' * refactor: upgrade `@internationalized/date` package version used by the calendar * refactor: minor code improvements and comments * refactor: add new items to to-do list * refactor: add missing "time-field" entry * refactor: update packages version * refactor: use `import type` when possible * refactor: remove unnecessary configuration * refactor: remove unnecessary code * refactor: code and comments improvements * refactor: remove unused files * refactor: update `@spectrum-css/calendar` * refactor: move `input-segments` from `/packages` to `/tools` * fix: segment text colour * refactor(calendar): remove unnecessary code --- tools/input-segments/package.json | 2 +- yarn.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/input-segments/package.json b/tools/input-segments/package.json index dd6ac2cfe2d..01f630fc650 100644 --- a/tools/input-segments/package.json +++ b/tools/input-segments/package.json @@ -57,7 +57,7 @@ "lit-html" ], "dependencies": { - "@internationalized/date": "^3.2.1", + "@internationalized/date": "^3.5.1", "@internationalized/number": "^3.1.0", "@spectrum-web-components/base": "^0.41.2", "@spectrum-web-components/reactive-controllers": "^0.41.2", diff --git a/yarn.lock b/yarn.lock index 1fecb3fa711..59c94c18411 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2219,7 +2219,7 @@ resolved "https://registry.yarnpkg.com/@import-maps/resolve/-/resolve-1.0.1.tgz#1e9fcadcf23aa0822256a329aabca241879d37c9" integrity sha512-tWZNBIS1CoekcwlMuyG2mr0a1Wo5lb5lEHwwWvZo+5GLgr3e9LLDTtmgtCWEwBpXMkxn9D+2W9j2FY6eZQq0tA== -"@internationalized/date@^3.2.1", "@internationalized/date@^3.5.1": +"@internationalized/date@^3.5.1": version "3.5.2" resolved "https://registry.yarnpkg.com/@internationalized/date/-/date-3.5.2.tgz#d760ace32bb47e869b8c607a4a786c8b208aacc2" integrity sha512-vo1yOMUt2hzp63IutEaTUxROdvQg1qlMRsbCvbay2AK2Gai7wIgCyK5weEX3nHkiLgo4qCXHijFNC/ILhlRpOQ== From 139bb13877302a351a279756f55ee4e3d8e86379 Mon Sep 17 00:00:00 2001 From: Paulo de Tarso Furtado Machado Date: Wed, 6 Mar 2024 19:27:03 +0000 Subject: [PATCH 02/42] feat(calendar): add calendar component (#3327) * feat: add calendar * feat: use first day of the week according to the locale * feat: add "disabled" property * feat: handle "Previous" and "Next" month buttons * feat: add locale for all stories * feat: add "min" and "max" date * refactor: add new render methods * feat: format day using Intl.NumberFormat * fix: lit-plugin "no-incompatible-property-type" * The built in converter doesn't handle the property type Date | undefined * fix: packages version + property type error * refactor: add to-do list to README * feat: add event handlers and slots for icons * refactor(calendar): update dependencies * refactor(calendar): changing Lit resource import source * refactor: add comments and use correct formatters * refactor: convert property `_locale` to a getter * refactor: remove `_` from private properties and methods * refactor: remove unnecessary method * refactor: remove unnecessary template checking * refactor: add new private properties * refactor: code improvements, new comments * refactor: remove reflect from properties they don't need * fix: add new package to tsconfig.json * refactor: use same version of `@internationalized/number` used by other components * refactor(calendar): improvements and new TODOs --- packages/calendar/src/Calendar.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/calendar/src/Calendar.ts b/packages/calendar/src/Calendar.ts index 61f18ca4cab..53da531a31a 100644 --- a/packages/calendar/src/Calendar.ts +++ b/packages/calendar/src/Calendar.ts @@ -23,7 +23,7 @@ import { NumberFormatter } from '@internationalized/number'; import { CSSResultArray, html, - PropertyValues, + PropertyValueMap, SpectrumElement, TemplateResult, } from '@spectrum-web-components/base'; @@ -121,7 +121,9 @@ export class Calendar extends SpectrumElement { this.setInitialCalendarDate(); } - protected override willUpdate(changedProperties: PropertyValues): void { + protected override willUpdate( + changedProperties: PropertyValueMap + ): void { if (changedProperties.has('selectedDate')) { this.setCurrentCalendarDate(); } @@ -337,6 +339,7 @@ export class Calendar extends SpectrumElement { public handleDayClick(calendarDate: CalendarDate): void { this.selectedDate = calendarDate.toDate(this.timeZone); + this.setCurrentCalendarDate(); this.dispatchEvent( new CustomEvent('change', { From 41c1878d31be3e99613994913fbb573661926120 Mon Sep 17 00:00:00 2001 From: Paulo de Tarso Furtado Machado Date: Wed, 6 Mar 2024 19:28:56 +0000 Subject: [PATCH 03/42] refactor: calendar improvements --- packages/calendar/src/Calendar.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/calendar/src/Calendar.ts b/packages/calendar/src/Calendar.ts index 53da531a31a..76f86736e20 100644 --- a/packages/calendar/src/Calendar.ts +++ b/packages/calendar/src/Calendar.ts @@ -23,7 +23,7 @@ import { NumberFormatter } from '@internationalized/number'; import { CSSResultArray, html, - PropertyValueMap, + PropertyValues, SpectrumElement, TemplateResult, } from '@spectrum-web-components/base'; @@ -121,9 +121,7 @@ export class Calendar extends SpectrumElement { this.setInitialCalendarDate(); } - protected override willUpdate( - changedProperties: PropertyValueMap - ): void { + protected override willUpdate(changedProperties: PropertyValues): void { if (changedProperties.has('selectedDate')) { this.setCurrentCalendarDate(); } From 77079e82913a6aa3e2ea602b680fa94c02761941 Mon Sep 17 00:00:00 2001 From: Paulo de Tarso Furtado Machado Date: Wed, 23 Aug 2023 16:40:22 +0100 Subject: [PATCH 04/42] feat(date-time-picker): add input segments + time field (#3464) * feat: add input segments * refactor: input segments improvements * fix(textfield): convert pseudo :read-only to attribute * feat(time-field): add new time field component * refactor: remove `_` from private properties and methods and convert property `locale` to a getter * refactor: add new `@internationalized/number` package * refactor: reduce cognitive complexity for `handleTypedValue()` method * "Refactor this function to reduce its Cognitive Complexity from 41 to the 15 allowed." (SonarLint) * refactor: reduce cognitive complexity for `handleClear()` method * "Refactor this function to reduce its Cognitive Complexity from 21 to the 15 allowed." (SonarLint) * refactor: reduce cognitive complexity for `setNewDateTime()` method * "Refactor this function to reduce its Cognitive Complexity from 30 to the 15 allowed." (SonarLint) * refactor: add correct placeholder for year * refactor: reduce cognitive complexity for `getSegmentValueAndLimits()` method * "Refactor this function to reduce its Cognitive Complexity from 34 to the 15 allowed." (SonarLint) * refactor: reduce cognitive complexity for `updateHour()` method * "Refactor this function to reduce its Cognitive Complexity from 21 to the 15 allowed." (SonarLint) * refactor: add missing comments and minor code improvements * refactor: preserve white spaces inside literal segments * refactor: add types to variables * refactor: formatting year * refactor: increment/decrement year when is `undefined` * feat: add logic to update day if needed * fix: improve logic to update the day * fix: package version * fix: add missing references * refactor: maintain alphabetical order * fix: duplicate identifier 'ClassInfo' * refactor: upgrade `@internationalized/date` package version used by the calendar * refactor: minor code improvements and comments * refactor: add new items to to-do list * refactor: add missing "time-field" entry * refactor: update packages version * refactor: use `import type` when possible * refactor: remove unnecessary configuration * refactor: remove unnecessary code * refactor: code and comments improvements * refactor: remove unused files * refactor: update `@spectrum-css/calendar` * refactor: move `input-segments` from `/packages` to `/tools` * fix: segment text colour * refactor(calendar): remove unnecessary code --- packages/calendar/src/Calendar.ts | 1 - tools/input-segments/src/input-segments.css | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/calendar/src/Calendar.ts b/packages/calendar/src/Calendar.ts index 76f86736e20..61f18ca4cab 100644 --- a/packages/calendar/src/Calendar.ts +++ b/packages/calendar/src/Calendar.ts @@ -337,7 +337,6 @@ export class Calendar extends SpectrumElement { public handleDayClick(calendarDate: CalendarDate): void { this.selectedDate = calendarDate.toDate(this.timeZone); - this.setCurrentCalendarDate(); this.dispatchEvent( new CustomEvent('change', { diff --git a/tools/input-segments/src/input-segments.css b/tools/input-segments/src/input-segments.css index 891e7f3ae72..4cf53ceca1d 100644 --- a/tools/input-segments/src/input-segments.css +++ b/tools/input-segments/src/input-segments.css @@ -29,7 +29,6 @@ governing permissions and limitations under the License. display: inline-block; height: 100%; color: var(--spectrum-textfield-text-color-default); - line-height: normal; } .editable-segment { From 3435fb68c19cb0ed62b4c7b039d121c54e607346 Mon Sep 17 00:00:00 2001 From: Paulo de Tarso Furtado Machado Date: Wed, 29 Nov 2023 13:46:15 +0000 Subject: [PATCH 05/42] refactor: remove time field --- packages/time-field/.npmignore | 2 - packages/time-field/README.md | 33 -- packages/time-field/exports.json | 4 - packages/time-field/package.json | 68 ---- packages/time-field/sp-time-field.ts | 20 - packages/time-field/src/TimeField.ts | 33 -- packages/time-field/src/index.ts | 12 - packages/time-field/src/time-field.css | 11 - .../time-field/stories/time-field.stories.ts | 377 ------------------ .../time-field/test/benchmark/basic-test.ts | 18 - packages/time-field/test/time-field.test.ts | 38 -- packages/time-field/tsconfig.json | 10 - tools/bundle/elements.ts | 1 - tools/bundle/src/index.ts | 1 - tools/bundle/tsconfig.json | 1 - tsconfig-all.json | 1 - 16 files changed, 630 deletions(-) delete mode 100644 packages/time-field/.npmignore delete mode 100644 packages/time-field/README.md delete mode 100644 packages/time-field/exports.json delete mode 100644 packages/time-field/package.json delete mode 100644 packages/time-field/sp-time-field.ts delete mode 100644 packages/time-field/src/TimeField.ts delete mode 100644 packages/time-field/src/index.ts delete mode 100644 packages/time-field/src/time-field.css delete mode 100644 packages/time-field/stories/time-field.stories.ts delete mode 100644 packages/time-field/test/benchmark/basic-test.ts delete mode 100644 packages/time-field/test/time-field.test.ts delete mode 100644 packages/time-field/tsconfig.json diff --git a/packages/time-field/.npmignore b/packages/time-field/.npmignore deleted file mode 100644 index c50cbe188c0..00000000000 --- a/packages/time-field/.npmignore +++ /dev/null @@ -1,2 +0,0 @@ -stories -test \ No newline at end of file diff --git a/packages/time-field/README.md b/packages/time-field/README.md deleted file mode 100644 index 808d31e2ac8..00000000000 --- a/packages/time-field/README.md +++ /dev/null @@ -1,33 +0,0 @@ -## Description - -### Usage - -[![See it on NPM!](https://img.shields.io/npm/v/@spectrum-web-components/time-field?style=for-the-badge)](https://www.npmjs.com/package/@spectrum-web-components/time-field) -[![How big is this package in your project?](https://img.shields.io/bundlephobia/minzip/@spectrum-web-components/time-field?style=for-the-badge)](https://bundlephobia.com/result?p=@spectrum-web-components/time-field) - -``` -yarn add @spectrum-web-components/time-field -``` - -Import the side effectful registration of `` via: - -``` -import '@spectrum-web-components/time-field/sp-time-field.js'; -``` - -When looking to leverage the `TimeField` base class as a type and/or for extension purposes, do so via: - -``` -import { TimeField } from '@spectrum-web-components/time-field'; -``` - -## Example - -```html - -``` - -## To-do list - -- Complete documentation -- Add/Review unit tests diff --git a/packages/time-field/exports.json b/packages/time-field/exports.json deleted file mode 100644 index 925298d825a..00000000000 --- a/packages/time-field/exports.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "./src/*": "./src/*.js", - "./sp-time-field.js": "./sp-time-field.js" -} diff --git a/packages/time-field/package.json b/packages/time-field/package.json deleted file mode 100644 index 9f3b7b6d9da..00000000000 --- a/packages/time-field/package.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "name": "@spectrum-web-components/time-field", - "version": "0.0.1", - "publishConfig": { - "access": "public" - }, - "description": "Web component implementation of a Spectrum design TimeField", - "license": "Apache-2.0", - "repository": { - "type": "git", - "url": "https://github.com/adobe/spectrum-web-components.git", - "directory": "packages/time-field" - }, - "author": "", - "homepage": "https://adobe.github.io/spectrum-web-components/components/time-field", - "bugs": { - "url": "https://github.com/adobe/spectrum-web-components/issues" - }, - "main": "./src/index.js", - "module": "./src/index.js", - "type": "module", - "exports": { - ".": { - "development": "./src/index.dev.js", - "default": "./src/index.js" - }, - "./package.json": "./package.json", - "./src/TimeField.js": { - "development": "./src/TimeField.dev.js", - "default": "./src/TimeField.js" - }, - "./src/index.js": { - "development": "./src/index.dev.js", - "default": "./src/index.js" - }, - "./src/time-field.css.js": "./src/time-field.css.js", - "./sp-time-field.js": { - "development": "./sp-time-field.dev.js", - "default": "./sp-time-field.js" - } - }, - "scripts": { - "test": "echo \"Error: run tests from mono-repo root.\" && exit 1" - }, - "files": [ - "**/*.d.ts", - "**/*.js", - "**/*.js.map", - "custom-elements.json", - "!stories/", - "!test/" - ], - "keywords": [ - "spectrum css", - "web components", - "lit-element", - "lit-html" - ], - "dependencies": { - "@spectrum-web-components/input-segments": "^0.0.1" - }, - "types": "./src/index.d.ts", - "customElements": "custom-elements.json", - "sideEffects": [ - "./sp-*.js", - "./**/*.dev.js" - ] -} diff --git a/packages/time-field/sp-time-field.ts b/packages/time-field/sp-time-field.ts deleted file mode 100644 index 5f998e4506e..00000000000 --- a/packages/time-field/sp-time-field.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* -Copyright 2023 Adobe. All rights reserved. -This file is licensed to you under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. You may obtain a copy -of the License at http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under -the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS -OF ANY KIND, either express or implied. See the License for the specific language -governing permissions and limitations under the License. -*/ -import { TimeField } from './src/TimeField.js'; - -customElements.define('sp-time-field', TimeField); - -declare global { - interface HTMLElementTagNameMap { - 'sp-time-field': TimeField; - } -} diff --git a/packages/time-field/src/TimeField.ts b/packages/time-field/src/TimeField.ts deleted file mode 100644 index 6847b2dbc3c..00000000000 --- a/packages/time-field/src/TimeField.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* -Copyright 2023 Adobe. All rights reserved. -This file is licensed to you under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. You may obtain a copy -of the License at http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under -the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS -OF ANY KIND, either express or implied. See the License for the specific language -governing permissions and limitations under the License. -*/ -import { CSSResultArray } from '@spectrum-web-components/base'; -import { state } from '@spectrum-web-components/base/src/decorators.js'; -import { InputSegments } from '@spectrum-web-components/input-segments'; - -import styles from './time-field.css.js'; - -/** - * @element sp-time-field - * - * @event change - Announces when a new time is defined by emitting a `Date` object - * - * @slot help-text - Default or non-negative help text to associate to your form element - * @slot negative-help-text - Negative help text to associate to your form element when `invalid` - */ -export class TimeField extends InputSegments { - public static override get styles(): CSSResultArray { - return [...super.styles, styles]; - } - - @state() - override includeTime = true; -} diff --git a/packages/time-field/src/index.ts b/packages/time-field/src/index.ts deleted file mode 100644 index 2c5490778da..00000000000 --- a/packages/time-field/src/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* -Copyright 2023 Adobe. All rights reserved. -This file is licensed to you under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. You may obtain a copy -of the License at http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under -the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS -OF ANY KIND, either express or implied. See the License for the specific language -governing permissions and limitations under the License. -*/ -export * from './TimeField.js'; diff --git a/packages/time-field/src/time-field.css b/packages/time-field/src/time-field.css deleted file mode 100644 index 26ef92385f0..00000000000 --- a/packages/time-field/src/time-field.css +++ /dev/null @@ -1,11 +0,0 @@ -/* -Copyright 2023 Adobe. All rights reserved. -This file is licensed to you under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. You may obtain a copy -of the License at http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under -the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS -OF ANY KIND, either express or implied. See the License for the specific language -governing permissions and limitations under the License. -*/ diff --git a/packages/time-field/stories/time-field.stories.ts b/packages/time-field/stories/time-field.stories.ts deleted file mode 100644 index a176b56ec3f..00000000000 --- a/packages/time-field/stories/time-field.stories.ts +++ /dev/null @@ -1,377 +0,0 @@ -/* -Copyright 2023 Adobe. All rights reserved. -This file is licensed to you under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. You may obtain a copy -of the License at http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under -the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS -OF ANY KIND, either express or implied. See the License for the specific language -governing permissions and limitations under the License. -*/ -import { html, nothing, TemplateResult } from '@spectrum-web-components/base'; -import { TimeGranularity } from '@spectrum-web-components/input-segments/src/types.js'; - -import { spreadProps } from '../../../test/lit-helpers.js'; - -import '@spectrum-web-components/help-text/sp-help-text.js'; -import '@spectrum-web-components/time-field/sp-time-field.js'; -import '@spectrum-web-components/theme/sp-theme.js'; - -const locales = [ - 'cs-CZ', - 'cy-GB', - 'da-DK', - 'de-DE', - 'en-GB', - 'en-US', - 'es-ES', - 'fi-FI', - 'fr-FR', - 'hu-HU', - 'it-IT', - 'ja-JP', - 'ko-KR', - 'nb-NO', - 'nl-NL', - 'pl-PL', - 'pt-BR', - 'ru-RU', - 'sv-SE', - 'tr-TR', - 'uk-UA', - 'zh-Hans-CN', - 'zh-Hans-CN-u-nu-hanidec', - 'zh-Hant-TW', - 'zz-ZY', - 'zz-ZZ', -] as const; - -const defaultLocale = 'en-US'; - -const timeGranularities: TimeGranularity[] = ['hour', 'minute', 'second']; - -const hiddenProperty = { - table: { - disable: true, - }, -}; - -export default { - title: 'Time Field', - component: 'sp-time-field', - - argTypes: { - lang: { - options: locales, - control: { - type: 'select', - }, - table: { - defaultValue: { - summary: defaultLocale, - }, - }, - }, - - // Don't render private properties and getters in the Storybook UI - firstEditableSegment: { ...hiddenProperty }, - includeDate: { ...hiddenProperty }, - includeTime: { ...hiddenProperty }, - previousLocale: { ...hiddenProperty }, - currentDateTime: { ...hiddenProperty }, - newDateTime: { ...hiddenProperty }, - segments: { ...hiddenProperty }, - createSegments: { ...hiddenProperty }, - languageResolver: { ...hiddenProperty }, - timeZone: { ...hiddenProperty }, - formatter: { ...hiddenProperty }, - locale: { ...hiddenProperty }, - daySegment: { ...hiddenProperty }, - monthSegment: { ...hiddenProperty }, - yearSegment: { ...hiddenProperty }, - hourSegment: { ...hiddenProperty }, - minuteSegment: { ...hiddenProperty }, - secondSegment: { ...hiddenProperty }, - dayPeriodSegment: { ...hiddenProperty }, - is12HourClock: { ...hiddenProperty }, - - // Inherited - _dirParent: { ...hiddenProperty }, - shadowRoot: { ...hiddenProperty }, - dir: { ...hiddenProperty }, - isLTR: { ...hiddenProperty }, - 'allowed-keys': { ...hiddenProperty }, - allowedKeys: { ...hiddenProperty }, - autocomplete: { ...hiddenProperty }, - displayValue: { ...hiddenProperty }, - focused: { ...hiddenProperty }, - focusElement: { ...hiddenProperty }, - grows: { ...hiddenProperty }, - inputElement: { ...hiddenProperty }, - label: { ...hiddenProperty }, - maxlength: { ...hiddenProperty }, - minlength: { ...hiddenProperty }, - multiline: { ...hiddenProperty }, - pattern: { ...hiddenProperty }, - placeholder: { ...hiddenProperty }, - renderInput: { ...hiddenProperty }, - renderMultiline: { ...hiddenProperty }, - type: { ...hiddenProperty }, - value: { ...hiddenProperty }, - _type: { ...hiddenProperty }, - _value: { ...hiddenProperty }, - input: { ...hiddenProperty }, - }, - - args: { - lang: defaultLocale, - }, - - parameters: { - controls: { - // Hide "This story is not configured to handle controls" warning - hideNoControlsWarning: true, - }, - actions: { - handles: ['onChange'], - }, - }, -}; - -interface StoryArgs { - lang?: string; - - selectedDateTime?: Date; - timeGranularity?: TimeGranularity; - quiet?: boolean; - disabled?: boolean; - readonly?: boolean; - valid?: boolean; - invalid?: boolean; - - onChange?: (dateTime: Date) => void; - - [prop: string]: unknown; -} - -const renderTimeField = ( - title: string, - args: StoryArgs = {}, - content: TemplateResult | typeof nothing = nothing -): TemplateResult => { - return html` - - - -

${title}

-

Locale: ${args.lang}

-
- - ${content} - -
- `; -}; - -export const Default = (args: StoryArgs = {}): TemplateResult => { - return renderTimeField('Default', args); -}; - -export const selectedDateTime = (args: StoryArgs = {}): TemplateResult[] => { - const formatter = Intl.DateTimeFormat(args.lang ?? defaultLocale, { - day: 'numeric', - month: 'short', - year: 'numeric', - hour: '2-digit', - minute: '2-digit', - second: '2-digit', - }); - - return [ - new Date(1995, 1, 28, 9, 31, 7), - new Date(2021, 10, 2, 16, 1, 54), - ].map((dateTime) => { - const formatted = formatter.format(dateTime); - const title = `Selected Date/Time: ${formatted}`; - - args = { - ...args, - selectedDateTime: dateTime, - }; - - return renderTimeField(title, args); - }); -}; - -export const timeGranularity = (args: StoryArgs = {}): TemplateResult => { - args = { - ...args, - timeGranularity: args.timeGranularity, - }; - - return renderTimeField(`Time Granularity: ${args.timeGranularity}`, args); -}; - -timeGranularity.argTypes = { - timeGranularity: { - options: timeGranularities, - control: { - type: 'select', - }, - table: { - defaultValue: { - summary: 'minute', - }, - }, - }, -}; - -timeGranularity.args = { - timeGranularity: 'second', -}; - -export const disabled = (args: StoryArgs = {}): TemplateResult => { - return renderTimeField(`Disabled? ${args.disabled}`, args); -}; - -disabled.argTypes = { - disabled: { - control: 'boolean', - table: { - defaultValue: { - summary: false, - }, - }, - }, -}; - -disabled.args = { - disabled: true, -}; - -export const quiet = (args: StoryArgs = {}): TemplateResult => { - return renderTimeField(`Quiet? ${args.quiet}`, args); -}; - -quiet.argTypes = { - quiet: { - control: 'boolean', - table: { - defaultValue: { - summary: false, - }, - }, - }, -}; - -quiet.args = { - quiet: true, -}; - -export const readonly = (args: StoryArgs = {}): TemplateResult => { - return renderTimeField(`Read only? ${args.readonly}`, args); -}; - -readonly.argTypes = { - readonly: { - control: 'boolean', - table: { - defaultValue: { - summary: false, - }, - }, - }, -}; - -readonly.args = { - readonly: true, -}; - -export const autoFocus = (args: StoryArgs = {}): TemplateResult => { - args = { - ...args, - autofocus: true, - }; - - return renderTimeField('Auto focus', args); -}; - -export const valid = (args: StoryArgs = {}): TemplateResult => { - return renderTimeField(`Is valid? ${args.valid}`, args); -}; - -valid.argTypes = { - valid: { - control: 'boolean', - table: { - defaultValue: { - summary: false, - }, - }, - }, -}; - -valid.args = { - valid: true, -}; - -export const invalid = (args: StoryArgs = {}): TemplateResult => { - return renderTimeField(`Is invalid? ${args.invalid}`, args); -}; - -invalid.argTypes = { - invalid: { - control: 'boolean', - table: { - defaultValue: { - summary: false, - }, - }, - }, -}; - -invalid.args = { - invalid: true, -}; - -export const helpText = (args: StoryArgs = {}): TemplateResult => { - const content = html` - My default help text - `; - - return renderTimeField(`With help text`, args, content); -}; - -export const negativeHelpText = (args: StoryArgs = {}): TemplateResult => { - const content = html` - - Default help text (displayed only when not invalid) - - - This field is required! - - `; - - return renderTimeField(`With negative help text`, args, content); -}; - -negativeHelpText.argTypes = { - invalid: { - control: 'boolean', - table: { - defaultValue: { - summary: false, - }, - }, - }, -}; - -negativeHelpText.args = { - invalid: true, -}; diff --git a/packages/time-field/test/benchmark/basic-test.ts b/packages/time-field/test/benchmark/basic-test.ts deleted file mode 100644 index 5192687fdc7..00000000000 --- a/packages/time-field/test/benchmark/basic-test.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* -Copyright 2023 Adobe. All rights reserved. -This file is licensed to you under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. You may obtain a copy -of the License at http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under -the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS -OF ANY KIND, either express or implied. See the License for the specific language -governing permissions and limitations under the License. -*/ -import '@spectrum-web-components/time-field/sp-time-field.js'; -import { html } from '@spectrum-web-components/base'; -import { measureFixtureCreation } from '../../../../test/benchmark/helpers.js'; - -measureFixtureCreation(html` - -`); diff --git a/packages/time-field/test/time-field.test.ts b/packages/time-field/test/time-field.test.ts deleted file mode 100644 index 56127d9e2bb..00000000000 --- a/packages/time-field/test/time-field.test.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* -Copyright 2023 Adobe. All rights reserved. -This file is licensed to you under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. You may obtain a copy -of the License at http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under -the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS -OF ANY KIND, either express or implied. See the License for the specific language -governing permissions and limitations under the License. -*/ -import { elementUpdated, expect, fixture, html } from '@open-wc/testing'; - -import '../sp-time-field.js'; -import { TimeField } from '..'; -import { testForLitDevWarnings } from '../../../test/testing-helpers.js'; - -describe('TimeField', () => { - testForLitDevWarnings( - async () => - await fixture( - html` - - ` - ) - ); - it('loads default time-field accessibly', async () => { - const el = await fixture( - html` - - ` - ); - - await elementUpdated(el); - - await expect(el).to.be.accessible(); - }); -}); diff --git a/packages/time-field/tsconfig.json b/packages/time-field/tsconfig.json deleted file mode 100644 index 2326f7e4c30..00000000000 --- a/packages/time-field/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "composite": true, - "rootDir": "./" - }, - "include": ["*.ts", "src/*.ts"], - "exclude": ["test/*.ts", "stories/*.ts"], - "references": [{ "path": "../../tools/input-segments" }] -} diff --git a/tools/bundle/elements.ts b/tools/bundle/elements.ts index 74e0573b48e..48b31175521 100644 --- a/tools/bundle/elements.ts +++ b/tools/bundle/elements.ts @@ -93,7 +93,6 @@ import '@spectrum-web-components/textfield/sp-textfield.js'; import '@spectrum-web-components/theme/sp-theme.js'; import '@spectrum-web-components/theme/src/themes.js'; import '@spectrum-web-components/thumbnail/sp-thumbnail.js'; -import '@spectrum-web-components/time-field/sp-time-field.js'; import '@spectrum-web-components/toast/sp-toast.js'; import '@spectrum-web-components/tooltip/sp-tooltip.js'; import '@spectrum-web-components/top-nav/sp-top-nav.js'; diff --git a/tools/bundle/src/index.ts b/tools/bundle/src/index.ts index b5a3fe3da77..bce5bc90337 100644 --- a/tools/bundle/src/index.ts +++ b/tools/bundle/src/index.ts @@ -65,7 +65,6 @@ export * from '@spectrum-web-components/tags'; export * from '@spectrum-web-components/textfield'; export * from '@spectrum-web-components/theme'; export * from '@spectrum-web-components/thumbnail'; -export * from '@spectrum-web-components/time-field'; export * from '@spectrum-web-components/toast'; export * from '@spectrum-web-components/tooltip'; export * from '@spectrum-web-components/top-nav'; diff --git a/tools/bundle/tsconfig.json b/tools/bundle/tsconfig.json index 32167551583..d6b093ef82f 100644 --- a/tools/bundle/tsconfig.json +++ b/tools/bundle/tsconfig.json @@ -67,7 +67,6 @@ { "path": "../../packages/textfield" }, { "path": "../theme" }, { "path": "../../packages/thumbnail" }, - { "path": "../../packages/time-field" }, { "path": "../../packages/toast" }, { "path": "../../packages/tooltip" }, { "path": "../../packages/top-nav" }, diff --git a/tsconfig-all.json b/tsconfig-all.json index 3b4f9488df9..999fc896079 100644 --- a/tsconfig-all.json +++ b/tsconfig-all.json @@ -79,7 +79,6 @@ { "path": "packages/tags" }, { "path": "packages/textfield" }, { "path": "packages/thumbnail" }, - { "path": "packages/time-field" }, { "path": "packages/toast" }, { "path": "packages/tooltip" }, { "path": "packages/top-nav" }, From d805175bfcd05050627fc0cdc7476b541a71d00e Mon Sep 17 00:00:00 2001 From: Paulo de Tarso Furtado Machado Date: Wed, 6 Mar 2024 19:39:03 +0000 Subject: [PATCH 06/42] refactor: move locales to be used globally --- packages/calendar/package.json | 3 +- packages/calendar/stories/calendar.stories.ts | 205 ++++++------------ .../story-decorator/src/StoryDecorator.ts | 59 ++++- 3 files changed, 129 insertions(+), 138 deletions(-) diff --git a/packages/calendar/package.json b/packages/calendar/package.json index 843908042fb..14614ba5a82 100644 --- a/packages/calendar/package.json +++ b/packages/calendar/package.json @@ -69,7 +69,8 @@ "@spectrum-web-components/reactive-controllers": "^0.41.2" }, "devDependencies": { - "@spectrum-css/calendar": "^4.2.4" + "@spectrum-css/calendar": "^4.2.4", + "@spectrum-web-components/story-decorator": "^0.41.2" }, "types": "./src/index.d.ts", "customElements": "custom-elements.json", diff --git a/packages/calendar/stories/calendar.stories.ts b/packages/calendar/stories/calendar.stories.ts index 73c2512e93e..bd61e328f8a 100644 --- a/packages/calendar/stories/calendar.stories.ts +++ b/packages/calendar/stories/calendar.stories.ts @@ -9,112 +9,37 @@ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTA OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -import { html, TemplateResult } from '@spectrum-web-components/base'; -import { ifDefined } from '@spectrum-web-components/base/src/directives.js'; +import { html, render, TemplateResult } from '@spectrum-web-components/base'; +import { defaultLocale } from '@spectrum-web-components/story-decorator/src/StoryDecorator.js'; import { spreadProps } from '../../../test/lit-helpers.js'; import '@spectrum-web-components/calendar/sp-calendar.js'; import '@spectrum-web-components/theme/sp-theme.js'; -const locales = [ - 'cs-CZ', - 'cy-GB', - 'da-DK', - 'de-DE', - 'en-GB', - 'en-US', - 'es-ES', - 'fi-FI', - 'fr-FR', - 'hu-HU', - 'it-IT', - 'ja-JP', - 'ko-KR', - 'nb-NO', - 'nl-NL', - 'pl-PL', - 'pt-BR', - 'ru-RU', - 'sv-SE', - 'tr-TR', - 'uk-UA', - 'zh-Hans-CN', - 'zh-Hans-CN-u-nu-hanidec', - 'zh-Hant-TW', - 'zz-ZY', - 'zz-ZZ', -] as const; - -const defaultLocale = 'en-US'; - -const hiddenProperty = { - table: { - disable: true, - }, -}; - export default { title: 'Calendar', component: 'sp-calendar', - - argTypes: { - lang: { - options: locales, - control: { - type: 'select', - }, - table: { - defaultValue: { - summary: defaultLocale, - }, - }, - }, - - // Don't render private properties and getters in the Storybook UI - currentDate: { ...hiddenProperty }, - minDate: { ...hiddenProperty }, - maxDate: { ...hiddenProperty }, - weeksInCurrentMonth: { ...hiddenProperty }, - weekdays: { ...hiddenProperty }, - languageResolver: { ...hiddenProperty }, - timeZone: { ...hiddenProperty }, - locale: { ...hiddenProperty }, - today: { ...hiddenProperty }, - - // Inherited - _dirParent: { ...hiddenProperty }, - shadowRoot: { ...hiddenProperty }, - dir: { ...hiddenProperty }, - isLTR: { ...hiddenProperty }, - }, - - args: { - lang: defaultLocale, - }, - parameters: { - controls: { - // Hide "This story is not configured to handle controls" warning - hideNoControlsWarning: true, - }, actions: { handles: ['onChange'], }, }, }; -interface StoryArgs { - lang?: string; - - padded?: boolean; - disabled?: boolean; +type ComponentArgs = { selectedDate?: Date; min?: Date; max?: Date; + padded?: boolean; + disabled?: boolean; +}; - onChange?: (date: Date) => void; +type StoryArgs = ComponentArgs & { + onChange?: (dateTime: Date) => void; +}; +interface SpreadStoryArgs { [prop: string]: unknown; } @@ -122,64 +47,34 @@ const renderCalendar = ( title: string, args: StoryArgs = {} ): TemplateResult => { - return html` - -

${title}

-

- Locale: - ${args.lang} -

- -
- - -
+ const story = html` +

${title}

+
+ `; -}; - -export const Default = (args: StoryArgs = {}): TemplateResult => { - return renderCalendar('Default', args); -}; -export const padded = (args: StoryArgs = {}): TemplateResult => { - return renderCalendar(`Padded? ${args.padded}`, args); -}; + const randomId = Math.floor(Math.random() * 99999); -padded.argTypes = { - padded: { - control: 'boolean', - table: { - defaultValue: { - summary: true, - }, - }, - }, -}; - -padded.args = { - padded: true, -}; + requestAnimationFrame(() => { + const container = document.querySelector( + `.story-container-${randomId}` + ); -export const disabled = (args: StoryArgs = {}): TemplateResult => { - return renderCalendar(`Disabled? ${args.disabled}`, args); -}; + if (container) { + render(story, container as HTMLElement); + } + }); -disabled.argTypes = { - disabled: { - control: 'boolean', - table: { - defaultValue: { - summary: true, - }, - }, - }, + return html` +
+ `; }; -disabled.args = { - disabled: true, +export const Default = (args: StoryArgs = {}): TemplateResult => { + return renderCalendar('Default', args); }; export const selectedDate = (args: StoryArgs = {}): TemplateResult => { @@ -241,3 +136,41 @@ export const maximumDate = (args: StoryArgs = {}): TemplateResult => { return renderCalendar(`Maximum Date: ${formatted}`, args); }; + +export const disabled = (args: StoryArgs = {}): TemplateResult => { + return renderCalendar(`Disabled? ${args.disabled}`, args); +}; + +disabled.argTypes = { + disabled: { + control: 'boolean', + table: { + defaultValue: { + summary: true, + }, + }, + }, +}; + +disabled.args = { + disabled: true, +}; + +export const padded = (args: StoryArgs = {}): TemplateResult => { + return renderCalendar(`Padded? ${args.padded}`, args); +}; + +padded.argTypes = { + padded: { + control: 'boolean', + table: { + defaultValue: { + summary: true, + }, + }, + }, +}; + +padded.args = { + padded: true, +}; diff --git a/projects/story-decorator/src/StoryDecorator.ts b/projects/story-decorator/src/StoryDecorator.ts index a3f5a8044b8..0934423c139 100644 --- a/projects/story-decorator/src/StoryDecorator.ts +++ b/projects/story-decorator/src/StoryDecorator.ts @@ -95,6 +95,34 @@ const reduceMotionProperties = css` --swc-test-duration: 1ms; `; +export const locales = [ + 'cs-CZ', + 'cy-GB', + 'da-DK', + 'de-DE', + 'en-GB', + 'en-US', + 'es-ES', + 'fi-FI', + 'fr-FR', + 'hu-HU', + 'it-IT', + 'ja-JP', + 'ko-KR', + 'nb-NO', + 'nl-NL', + 'pl-PL', + 'pt-BR', + 'ru-RU', + 'sv-SE', + 'tr-TR', + 'uk-UA', + 'zh-Hans-CN', + 'zh-Hant-TW', +] as const; + +export const defaultLocale = 'en-US'; + export class StoryDecorator extends SpectrumElement { static override get styles() { return [ @@ -190,6 +218,9 @@ export class StoryDecorator extends SpectrumElement { @property({ type: Boolean, reflect: true }) public screenshot = screenshot; + @property() + public locale: typeof locales[number] = defaultLocale; + @queryAsync('sp-theme') private themeRoot!: Theme; @@ -242,6 +273,10 @@ export class StoryDecorator extends SpectrumElement { } } + private updateLocale({ target }: Event & { target: Picker }): void { + this.locale = target.value as typeof locales[number]; + } + protected handleKeydown(event: KeyboardEvent): void { const path = event.composedPath(); const hasInput = path.some( @@ -262,6 +297,7 @@ export class StoryDecorator extends SpectrumElement { color=${this.color} scale=${this.scale} dir=${this.direction} + lang=${this.locale} part="container" @keydown=${this.handleKeydown} > @@ -306,7 +342,8 @@ export class StoryDecorator extends SpectrumElement { return html`
${this.themeControl} ${this.colorControl} ${this.scaleControl} - ${this.dirControl} ${this.reduceMotionControl} + ${this.dirControl} ${this.localeControl} + ${this.reduceMotionControl}
`; } @@ -387,6 +424,26 @@ export class StoryDecorator extends SpectrumElement { `; } + private get localeControl(): TemplateResult { + return html` + Locale + + ${locales.map( + (locale) => html` + ${locale} + ` + )} + + `; + } + private get reduceMotionControl(): TemplateResult { return html` Date: Wed, 6 Mar 2024 19:40:55 +0000 Subject: [PATCH 07/42] fix: picker button import --- packages/picker-button/stories/picker-button-sizes.stories.ts | 1 + packages/picker-button/stories/picker-button.stories.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/picker-button/stories/picker-button-sizes.stories.ts b/packages/picker-button/stories/picker-button-sizes.stories.ts index f97155b4f19..15459cbdbf2 100644 --- a/packages/picker-button/stories/picker-button-sizes.stories.ts +++ b/packages/picker-button/stories/picker-button-sizes.stories.ts @@ -12,6 +12,7 @@ governing permissions and limitations under the License. import { TemplateResult } from '@spectrum-web-components/base'; import { argTypes, StoryArgs, Template } from './index.js'; + import '@spectrum-web-components/picker-button/sp-picker-button.js'; export default { diff --git a/packages/picker-button/stories/picker-button.stories.ts b/packages/picker-button/stories/picker-button.stories.ts index e1d9864467a..8445a30ca50 100644 --- a/packages/picker-button/stories/picker-button.stories.ts +++ b/packages/picker-button/stories/picker-button.stories.ts @@ -13,9 +13,9 @@ governing permissions and limitations under the License. import { html, TemplateResult } from '@spectrum-web-components/base'; import { argTypes, StoryArgs, Template } from './index.js'; -import '@spectrum-web-components/picker-button/sp-picker-button.js'; import '@spectrum-web-components/icons-workflow/icons/sp-icon-add.js'; +import '@spectrum-web-components/picker-button/sp-picker-button.js'; export default { title: 'Picker Button', From a95fec6f015b41817dfd651ae4020004deb56fd6 Mon Sep 17 00:00:00 2001 From: Paulo de Tarso Furtado Machado Date: Wed, 6 Mar 2024 19:45:45 +0000 Subject: [PATCH 08/42] refactor: use `beforeinput` and `input` events --- tools/input-segments/README.md | 6 +- tools/input-segments/src/InputSegments.ts | 1067 +++++++++++-------- tools/input-segments/src/input-segments.css | 8 +- tools/input-segments/src/types.ts | 4 +- 4 files changed, 614 insertions(+), 471 deletions(-) diff --git a/tools/input-segments/README.md b/tools/input-segments/README.md index fd4177d5364..b711a31c4cd 100644 --- a/tools/input-segments/README.md +++ b/tools/input-segments/README.md @@ -21,10 +21,8 @@ export class MyInput extends InputSegments { ## To-do list -- Include ARIA attributes for editable segments -- Use `@input`/`@beforeinput` events to handle data input/content cleanup -- Move `handleKeydown()` call to a cache so that it doesn't cycle on the binding in each render pass -- Rename `handleKeydown()` to match the new events used +- Include/review ARIA attributes for editable segments +- Move `handle` functions call to a cache so that it doesn't cycle on the binding in each render pass - Define/revise list of locales and include them in the VRT process to ensure long-term delivery - Complete documentation - Add/Review unit tests diff --git a/tools/input-segments/src/InputSegments.ts b/tools/input-segments/src/InputSegments.ts index 70d86174e02..600c4811532 100644 --- a/tools/input-segments/src/InputSegments.ts +++ b/tools/input-segments/src/InputSegments.ts @@ -205,8 +205,12 @@ export class InputSegments extends TextfieldBase { protected override renderField(): TemplateResult { return html` - ${this.renderStateIcons()} + ${this.renderStateIcons()} ${this.renderInputContent()} + `; + } + public renderInputContent(): TemplateResult { + return html`
{ this.handleKeydown(segment, event); }} + @beforeinput=${(event: InputEvent) => { + this.handleBeforeInput(segment, event); + }} + @input=${(event: InputEvent) => { + this.handleInputEvent(segment, event); + }} > ${when( - isPlaceholderVisible, + usePlaceholder, () => html`
+ >
`; } From 496b975045d0788d38812d4551c81650865de88a Mon Sep 17 00:00:00 2001 From: Paulo de Tarso Furtado Machado Date: Fri, 1 Dec 2023 13:24:48 +0000 Subject: [PATCH 11/42] fix: dealing with days and hours --- tools/input-segments/src/InputSegments.ts | 129 +++++++++++++++++++--- 1 file changed, 112 insertions(+), 17 deletions(-) diff --git a/tools/input-segments/src/InputSegments.ts b/tools/input-segments/src/InputSegments.ts index e66a55d2619..cd36fbfe0ba 100644 --- a/tools/input-segments/src/InputSegments.ts +++ b/tools/input-segments/src/InputSegments.ts @@ -392,12 +392,13 @@ export class InputSegments extends TextfieldBase { return; } + const isDate = dateSegmentTypes.includes(segment.type); const typedValue = this.numberParser.parse(data); const isAmPmHour = this.is12HourClock && segment.type === 'hour'; segment.value = isAmPmHour ? this.getNewValueForAmPmHourSegment(details, typedValue) - : this.getNewValueForOtherSegments(details, typedValue); + : this.getNewValueForOtherSegments(details, typedValue, isDate); this.valueChanged(segment, event); } @@ -521,8 +522,12 @@ export class InputSegments extends TextfieldBase { segment: Segment, event: InputEvent | KeyboardEvent ): void { - if (this.is12HourClock && segment.type === 'dayPeriod') { - this.updateHour(); + if (this.is12HourClock) { + if (segment.type === 'hour') { + this.updateAmPm(); + } else if (segment.type === 'dayPeriod') { + this.updateHour(); + } } const hasDay = isNumber(this.daySegment?.value); @@ -704,16 +709,22 @@ export class InputSegments extends TextfieldBase { * * @param details - Segment value and limits * @param typedValue - The value typed by the user + * @param isDateSegment - Indicates if it is a date segment */ protected getNewValueForOtherSegments( details: SegmentDetails, - typedValue: number - ): number { + typedValue: number, + isDateSegment: boolean + ): number | undefined { let newValue = this.mergePreviousValueWithTypedValue( details, typedValue ); + if (isDateSegment && newValue === 0) { + return undefined; + } + const min = details.minValue; const max = details.maxValue; @@ -731,7 +742,14 @@ export class InputSegments extends TextfieldBase { } /** - * If the segment has a `value`, it defines the text used in the UI formatted according to the locale + * If the segment has a `value`, it defines the text used in the UI formatted according to the locale. At this + * moment we are formatting the value of a specific segment, but it is not possible to generate a valid Date object + * with just one piece of information (day, month, year, etc.), so we need to define a "base date" to be used + * together with the value of the segment. + * + * For example, if the current segment is the day segment, but the month and year segment have not yet been defined, + * we need to choose a month and a year to be used in composing the date that will be used in formatting, after all, + * there is no day without a month and a year. * * @param segment - Segment to format the value */ @@ -740,22 +758,28 @@ export class InputSegments extends TextfieldBase { return; } + // We always use the first day of a month unless a specific day is specified + let day = this.daySegment?.value ?? 1; + + // We always use the first month of the year unless a specific month is specified + let month = + this.monthSegment?.value ?? + getMinimumMonthInYear(this.currentDateTime); + let year = this.yearSegment?.value ?? this.currentDateTime.year; - let month = this.monthSegment?.value ?? this.currentDateTime.month; - let day = this.daySegment?.value ?? this.currentDateTime.day; let hour = this.hourSegment?.value ?? this.currentDateTime.hour; let minute = this.minuteSegment?.value ?? this.currentDateTime.minute; let second = this.secondSegment?.value ?? this.currentDateTime.second; switch (segment.type) { - case 'year': - year = segment.value; + case 'day': + day = segment.value; break; case 'month': month = segment.value; break; - case 'day': - day = segment.value; + case 'year': + year = segment.value; break; case 'hour': hour = segment.value; @@ -766,6 +790,9 @@ export class InputSegments extends TextfieldBase { case 'second': second = segment.value; break; + case 'dayPeriod': + hour = (segment.value ?? 0) + 1; + break; } /** @@ -778,6 +805,20 @@ export class InputSegments extends TextfieldBase { return; } + /** + * If the day being formatted is February 29th but the year segment has not yet been filled, we need to use a + * leap year to allow the 29th to remain, otherwise, if we use the current year and it is not a leap year, the + * day that would be displayed would be March 1st, as February 29th would not exist and JavaScript “moves” the + * day to the next day. As this year is only used to format the day and month, we use the year 2000 as the "base + * year" for formatting + */ + if ( + !this.yearSegment?.value && + (['day', 'month'] as typeof dateSegmentTypes).includes(segment.type) + ) { + year = 2000; + } + const date = this.getDate(year, month, day); if (!date) { @@ -1047,6 +1088,16 @@ export class InputSegments extends TextfieldBase { } } + /** + * If the defined month is February but we don't yet have the year defined, we use 29 as the max limit, as we have + * no way of knowing whether it is a leap year or not until the year segment is filled + */ + private getFebruaryMaxValue(): number | undefined { + return this.monthSegment?.value === 2 && !this.yearSegment?.value + ? 29 + : undefined; + } + /** * Checks whether the segment being created or updated will have a value or not by checking the following order: * @@ -1135,15 +1186,34 @@ export class InputSegments extends TextfieldBase { ), value, }; - case 'day': + case 'day': { + let max = this.currentDateTime.calendar.getDaysInMonth( + this.currentDateTime + ); + + /** + * If we do not yet have a month defined by the user, we use the highest possible number as a maximum + * limit. When the month is set, if the day is outside the allowed range, it will be corrected + * automatically + */ + if (!this.monthSegment?.value) { + max = 31; + } + + // Check whether the maximum possible limit for the month of February should be used + const febMaxValue = this.getFebruaryMaxValue(); + + if (isNumber(febMaxValue)) { + max = febMaxValue; + } + return { minValue: getMinimumDayInMonth(this.currentDateTime), - maxValue: this.currentDateTime.calendar.getDaysInMonth( - this.currentDateTime - ), + maxValue: max, value, }; - case 'hour': + } + case 'hour': { let min = 0; let max = 23; @@ -1161,6 +1231,7 @@ export class InputSegments extends TextfieldBase { maxValue: max, value, }; + } case 'minute': case 'second': return { @@ -1199,6 +1270,23 @@ export class InputSegments extends TextfieldBase { } } + private updateAmPm(): void { + if (!this.hourSegment || !this.amPmSegment) { + this.resetHourAndAmPm(); + return; + } + + // If there is no hour or if AM/PM is already set, there is nothing to do + if ( + this.hourSegment.value === undefined || + this.amPmSegment.value !== undefined + ) { + return; + } + + this.amPmSegment.value = this.getAmPmModifier(this.hourSegment.value); + } + /** * When the day period is changed, it automatically adjusts the hour if it has already been informed previously to * match the new period (AM or PM). In addition, the minimum and maximum values of the hour are also changed @@ -1285,6 +1373,13 @@ export class InputSegments extends TextfieldBase { this.daySegment.maxValue = lastDayOfMonth.day; + // Check whether the maximum possible limit for the month of February should be used + const febMaxValue = this.getFebruaryMaxValue(); + + if (isNumber(febMaxValue)) { + this.daySegment.maxValue = febMaxValue; + } + if ( isNumber(this.daySegment.value) && this.daySegment.value > this.daySegment.maxValue From 7127a7e42ec54e5fa0098119da16628078b4b16b Mon Sep 17 00:00:00 2001 From: Mirek Szot Date: Wed, 6 Dec 2023 09:55:31 +0100 Subject: [PATCH 12/42] fix: fix quiet variant styles --- packages/picker-button/src/PickerButton.ts | 4 ++++ packages/picker-button/stories/picker-button.stories.ts | 3 +++ 2 files changed, 7 insertions(+) diff --git a/packages/picker-button/src/PickerButton.ts b/packages/picker-button/src/PickerButton.ts index 9fa2e11305a..ea795ab2a56 100644 --- a/packages/picker-button/src/PickerButton.ts +++ b/packages/picker-button/src/PickerButton.ts @@ -45,6 +45,9 @@ export class PickerButton extends SizedMixin( @property({ type: Boolean, reflect: true }) invalid = false; + @property({ type: Boolean, reflect: true }) + quiet = false; + @property({ reflect: true }) position: 'left' | 'right' = 'right'; @@ -57,6 +60,7 @@ export class PickerButton extends SizedMixin( root: true, uiicononly: !this.hasText, textuiicon: this.hasText, + 'spectrum-PickerButton--quiet': this.quiet, }; return html`
diff --git a/packages/picker-button/stories/picker-button.stories.ts b/packages/picker-button/stories/picker-button.stories.ts index 8445a30ca50..5510287005f 100644 --- a/packages/picker-button/stories/picker-button.stories.ts +++ b/packages/picker-button/stories/picker-button.stories.ts @@ -39,6 +39,9 @@ customIcon.args = { export const invalid = (args: StoryArgs): TemplateResult => Template(args); invalid.args = { invalid: true }; +export const quiet = (args: StoryArgs): TemplateResult => Template(args); +quiet.args = { quiet: true }; + export const label = (args: StoryArgs): TemplateResult => Template(args); label.args = { label: true }; From 74af9e96051de15080d290a9dc4e87c255fa877f Mon Sep 17 00:00:00 2001 From: Mirek Szot Date: Thu, 7 Dec 2023 08:54:55 +0100 Subject: [PATCH 13/42] fix: add calculation to count the width of the date/time picker --- packages/date-time-picker/src/date-time-picker.css | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/date-time-picker/src/date-time-picker.css b/packages/date-time-picker/src/date-time-picker.css index 0fa8a5aeb59..27770aaee62 100644 --- a/packages/date-time-picker/src/date-time-picker.css +++ b/packages/date-time-picker/src/date-time-picker.css @@ -20,6 +20,16 @@ governing permissions and limitations under the License. var(--spectrum-textfield-border-width) ) ); + + inline-size: calc( + 20ch + + ( + var( + --mod-textfield-icon-size-invalid, + var(--spectrum-textfield-icon-size-invalid) + ) * 3 + ) + var(--mod-textfield-height, var(--spectrum-textfield-height)) + ); } :host([valid]) #textfield .icon, From 7755dd79ce484f40c915ead1ffbe7b6f8cf9eca0 Mon Sep 17 00:00:00 2001 From: Mirek Szot Date: Thu, 7 Dec 2023 08:56:54 +0100 Subject: [PATCH 14/42] refactor: removes solved TODO's points --- packages/date-time-picker/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/date-time-picker/README.md b/packages/date-time-picker/README.md index ccbbfa9842d..a4dd1ab9425 100644 --- a/packages/date-time-picker/README.md +++ b/packages/date-time-picker/README.md @@ -30,7 +30,5 @@ import { DateTimePicker } from '@spectrum-web-components/date-time-picker'; ## To-do list - Enable "receives-focus" when calendar is navigable via keyboard -- Review border applied to `` when field is invalid -- Review field styles when using large scale - Complete documentation - Add/Review unit tests From 97f79ff97c18aa6d498d395246dae28df46859a6 Mon Sep 17 00:00:00 2001 From: Mirek Szot Date: Fri, 8 Dec 2023 15:27:14 +0100 Subject: [PATCH 15/42] refactor: removes broken unit test --- .../test/date-time-picker.test.ts | 23 +------------------ 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/packages/date-time-picker/test/date-time-picker.test.ts b/packages/date-time-picker/test/date-time-picker.test.ts index f1b6245eb5f..5bd45bcb851 100644 --- a/packages/date-time-picker/test/date-time-picker.test.ts +++ b/packages/date-time-picker/test/date-time-picker.test.ts @@ -9,30 +9,9 @@ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTA OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -import { elementUpdated, expect, fixture, html } from '@open-wc/testing'; import '../sp-date-time-picker.js'; -import { DateTimePicker } from '..'; -import { testForLitDevWarnings } from '../../../test/testing-helpers.js'; describe('DateTimePicker', () => { - testForLitDevWarnings( - async () => - await fixture( - html` - - ` - ) - ); - it('loads default date-time-picker accessibly', async () => { - const el = await fixture( - html` - - ` - ); - - await elementUpdated(el); - - await expect(el).to.be.accessible(); - }); + // TODO: add unit tests }); From 739091cd420054ce8b810418b6640712810f76ea Mon Sep 17 00:00:00 2001 From: Mirek Szot Date: Fri, 8 Dec 2023 17:40:16 +0100 Subject: [PATCH 16/42] refactor: adds unit test for default datetime picker --- .../test/date-time-picker.test.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/date-time-picker/test/date-time-picker.test.ts b/packages/date-time-picker/test/date-time-picker.test.ts index 5bd45bcb851..a2fc01c9d39 100644 --- a/packages/date-time-picker/test/date-time-picker.test.ts +++ b/packages/date-time-picker/test/date-time-picker.test.ts @@ -10,8 +10,19 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -import '../sp-date-time-picker.js'; +import { elementUpdated, expect, fixture } from '@open-wc/testing'; +import { testForLitDevWarnings } from '../../../test/testing-helpers.js'; +import { DateTimePicker } from '../src/DateTimePicker.js'; +import { Default } from '../stories/date-time-picker.stories.js'; describe('DateTimePicker', () => { - // TODO: add unit tests + testForLitDevWarnings(async () => await fixture(Default())); + + it('loads default date-time picker accessibly', async () => { + const el = await fixture(Default()); + + await elementUpdated(el); + + await expect(el).to.be.accessible(); + }); }); From 6aedcfc3967b5ab1a7c82a0bb655f8bedb400396 Mon Sep 17 00:00:00 2001 From: Mirek Szot Date: Wed, 13 Dec 2023 14:37:36 +0100 Subject: [PATCH 17/42] refactor: unit tests for date-time-picker --- .../test/date-time-picker.test.ts | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/packages/date-time-picker/test/date-time-picker.test.ts b/packages/date-time-picker/test/date-time-picker.test.ts index a2fc01c9d39..a55e4ee9d83 100644 --- a/packages/date-time-picker/test/date-time-picker.test.ts +++ b/packages/date-time-picker/test/date-time-picker.test.ts @@ -13,13 +13,23 @@ governing permissions and limitations under the License. import { elementUpdated, expect, fixture } from '@open-wc/testing'; import { testForLitDevWarnings } from '../../../test/testing-helpers.js'; import { DateTimePicker } from '../src/DateTimePicker.js'; -import { Default } from '../stories/date-time-picker.stories.js'; +import { html } from 'lit'; describe('DateTimePicker', () => { - testForLitDevWarnings(async () => await fixture(Default())); - - it('loads default date-time picker accessibly', async () => { - const el = await fixture(Default()); + testForLitDevWarnings( + async () => + await fixture( + html` + + ` + ) + ); + it('loads default sp-date-time-picker accessibly', async () => { + const el = await fixture( + html` + + ` + ); await elementUpdated(el); From 6873977fb303000156aab36f5605e31126ae2f41 Mon Sep 17 00:00:00 2001 From: Mirek Szot Date: Tue, 19 Dec 2023 14:32:04 +0100 Subject: [PATCH 18/42] refactor: fixes input line height --- tools/input-segments/src/input-segments.css | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/input-segments/src/input-segments.css b/tools/input-segments/src/input-segments.css index 9edcf6e47be..6d686ec33a4 100644 --- a/tools/input-segments/src/input-segments.css +++ b/tools/input-segments/src/input-segments.css @@ -16,6 +16,7 @@ governing permissions and limitations under the License. height: 100%; overflow-x: auto; scrollbar-width: none; /* Firefox */ + line-height: normal; } .input-content::-webkit-scrollbar { From 148dc8326bcf5297016fe0c6d197ef8be62da614 Mon Sep 17 00:00:00 2001 From: Paulo de Tarso Furtado Machado Date: Wed, 6 Mar 2024 19:54:52 +0000 Subject: [PATCH 19/42] chore: bump packages to 0.41.2 --- packages/date-time-picker/package.json | 12 ++++++------ yarn.lock | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/date-time-picker/package.json b/packages/date-time-picker/package.json index 55de70fcb65..4d6c18d0d4f 100644 --- a/packages/date-time-picker/package.json +++ b/packages/date-time-picker/package.json @@ -58,15 +58,15 @@ ], "dependencies": { "@spectrum-web-components/calendar": "^0.0.1", - "@spectrum-web-components/field-label": "^0.40.0", - "@spectrum-web-components/icons-workflow": "^0.40.0", + "@spectrum-web-components/field-label": "^0.40.2", + "@spectrum-web-components/icons-workflow": "^0.40.2", "@spectrum-web-components/input-segments": "^0.0.1", - "@spectrum-web-components/overlay": "^0.40.0", - "@spectrum-web-components/picker-button": "^0.40.0", - "@spectrum-web-components/popover": "^0.40.0" + "@spectrum-web-components/overlay": "^0.40.2", + "@spectrum-web-components/picker-button": "^0.40.2", + "@spectrum-web-components/popover": "^0.40.2" }, "devDependencies": { - "@spectrum-web-components/story-decorator": "^0.40.0" + "@spectrum-web-components/story-decorator": "^0.40.2" }, "types": "./src/index.d.ts", "customElements": "custom-elements.json", diff --git a/yarn.lock b/yarn.lock index 2efc7801a47..1971f2e19be 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5450,7 +5450,7 @@ "@spectrum-web-components/eslint-plugin@file:./linters/eslint": version "0.41.2" -"@spectrum-web-components/field-label@^0.40.0", "@spectrum-web-components/field-label@^0.40.5": +"@spectrum-web-components/field-label@^0.40.2", "@spectrum-web-components/field-label@^0.40.5": version "0.40.5" resolved "https://registry.yarnpkg.com/@spectrum-web-components/field-label/-/field-label-0.40.5.tgz#7ca5e44a24fa613e2f0adfc6f1209667f4515cd5" integrity sha512-lpw1j1+UHNsRAwKIvwsGQ/igfEp40JfteywF0gkgeHHi6XpN2moyZTaKw+p8RiVM6yaZyy8CvGJ+ATcgIjpalA== @@ -5478,7 +5478,7 @@ "@spectrum-web-components/icon" "^0.40.5" "@spectrum-web-components/iconset" "^0.40.5" -"@spectrum-web-components/icons-workflow@^0.40.0", "@spectrum-web-components/icons-workflow@^0.40.5": +"@spectrum-web-components/icons-workflow@^0.40.2", "@spectrum-web-components/icons-workflow@^0.40.5": version "0.40.5" resolved "https://registry.yarnpkg.com/@spectrum-web-components/icons-workflow/-/icons-workflow-0.40.5.tgz#8de8dd715f7cada2a874289c8513aeec622e7058" integrity sha512-gDYhC30iRp8FZrsvnudfsuXhBS6CKW0IM+fjAh4xZ9Hid6fv7GqRkT8rQ13Xkrx5d0ddZplDC1nNh6LMpuKEhw== @@ -5515,7 +5515,7 @@ dependencies: "@spectrum-web-components/base" "^0.40.5" -"@spectrum-web-components/overlay@^0.40.0", "@spectrum-web-components/overlay@^0.40.5": +"@spectrum-web-components/overlay@^0.40.2", "@spectrum-web-components/overlay@^0.40.5": version "0.40.5" resolved "https://registry.yarnpkg.com/@spectrum-web-components/overlay/-/overlay-0.40.5.tgz#5f7555f8463eb72107ec7e7a4ba6099c29af7f62" integrity sha512-G4Lt/nVrjhpTRIX3YikGEK9xiulSJDSwoN+oIeymaGFiKsDJtd12gU2ex231FhipeLrwrDtx4xyc8h/nXUL9NQ== @@ -5528,7 +5528,7 @@ "@spectrum-web-components/shared" "^0.40.5" "@spectrum-web-components/theme" "^0.40.5" -"@spectrum-web-components/picker-button@^0.40.0": +"@spectrum-web-components/picker-button@^0.40.2": version "0.40.5" resolved "https://registry.yarnpkg.com/@spectrum-web-components/picker-button/-/picker-button-0.40.5.tgz#8fdbe43c4d43cc442c105b20dc7de2d0bd12cad5" integrity sha512-IKy7niIVenRbZd+LPX6tWU8OCKM3hOGKEEr+l22yqyLxQEhmjduA8zqcdOiZ0LjQPXLCBO7nJ9E2qZvSugsFDA== @@ -5557,7 +5557,7 @@ "@spectrum-web-components/tooltip" "^0.40.5" "@spectrum-web-components/tray" "^0.40.5" -"@spectrum-web-components/popover@^0.40.0", "@spectrum-web-components/popover@^0.40.5": +"@spectrum-web-components/popover@^0.40.2", "@spectrum-web-components/popover@^0.40.5": version "0.40.5" resolved "https://registry.yarnpkg.com/@spectrum-web-components/popover/-/popover-0.40.5.tgz#383f2583331a3a3f2862180a93277d2c65fefddd" integrity sha512-G34spy2TJUx9R6JHHjVoNG+ldk/RcLOfEEpj1aXKQrWDSzN3tF7zxFm0DOSj7FZ982vI3PpHV5m+7RpmeI7l2w== @@ -5581,7 +5581,7 @@ "@spectrum-web-components/base" "^0.40.5" focus-visible "^5.1.0" -"@spectrum-web-components/story-decorator@^0.40.0": +"@spectrum-web-components/story-decorator@^0.40.2": version "0.40.5" resolved "https://registry.yarnpkg.com/@spectrum-web-components/story-decorator/-/story-decorator-0.40.5.tgz#dcb4ebae188b31be95cffb4689c9cee5524ecf91" integrity sha512-Qbse5BYDtLL+QTTK9hJvObl7tlXecqmW5QqCUNnoiR/6FwfVx6AawLDYBu5jEV3HXteuQgds/gPWEMXfBTyK/g== From 8e5949755f1ed72c33fa89aa5f9d4782f93f6aac Mon Sep 17 00:00:00 2001 From: Paulo de Tarso Furtado Machado Date: Wed, 6 Mar 2024 19:57:25 +0000 Subject: [PATCH 20/42] refactor: feedback implementation v1 --- packages/calendar/src/Calendar.ts | 4 +- packages/calendar/stories/calendar.stories.ts | 38 +++++------------ packages/date-time-picker/README.md | 1 + .../date-time-picker/src/DateTimePicker.ts | 42 +++++++++---------- .../date-time-picker/src/date-time-picker.css | 22 +++++----- .../test/benchmark/basic-test.ts | 4 +- packages/picker-button/src/PickerButton.ts | 5 +-- packages/picker-button/src/spectrum-config.js | 2 +- .../src/spectrum-picker-button.css | 2 +- tools/input-segments/src/InputSegments.ts | 20 +++++---- tools/input-segments/src/input-segments.css | 8 +++- 11 files changed, 68 insertions(+), 80 deletions(-) diff --git a/packages/calendar/src/Calendar.ts b/packages/calendar/src/Calendar.ts index 61f18ca4cab..8bc744cc633 100644 --- a/packages/calendar/src/Calendar.ts +++ b/packages/calendar/src/Calendar.ts @@ -89,8 +89,8 @@ export class Calendar extends SpectrumElement { @property({ type: Boolean, reflect: true }) padded = false; - @state() - private currentDate!: CalendarDate; + @property({ attribute: false }) + currentDate!: CalendarDate; @state() private minDate!: CalendarDate; diff --git a/packages/calendar/stories/calendar.stories.ts b/packages/calendar/stories/calendar.stories.ts index bd61e328f8a..6ff9f12ea5e 100644 --- a/packages/calendar/stories/calendar.stories.ts +++ b/packages/calendar/stories/calendar.stories.ts @@ -16,6 +16,7 @@ import { spreadProps } from '../../../test/lit-helpers.js'; import '@spectrum-web-components/calendar/sp-calendar.js'; import '@spectrum-web-components/theme/sp-theme.js'; +import { CalendarDate } from '@internationalized/date'; export default { title: 'Calendar', @@ -28,6 +29,7 @@ export default { }; type ComponentArgs = { + currentDate?: CalendarDate; selectedDate?: Date; min?: Date; max?: Date; @@ -47,11 +49,13 @@ const renderCalendar = ( title: string, args: StoryArgs = {} ): TemplateResult => { + const currentDate = new CalendarDate(2023, 11, 17); const story = html`

${title}


`; @@ -94,47 +98,25 @@ export const selectedDate = (args: StoryArgs = {}): TemplateResult => { }; export const minimumDate = (args: StoryArgs = {}): TemplateResult => { - const today = new Date(); - const lastMonth = new Date( - today.getFullYear(), - today.getMonth() - 1, - today.getDate() - ); - - const formatted = Intl.DateTimeFormat(defaultLocale, { - day: 'numeric', - month: 'long', - year: 'numeric', - }).format(lastMonth); + const minimumDate = new Date(2023, 10, 12); args = { ...args, - min: lastMonth, + min: minimumDate, }; - return renderCalendar(`Minimum Date: ${formatted}`, args); + return renderCalendar(`Minimum Date: ${minimumDate.toDateString()}`, args); }; export const maximumDate = (args: StoryArgs = {}): TemplateResult => { - const today = new Date(); - const nextMonth = new Date( - today.getFullYear(), - today.getMonth() + 1, - today.getDate() - ); - - const formatted = Intl.DateTimeFormat(defaultLocale, { - day: 'numeric', - month: 'long', - year: 'numeric', - }).format(nextMonth); + const maxDate = new Date(2023, 10, 23); args = { ...args, - max: nextMonth, + max: maxDate, }; - return renderCalendar(`Maximum Date: ${formatted}`, args); + return renderCalendar(`Maximum Date: ${maxDate.toDateString()}`, args); }; export const disabled = (args: StoryArgs = {}): TemplateResult => { diff --git a/packages/date-time-picker/README.md b/packages/date-time-picker/README.md index a4dd1ab9425..c7ffcdf2da8 100644 --- a/packages/date-time-picker/README.md +++ b/packages/date-time-picker/README.md @@ -32,3 +32,4 @@ import { DateTimePicker } from '@spectrum-web-components/date-time-picker'; - Enable "receives-focus" when calendar is navigable via keyboard - Complete documentation - Add/Review unit tests +- Review https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-datepicker/ - we likely want this to trap the tab order. diff --git a/packages/date-time-picker/src/DateTimePicker.ts b/packages/date-time-picker/src/DateTimePicker.ts index c091561e70f..0d262752bd1 100644 --- a/packages/date-time-picker/src/DateTimePicker.ts +++ b/packages/date-time-picker/src/DateTimePicker.ts @@ -60,23 +60,23 @@ export class DateTimePicker extends InputSegments { protected override renderField(): TemplateResult { return html` - ${super.renderInputContent()} ${this.renderPicker()} + ${this.renderInputContent()} ${this.renderPicker()} `; } public renderPicker(): TemplateResult { - const isDisabled = super.disabled || super.readonly; + const isDisabled = this.disabled || this.readonly; return html`
- ${super.renderStateIcons()} + ${this.renderStateIcons()} @@ -89,7 +89,7 @@ export class DateTimePicker extends InputSegments { receives-focus="false" .triggerElement=${this as HTMLElement} ?open=${this.open} - @sp-closed=${this.closePicker} + @sp-closed=${this.hidePicker} >
@@ -104,14 +104,14 @@ export class DateTimePicker extends InputSegments { `; } - public openPicker(): void { - this.pickerDate = super.getDateFromSegments(); + public showPicker(): void { + this.pickerDate = this.getDateFromSegments(); this.open = true; } - public closePicker(): void { - super.setNewDateTime(); - super.emitNewDateTime(); + public hidePicker(): void { + this.setNewDateTime(); + this.emitNewDateTime(); this.pickerDate = undefined; this.open = false; @@ -122,7 +122,7 @@ export class DateTimePicker extends InputSegments { * * @param event - Event with the value emitted by the calendar */ - public handleDate(event: CustomEvent): void { + private handleDate(event: CustomEvent): void { event.stopPropagation(); const dateTime = event.detail; @@ -140,19 +140,19 @@ export class DateTimePicker extends InputSegments { const { year, month, day } = this.dateToCalendarDateTime(dateTime); - if (!super.yearSegment || !super.monthSegment || !super.daySegment) { + if (!this.yearSegment || !this.monthSegment || !this.daySegment) { return; } - super.yearSegment.value = year; - super.formatValue(super.yearSegment); + this.yearSegment.value = year; + this.formatValue(this.yearSegment); - super.monthSegment.value = month; - super.formatValue(super.monthSegment); + this.monthSegment.value = month; + this.formatValue(this.monthSegment); - super.daySegment.value = day; - super.formatValue(super.daySegment); + this.daySegment.value = day; + this.formatValue(this.daySegment); - super.requestUpdate(); + this.requestUpdate(); } } diff --git a/packages/date-time-picker/src/date-time-picker.css b/packages/date-time-picker/src/date-time-picker.css index 27770aaee62..74be49f2a33 100644 --- a/packages/date-time-picker/src/date-time-picker.css +++ b/packages/date-time-picker/src/date-time-picker.css @@ -10,17 +10,6 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ :host { - --datetime-picker-spacing: calc( - var( - --mod-textfield-spacing-inline, - var(--spectrum-textfield-spacing-inline) - ) - - var( - --mod-textfield-border-width, - var(--spectrum-textfield-border-width) - ) - ); - inline-size: calc( 20ch + ( @@ -46,7 +35,16 @@ governing permissions and limitations under the License. align-items: center; justify-content: flex-end; height: 100%; - gap: var(--datetime-picker-spacing); + gap: calc( + var( + --mod-textfield-spacing-inline, + var(--spectrum-textfield-spacing-inline) + ) - + var( + --mod-textfield-border-width, + var(--spectrum-textfield-border-width) + ) + ); } .popover { diff --git a/packages/date-time-picker/test/benchmark/basic-test.ts b/packages/date-time-picker/test/benchmark/basic-test.ts index 68adff096f8..19533cc15eb 100644 --- a/packages/date-time-picker/test/benchmark/basic-test.ts +++ b/packages/date-time-picker/test/benchmark/basic-test.ts @@ -14,5 +14,7 @@ import { html } from '@spectrum-web-components/base'; import { measureFixtureCreation } from '../../../../test/benchmark/helpers.js'; measureFixtureCreation(html` - + `); diff --git a/packages/picker-button/src/PickerButton.ts b/packages/picker-button/src/PickerButton.ts index ea795ab2a56..f4794c649cb 100644 --- a/packages/picker-button/src/PickerButton.ts +++ b/packages/picker-button/src/PickerButton.ts @@ -45,9 +45,6 @@ export class PickerButton extends SizedMixin( @property({ type: Boolean, reflect: true }) invalid = false; - @property({ type: Boolean, reflect: true }) - quiet = false; - @property({ reflect: true }) position: 'left' | 'right' = 'right'; @@ -60,8 +57,8 @@ export class PickerButton extends SizedMixin( root: true, uiicononly: !this.hasText, textuiicon: this.hasText, - 'spectrum-PickerButton--quiet': this.quiet, }; + return html`
diff --git a/packages/picker-button/src/spectrum-config.js b/packages/picker-button/src/spectrum-config.js index b555a8a7246..682418c3632 100644 --- a/packages/picker-button/src/spectrum-config.js +++ b/packages/picker-button/src/spectrum-config.js @@ -211,7 +211,7 @@ const config = { 'rounded' ), converter.classToAttribute( - 'spectrum-PickerButton--low', + 'spectrum-PickerButton--quiet', 'quiet' ), converter.classToClass('spectrum-PickerButton--uiicononly'), diff --git a/packages/picker-button/src/spectrum-picker-button.css b/packages/picker-button/src/spectrum-picker-button.css index 2848dc62799..229ec2009d7 100644 --- a/packages/picker-button/src/spectrum-picker-button.css +++ b/packages/picker-button/src/spectrum-picker-button.css @@ -106,7 +106,7 @@ governing permissions and limitations under the License. ); } -.root.spectrum-PickerButton--quiet { +:host([quiet]) .root { --mod-picker-button-background-color: var( --mod-picker-button-background-color-quiet, transparent diff --git a/tools/input-segments/src/InputSegments.ts b/tools/input-segments/src/InputSegments.ts index cd36fbfe0ba..ea4f83436ad 100644 --- a/tools/input-segments/src/InputSegments.ts +++ b/tools/input-segments/src/InputSegments.ts @@ -209,6 +209,15 @@ export class InputSegments extends TextfieldBase { `; } + protected renderSegmentText(segment: Segment): string { + const usePlaceholder = segment.value === undefined; + return when( + usePlaceholder, + () => segment.placeholder ?? '', + () => segment.formatted ?? '' + ); + } + public renderInputContent(): TemplateResult { return html`
@@ -283,11 +292,7 @@ export class InputSegments extends TextfieldBase { @input=${(event: InputEvent) => { this.handleInputEvent(segment, event); }} - .innerText=${when( - usePlaceholder, - () => segment.placeholder ?? '', - () => segment.formatted ?? '' - )} + .innerText=${this.renderSegmentText(segment)} >
`; } @@ -621,16 +626,13 @@ export class InputSegments extends TextfieldBase { }; } - const { value, minValue, maxValue } = this.getValueAndLimits(type); const placeholder = this.getPlaceholder(type, part.value); const segment: Segment = { type, formatted, - ...(value !== undefined && { value }), - ...(minValue !== undefined && { minValue }), - ...(maxValue !== undefined && { maxValue }), ...(placeholder !== undefined && { placeholder }), + ...this.getValueAndLimits(type), }; this.formatValue(segment); diff --git a/tools/input-segments/src/input-segments.css b/tools/input-segments/src/input-segments.css index 6d686ec33a4..3e7102b2817 100644 --- a/tools/input-segments/src/input-segments.css +++ b/tools/input-segments/src/input-segments.css @@ -50,10 +50,16 @@ governing permissions and limitations under the License. text-align: start; } -.editable-segment.is-placeholder { +.is-placeholder { font-style: italic; } +.is-placeholder:lang(ja), +.is-placeholder:lang(ko), +.is-placeholder:lang(zh) { + font-style: normal; +} + .editable-segment.is-placeholder, .editable-segment.is-placeholder + .literal-segment { color: var(--spectrum-gray-500); From 4254a70dbbc0d0fe5acdfb65d122d8eb822e30bf Mon Sep 17 00:00:00 2001 From: Mirek Szot Date: Thu, 21 Dec 2023 09:41:59 +0100 Subject: [PATCH 21/42] refactor: mock slected date for timeGlanularity story --- packages/date-time-picker/stories/date-time-picker.stories.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/date-time-picker/stories/date-time-picker.stories.ts b/packages/date-time-picker/stories/date-time-picker.stories.ts index fba2338f355..74dce12aa24 100644 --- a/packages/date-time-picker/stories/date-time-picker.stories.ts +++ b/packages/date-time-picker/stories/date-time-picker.stories.ts @@ -123,6 +123,7 @@ export const timeGranularity = (args: StoryArgs = {}): TemplateResult => { args = { ...args, timeGranularity: args.timeGranularity, + selectedDateTime: new Date(2021, 10, 2, 16, 1, 54), }; return renderDateTimePicker( From 5975f8833f844f500589e946f7dd4e498fad7cd3 Mon Sep 17 00:00:00 2001 From: Mirek Szot Date: Fri, 22 Dec 2023 10:40:31 +0100 Subject: [PATCH 22/42] refactor: adds unit test to calendar --- packages/calendar/src/Calendar.ts | 3 + packages/calendar/test/calendar.test.ts | 83 +++++++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/packages/calendar/src/Calendar.ts b/packages/calendar/src/Calendar.ts index 8bc744cc633..0bb82ba32db 100644 --- a/packages/calendar/src/Calendar.ts +++ b/packages/calendar/src/Calendar.ts @@ -162,6 +162,7 @@ export class Calendar extends SpectrumElement { class="spectrum-Calendar-title" aria-live="assertive" aria-atomic="true" + data-test-id="calendar-title" > ${monthAndYear}
@@ -176,6 +177,7 @@ export class Calendar extends SpectrumElement { aria-label="Previous" title="Previous" class="spectrum-Calendar-prevMonth" + data-test-id="prev-btn" ?disabled=${this.disabled} @click=${this.handlePreviousMonth} > @@ -196,6 +198,7 @@ export class Calendar extends SpectrumElement { aria-label="Next" title="Next" class="spectrum-Calendar-nextMonth" + data-test-id="next-btn" ?disabled=${this.disabled} @click=${this.handleNextMonth} > diff --git a/packages/calendar/test/calendar.test.ts b/packages/calendar/test/calendar.test.ts index 9bc72ba3af8..c300e4fdb32 100644 --- a/packages/calendar/test/calendar.test.ts +++ b/packages/calendar/test/calendar.test.ts @@ -14,6 +14,7 @@ import { elementUpdated, expect, fixture, html } from '@open-wc/testing'; import '../sp-calendar.js'; import { Calendar } from '..'; import { testForLitDevWarnings } from '../../../test/testing-helpers.js'; +import { CalendarDate } from '@internationalized/date'; describe('Calendar', () => { testForLitDevWarnings( @@ -35,4 +36,86 @@ describe('Calendar', () => { await expect(el).to.be.accessible(); }); + + it('should render calendar with correct month and year', async () => { + const el = await fixture( + html` + + ` + ); + + await elementUpdated(el); + + const monthYear = el.shadowRoot.querySelector( + '[data-test-id="calendar-title"]' + ); + + expect(monthYear?.innerHTML).contain('May 2022'); + }); + + it('should render disabled calendar cells', async () => { + const el = await fixture( + html` + + ` + ); + + await elementUpdated(el); + + const items = el.shadowRoot.querySelectorAll('td span'); + + items.forEach((item) => { + expect(item.classList.contains('is-disabled')).to.be.true; + }); + }); + + it('should go to next month after "Next" button click', async () => { + const currentMonth = new CalendarDate(2022, 2, 20); // 20 Feb 2022 + const el = await fixture( + html` + + ` + ); + + await elementUpdated(el); + + const nextBtn = el.shadowRoot.querySelector( + '[data-test-id="next-btn"]' + ); + + const monthYear = el.shadowRoot.querySelector( + '[data-test-id="calendar-title"]' + ); + + nextBtn?.click(); + await elementUpdated(el); + + expect(monthYear?.innerHTML).to.contain('March 2022'); + }); + + it('should go to previous month after "Prev" button click', async () => { + const currentMonth = new CalendarDate(2022, 2, 20); // 20 Feb 2022 + const el = await fixture( + html` + + ` + ); + + await elementUpdated(el); + + const nextBtn = el.shadowRoot.querySelector( + '[data-test-id="prev-btn"]' + ); + + const monthYear = el.shadowRoot.querySelector( + '[data-test-id="calendar-title"]' + ); + + nextBtn?.click(); + await elementUpdated(el); + + expect(monthYear?.innerHTML).to.contain('January 2022'); + }); }); From 4ba335c0d53278a55fe1e857b7303852553feca6 Mon Sep 17 00:00:00 2001 From: Mirek Szot Date: Fri, 22 Dec 2023 11:28:18 +0100 Subject: [PATCH 23/42] refactor: update naming --- packages/calendar/test/calendar.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/calendar/test/calendar.test.ts b/packages/calendar/test/calendar.test.ts index c300e4fdb32..566fafc8ec1 100644 --- a/packages/calendar/test/calendar.test.ts +++ b/packages/calendar/test/calendar.test.ts @@ -105,7 +105,7 @@ describe('Calendar', () => { await elementUpdated(el); - const nextBtn = el.shadowRoot.querySelector( + const prevBtn = el.shadowRoot.querySelector( '[data-test-id="prev-btn"]' ); @@ -113,7 +113,7 @@ describe('Calendar', () => { '[data-test-id="calendar-title"]' ); - nextBtn?.click(); + prevBtn?.click(); await elementUpdated(el); expect(monthYear?.innerHTML).to.contain('January 2022'); From 6a19a69bc48f8d4314792fc8df9e7d7bf28fe3d7 Mon Sep 17 00:00:00 2001 From: Mirek Szot Date: Fri, 22 Dec 2023 14:24:08 +0100 Subject: [PATCH 24/42] refactor: adds unit test for handleDayClick method --- packages/calendar/test/calendar.test.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/packages/calendar/test/calendar.test.ts b/packages/calendar/test/calendar.test.ts index 566fafc8ec1..0eb12d5d047 100644 --- a/packages/calendar/test/calendar.test.ts +++ b/packages/calendar/test/calendar.test.ts @@ -15,6 +15,7 @@ import '../sp-calendar.js'; import { Calendar } from '..'; import { testForLitDevWarnings } from '../../../test/testing-helpers.js'; import { CalendarDate } from '@internationalized/date'; +import { spy } from 'sinon'; describe('Calendar', () => { testForLitDevWarnings( @@ -118,4 +119,22 @@ describe('Calendar', () => { expect(monthYear?.innerHTML).to.contain('January 2022'); }); + + it('should call "@change" event', async () => { + const changeSpy = spy(); + const currentDate = new CalendarDate(2022, 2, 20); + const selectedDay = new CalendarDate(2022, 2, 3); + const el = await fixture( + html` + + ` + ); + + el.addEventListener('change', changeSpy); + el.handleDayClick(selectedDay); + + await elementUpdated(el); + + expect(changeSpy).to.be.calledOnce; + }); }); From 0a55f77b0531991f8a6ffe712dd3796e51fd2324 Mon Sep 17 00:00:00 2001 From: Paulo de Tarso Furtado Machado Date: Mon, 8 Jan 2024 13:43:15 -0300 Subject: [PATCH 25/42] refactor: update TODO list --- packages/date-time-picker/README.md | 1 + packages/date-time-picker/src/DateTimePicker.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/date-time-picker/README.md b/packages/date-time-picker/README.md index c7ffcdf2da8..3552431090e 100644 --- a/packages/date-time-picker/README.md +++ b/packages/date-time-picker/README.md @@ -33,3 +33,4 @@ import { DateTimePicker } from '@spectrum-web-components/date-time-picker'; - Complete documentation - Add/Review unit tests - Review https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-datepicker/ - we likely want this to trap the tab order. +- Load dependencies lazily when possible diff --git a/packages/date-time-picker/src/DateTimePicker.ts b/packages/date-time-picker/src/DateTimePicker.ts index 0d262752bd1..dc108c13efc 100644 --- a/packages/date-time-picker/src/DateTimePicker.ts +++ b/packages/date-time-picker/src/DateTimePicker.ts @@ -22,6 +22,7 @@ import { InputSegments } from '@spectrum-web-components/input-segments'; import styles from './date-time-picker.css.js'; +// TODO: Load dependencies lazily when possible import '@spectrum-web-components/calendar/sp-calendar.js'; import '@spectrum-web-components/field-label/sp-field-label.js'; import '@spectrum-web-components/icons-workflow/icons/sp-icon-calendar.js'; From 6ebca739d4685f641011e27bafbb223b061b12da Mon Sep 17 00:00:00 2001 From: Paulo de Tarso Furtado Machado Date: Mon, 8 Jan 2024 14:36:41 -0300 Subject: [PATCH 26/42] fix: create new segments when granularity is changed --- tools/input-segments/src/InputSegments.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/input-segments/src/InputSegments.ts b/tools/input-segments/src/InputSegments.ts index ea4f83436ad..f6c77dd2658 100644 --- a/tools/input-segments/src/InputSegments.ts +++ b/tools/input-segments/src/InputSegments.ts @@ -182,20 +182,20 @@ export class InputSegments extends TextfieldBase { let createSegments = false; if (changedProperties.has(languageResolverUpdatedSymbol)) { - createSegments = true; - - this.setFormatter(); this.setNumberParser(); } - if (changedProperties.has('selectedDateTime')) { + if ( + changedProperties.has(languageResolverUpdatedSymbol) || + changedProperties.has('timeGranularity') + ) { createSegments = true; - - this.setCurrentDateTime(); + this.setFormatter(); } - if (changedProperties.has('timeGranularity')) { + if (changedProperties.has('selectedDateTime')) { createSegments = true; + this.setCurrentDateTime(); } if (createSegments) { From 266dfe4542fad6bfb3e5e031b4cd2d0c19d380d8 Mon Sep 17 00:00:00 2001 From: Paulo de Tarso Furtado Machado Date: Thu, 11 Jan 2024 19:44:58 -0300 Subject: [PATCH 27/42] fix: renaming attribute from `locale` to `lang` --- projects/story-decorator/src/StoryDecorator.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/projects/story-decorator/src/StoryDecorator.ts b/projects/story-decorator/src/StoryDecorator.ts index 0934423c139..45dc8cce050 100644 --- a/projects/story-decorator/src/StoryDecorator.ts +++ b/projects/story-decorator/src/StoryDecorator.ts @@ -218,8 +218,8 @@ export class StoryDecorator extends SpectrumElement { @property({ type: Boolean, reflect: true }) public screenshot = screenshot; - @property() - public locale: typeof locales[number] = defaultLocale; + @property({ reflect: true }) + public override lang: typeof locales[number] = defaultLocale; @queryAsync('sp-theme') private themeRoot!: Theme; @@ -274,7 +274,7 @@ export class StoryDecorator extends SpectrumElement { } private updateLocale({ target }: Event & { target: Picker }): void { - this.locale = target.value as typeof locales[number]; + this.lang = target.value as typeof locales[number]; } protected handleKeydown(event: KeyboardEvent): void { @@ -297,7 +297,7 @@ export class StoryDecorator extends SpectrumElement { color=${this.color} scale=${this.scale} dir=${this.direction} - lang=${this.locale} + lang=${this.lang} part="container" @keydown=${this.handleKeydown} > @@ -432,7 +432,7 @@ export class StoryDecorator extends SpectrumElement { label="Locale" placement="top" quiet - .value=${this.locale} + .value=${this.lang} @change=${this.updateLocale} > ${locales.map( From 4cd79a5394188407009769a555ef32225ff78723 Mon Sep 17 00:00:00 2001 From: Paulo de Tarso Furtado Machado Date: Fri, 12 Jan 2024 10:26:13 -0300 Subject: [PATCH 28/42] refactor: use "quiet" variant of `sp-picker-button` when input is read-only --- packages/date-time-picker/src/DateTimePicker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/date-time-picker/src/DateTimePicker.ts b/packages/date-time-picker/src/DateTimePicker.ts index dc108c13efc..7fa04b7e3c1 100644 --- a/packages/date-time-picker/src/DateTimePicker.ts +++ b/packages/date-time-picker/src/DateTimePicker.ts @@ -74,7 +74,7 @@ export class DateTimePicker extends InputSegments { Date: Fri, 12 Jan 2024 10:27:44 -0300 Subject: [PATCH 29/42] refactor: remove unused imports --- packages/calendar/stories/calendar.stories.ts | 3 +-- packages/date-time-picker/stories/date-time-picker.stories.ts | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/calendar/stories/calendar.stories.ts b/packages/calendar/stories/calendar.stories.ts index 6ff9f12ea5e..c3fcb0ea919 100644 --- a/packages/calendar/stories/calendar.stories.ts +++ b/packages/calendar/stories/calendar.stories.ts @@ -9,14 +9,13 @@ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTA OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ +import { CalendarDate } from '@internationalized/date'; import { html, render, TemplateResult } from '@spectrum-web-components/base'; import { defaultLocale } from '@spectrum-web-components/story-decorator/src/StoryDecorator.js'; import { spreadProps } from '../../../test/lit-helpers.js'; import '@spectrum-web-components/calendar/sp-calendar.js'; -import '@spectrum-web-components/theme/sp-theme.js'; -import { CalendarDate } from '@internationalized/date'; export default { title: 'Calendar', diff --git a/packages/date-time-picker/stories/date-time-picker.stories.ts b/packages/date-time-picker/stories/date-time-picker.stories.ts index 74dce12aa24..cb78d0b2f14 100644 --- a/packages/date-time-picker/stories/date-time-picker.stories.ts +++ b/packages/date-time-picker/stories/date-time-picker.stories.ts @@ -23,7 +23,6 @@ import { spreadProps } from '../../../test/lit-helpers.js'; import '@spectrum-web-components/date-time-picker/sp-date-time-picker.js'; import '@spectrum-web-components/help-text/sp-help-text.js'; import '@spectrum-web-components/icons-workflow/icons/sp-icon-alert.js'; -import '@spectrum-web-components/theme/sp-theme.js'; export default { title: 'Date∕Time Picker', From 9119c5cf0904dee335d175ad2637d2e661d70bfa Mon Sep 17 00:00:00 2001 From: Paulo de Tarso Furtado Machado Date: Fri, 12 Jan 2024 10:29:54 -0300 Subject: [PATCH 30/42] refactor: enable "valid" and "invalid" attributes for all stories --- .../stories/date-time-picker.stories.ts | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/packages/date-time-picker/stories/date-time-picker.stories.ts b/packages/date-time-picker/stories/date-time-picker.stories.ts index cb78d0b2f14..3859e82d16b 100644 --- a/packages/date-time-picker/stories/date-time-picker.stories.ts +++ b/packages/date-time-picker/stories/date-time-picker.stories.ts @@ -32,6 +32,28 @@ export default { handles: ['onChange'], }, }, + argTypes: { + valid: { + control: 'boolean', + table: { + defaultValue: { + summary: false, + }, + }, + }, + invalid: { + control: 'boolean', + table: { + defaultValue: { + summary: false, + }, + }, + }, + }, + args: { + valid: false, + invalid: false, + }, }; const timeGranularities: TimeGranularity[] = ['hour', 'minute', 'second']; @@ -220,12 +242,9 @@ export const valid = (args: StoryArgs = {}): TemplateResult => { }; valid.argTypes = { - valid: { - control: 'boolean', + invalid: { table: { - defaultValue: { - summary: false, - }, + disable: true, }, }, }; @@ -239,12 +258,9 @@ export const invalid = (args: StoryArgs = {}): TemplateResult => { }; invalid.argTypes = { - invalid: { - control: 'boolean', + valid: { table: { - defaultValue: { - summary: false, - }, + disable: true, }, }, }; From 1901e55c07a2ff684b15a9def7be77cb1a74c110 Mon Sep 17 00:00:00 2001 From: Paulo de Tarso Furtado Machado Date: Fri, 12 Jan 2024 11:09:50 -0300 Subject: [PATCH 31/42] refactor: italicised placeholders for non-CJK languages --- tools/input-segments/src/InputSegments.ts | 1 + tools/input-segments/src/input-segments.css | 31 ++++++--------------- 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/tools/input-segments/src/InputSegments.ts b/tools/input-segments/src/InputSegments.ts index f6c77dd2658..8aab23d383b 100644 --- a/tools/input-segments/src/InputSegments.ts +++ b/tools/input-segments/src/InputSegments.ts @@ -211,6 +211,7 @@ export class InputSegments extends TextfieldBase { protected renderSegmentText(segment: Segment): string { const usePlaceholder = segment.value === undefined; + return when( usePlaceholder, () => segment.placeholder ?? '', diff --git a/tools/input-segments/src/input-segments.css b/tools/input-segments/src/input-segments.css index 3e7102b2817..9d3d5aa1d44 100644 --- a/tools/input-segments/src/input-segments.css +++ b/tools/input-segments/src/input-segments.css @@ -41,37 +41,25 @@ governing permissions and limitations under the License. outline: none; } -.literal-segment { - white-space: pre; - user-select: none; -} - [dir='ltr'] .editable-segment { text-align: start; } -.is-placeholder { - font-style: italic; -} - -.is-placeholder:lang(ja), -.is-placeholder:lang(ko), -.is-placeholder:lang(zh) { - font-style: normal; +.literal-segment { + white-space: pre; + user-select: none; } -.editable-segment.is-placeholder, -.editable-segment.is-placeholder + .literal-segment { +.is-placeholder, +.is-placeholder + .literal-segment { color: var(--spectrum-gray-500); } -.editable-segment.is-placeholder .placeholder { - height: auto; - visibility: visible; +.is-placeholder:not(:is(:lang(ja), :lang(ko), :lang(zh))) { + font-style: italic; } -.editable-segment:focus, -.editable-segment:focus .placeholder { +.editable-segment:focus { color: var(--spectrum-white); background-color: var(--spectrum-accent-background-color-default); } @@ -80,7 +68,6 @@ governing permissions and limitations under the License. * Hide selection because there is no way to avoid it entirely in Firefox * https://bugzilla.mozilla.org/show_bug.cgi?id=1742153 */ -.editable-segment::selection, -.placeholder::selection { +.editable-segment::selection { background-color: transparent; } From 08a748fbbd14e2f4bd338834adb5326b738235e5 Mon Sep 17 00:00:00 2001 From: Paulo de Tarso Furtado Machado Date: Fri, 12 Jan 2024 11:11:36 -0300 Subject: [PATCH 32/42] refactor: date/time picker width definition --- .../date-time-picker/src/date-time-picker.css | 48 ++++++++++++------- .../stories/date-time-picker.stories.ts | 40 +++++++++++++++- 2 files changed, 69 insertions(+), 19 deletions(-) diff --git a/packages/date-time-picker/src/date-time-picker.css b/packages/date-time-picker/src/date-time-picker.css index 74be49f2a33..7c6e11b7f5c 100644 --- a/packages/date-time-picker/src/date-time-picker.css +++ b/packages/date-time-picker/src/date-time-picker.css @@ -10,15 +10,24 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ :host { - inline-size: calc( - 20ch + - ( - var( - --mod-textfield-icon-size-invalid, - var(--spectrum-textfield-icon-size-invalid) - ) * 3 - ) + var(--mod-textfield-height, var(--spectrum-textfield-height)) + --status-icon-size: var( + --mod-textfield-icon-size-invalid, + var(--spectrum-textfield-icon-size-invalid) ); + --picker-button-size: var( + --mod-textfield-height, + var(--spectrum-textfield-height) + ); + --input-spacing: var( + --mod-textfield-spacing-inline, + var(--spectrum-textfield-spacing-inline) + ); + --input-border: var( + --mod-textfield-border-width, + var(--spectrum-textfield-border-width) + ); + + inline-size: auto; } :host([valid]) #textfield .icon, @@ -27,6 +36,18 @@ governing permissions and limitations under the License. inset: initial; } +:host .input, +:host([quiet]) .input, +:host([valid]) .input, +:host([invalid]) .input, +:host([quiet][valid]) #textfield .input, +:host([quiet][invalid]) #textfield .input { + padding-inline-end: calc( + var(--status-icon-size) + var(--picker-button-size) + + (var(--input-spacing) - var(--input-border)) * 2 + ); +} + .picker { position: absolute; inset-block-start: 0; @@ -35,16 +56,7 @@ governing permissions and limitations under the License. align-items: center; justify-content: flex-end; height: 100%; - gap: calc( - var( - --mod-textfield-spacing-inline, - var(--spectrum-textfield-spacing-inline) - ) - - var( - --mod-textfield-border-width, - var(--spectrum-textfield-border-width) - ) - ); + gap: calc(var(--input-spacing) - var(--input-border)); } .popover { diff --git a/packages/date-time-picker/stories/date-time-picker.stories.ts b/packages/date-time-picker/stories/date-time-picker.stories.ts index 3859e82d16b..4a5d46f54e7 100644 --- a/packages/date-time-picker/stories/date-time-picker.stories.ts +++ b/packages/date-time-picker/stories/date-time-picker.stories.ts @@ -10,11 +10,18 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ import { + css, + CSSResult, html, nothing, render, TemplateResult, + unsafeCSS, } from '@spectrum-web-components/base'; +import { + ifDefined, + when, +} from '@spectrum-web-components/base/src/directives.js'; import { TimeGranularity } from '@spectrum-web-components/input-segments/src/types.js'; import { defaultLocale } from '@spectrum-web-components/story-decorator/src/StoryDecorator.js'; @@ -80,12 +87,24 @@ interface SpreadStoryArgs { const renderDateTimePicker = ( title: string, args: StoryArgs = {}, - content: TemplateResult | typeof nothing = nothing + content: TemplateResult | typeof nothing = nothing, + id: string | undefined = undefined, + styles: CSSResult | typeof nothing = nothing ): TemplateResult => { const story = html` + ${when( + styles, + () => html` + + ` + )} +

${title}


@@ -312,3 +331,22 @@ export const customIcon = (args: StoryArgs = {}): TemplateResult => { return renderDateTimePicker('Custom icon', args, content); }; + +export const customWidth = (args: StoryArgs = {}): TemplateResult[] => { + return ['100%', '50%', '350px', 'auto'].map((width, index) => { + const id = `date-time-picker--${index}`; + const styles = css` + sp-date-time-picker#${unsafeCSS(id)} { + inline-size: ${unsafeCSS(width)}; + } + `; + + return renderDateTimePicker( + `Custom width: ${width}`, + args, + undefined, + id, + styles + ); + }); +}; From 747ec46f8139e36d315331fa3a5571e28b8b2700 Mon Sep 17 00:00:00 2001 From: Paulo de Tarso Furtado Machado Date: Wed, 6 Mar 2024 19:59:29 +0000 Subject: [PATCH 33/42] chore: bump packages to 0.41.2 --- packages/date-time-picker/package.json | 12 ++++++------ yarn.lock | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/date-time-picker/package.json b/packages/date-time-picker/package.json index 4d6c18d0d4f..2eb6cea5426 100644 --- a/packages/date-time-picker/package.json +++ b/packages/date-time-picker/package.json @@ -58,15 +58,15 @@ ], "dependencies": { "@spectrum-web-components/calendar": "^0.0.1", - "@spectrum-web-components/field-label": "^0.40.2", - "@spectrum-web-components/icons-workflow": "^0.40.2", + "@spectrum-web-components/field-label": "^0.40.3", + "@spectrum-web-components/icons-workflow": "^0.40.3", "@spectrum-web-components/input-segments": "^0.0.1", - "@spectrum-web-components/overlay": "^0.40.2", - "@spectrum-web-components/picker-button": "^0.40.2", - "@spectrum-web-components/popover": "^0.40.2" + "@spectrum-web-components/overlay": "^0.40.3", + "@spectrum-web-components/picker-button": "^0.40.3", + "@spectrum-web-components/popover": "^0.40.3" }, "devDependencies": { - "@spectrum-web-components/story-decorator": "^0.40.2" + "@spectrum-web-components/story-decorator": "^0.40.3" }, "types": "./src/index.d.ts", "customElements": "custom-elements.json", diff --git a/yarn.lock b/yarn.lock index 1971f2e19be..c8e214d7eca 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5450,7 +5450,7 @@ "@spectrum-web-components/eslint-plugin@file:./linters/eslint": version "0.41.2" -"@spectrum-web-components/field-label@^0.40.2", "@spectrum-web-components/field-label@^0.40.5": +"@spectrum-web-components/field-label@^0.40.3", "@spectrum-web-components/field-label@^0.40.5": version "0.40.5" resolved "https://registry.yarnpkg.com/@spectrum-web-components/field-label/-/field-label-0.40.5.tgz#7ca5e44a24fa613e2f0adfc6f1209667f4515cd5" integrity sha512-lpw1j1+UHNsRAwKIvwsGQ/igfEp40JfteywF0gkgeHHi6XpN2moyZTaKw+p8RiVM6yaZyy8CvGJ+ATcgIjpalA== @@ -5478,7 +5478,7 @@ "@spectrum-web-components/icon" "^0.40.5" "@spectrum-web-components/iconset" "^0.40.5" -"@spectrum-web-components/icons-workflow@^0.40.2", "@spectrum-web-components/icons-workflow@^0.40.5": +"@spectrum-web-components/icons-workflow@^0.40.3", "@spectrum-web-components/icons-workflow@^0.40.5": version "0.40.5" resolved "https://registry.yarnpkg.com/@spectrum-web-components/icons-workflow/-/icons-workflow-0.40.5.tgz#8de8dd715f7cada2a874289c8513aeec622e7058" integrity sha512-gDYhC30iRp8FZrsvnudfsuXhBS6CKW0IM+fjAh4xZ9Hid6fv7GqRkT8rQ13Xkrx5d0ddZplDC1nNh6LMpuKEhw== @@ -5515,7 +5515,7 @@ dependencies: "@spectrum-web-components/base" "^0.40.5" -"@spectrum-web-components/overlay@^0.40.2", "@spectrum-web-components/overlay@^0.40.5": +"@spectrum-web-components/overlay@^0.40.3", "@spectrum-web-components/overlay@^0.40.5": version "0.40.5" resolved "https://registry.yarnpkg.com/@spectrum-web-components/overlay/-/overlay-0.40.5.tgz#5f7555f8463eb72107ec7e7a4ba6099c29af7f62" integrity sha512-G4Lt/nVrjhpTRIX3YikGEK9xiulSJDSwoN+oIeymaGFiKsDJtd12gU2ex231FhipeLrwrDtx4xyc8h/nXUL9NQ== @@ -5528,7 +5528,7 @@ "@spectrum-web-components/shared" "^0.40.5" "@spectrum-web-components/theme" "^0.40.5" -"@spectrum-web-components/picker-button@^0.40.2": +"@spectrum-web-components/picker-button@^0.40.3": version "0.40.5" resolved "https://registry.yarnpkg.com/@spectrum-web-components/picker-button/-/picker-button-0.40.5.tgz#8fdbe43c4d43cc442c105b20dc7de2d0bd12cad5" integrity sha512-IKy7niIVenRbZd+LPX6tWU8OCKM3hOGKEEr+l22yqyLxQEhmjduA8zqcdOiZ0LjQPXLCBO7nJ9E2qZvSugsFDA== @@ -5557,7 +5557,7 @@ "@spectrum-web-components/tooltip" "^0.40.5" "@spectrum-web-components/tray" "^0.40.5" -"@spectrum-web-components/popover@^0.40.2", "@spectrum-web-components/popover@^0.40.5": +"@spectrum-web-components/popover@^0.40.3", "@spectrum-web-components/popover@^0.40.5": version "0.40.5" resolved "https://registry.yarnpkg.com/@spectrum-web-components/popover/-/popover-0.40.5.tgz#383f2583331a3a3f2862180a93277d2c65fefddd" integrity sha512-G34spy2TJUx9R6JHHjVoNG+ldk/RcLOfEEpj1aXKQrWDSzN3tF7zxFm0DOSj7FZ982vI3PpHV5m+7RpmeI7l2w== @@ -5581,7 +5581,7 @@ "@spectrum-web-components/base" "^0.40.5" focus-visible "^5.1.0" -"@spectrum-web-components/story-decorator@^0.40.2": +"@spectrum-web-components/story-decorator@^0.40.3": version "0.40.5" resolved "https://registry.yarnpkg.com/@spectrum-web-components/story-decorator/-/story-decorator-0.40.5.tgz#dcb4ebae188b31be95cffb4689c9cee5524ecf91" integrity sha512-Qbse5BYDtLL+QTTK9hJvObl7tlXecqmW5QqCUNnoiR/6FwfVx6AawLDYBu5jEV3HXteuQgds/gPWEMXfBTyK/g== From e8511446c8c1e4fc42993d94db2656f8366ed5eb Mon Sep 17 00:00:00 2001 From: Paulo de Tarso Furtado Machado Date: Mon, 15 Jan 2024 07:43:52 -0300 Subject: [PATCH 34/42] refactor: add comment about use of `.innerText` --- tools/input-segments/src/InputSegments.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tools/input-segments/src/InputSegments.ts b/tools/input-segments/src/InputSegments.ts index 8aab23d383b..bcb56a1c358 100644 --- a/tools/input-segments/src/InputSegments.ts +++ b/tools/input-segments/src/InputSegments.ts @@ -271,6 +271,21 @@ export class InputSegments extends TextfieldBase { }; /** + * When dealing with tags that have the `contenteditable` attribute, it is recommended that the tag content be + * inserted using the `.innerText` property instead of using string interpolation: + * + * https://lit.dev/docs/templates/expressions/#invalid-locations:~:text=bind%20to%20the%20.innerText + * + * Although this is just a Lit recommendation (as described in the documentation itself, "beware"), we have + * identified that the use of `.innerText` here is mandatory. + * + * We use the `input` event to define the content of the segment, and there are moments when we want to cancel + * the default action of a key typed by the user (for example, when the user types a letter in which only + * numbers are accepted), however, the `input` event action cannot be cancelled with `event.preventDefault()`, + * and because of this, if we try to use string interpolation, it will break the references to the DOM that Lit + * uses to dynamically update the content, but this problem does not occur when we bind to the `.innerText` + * property. + * * TODO: Include/review ARIA attributes for editable segments * TODO: Move `handle` functions call to a cache so that it doesn't cycle on the binding in each render pass */ From 68394479501e87b5a7fbf4a960b28b99475caa23 Mon Sep 17 00:00:00 2001 From: Paulo de Tarso Furtado Machado Date: Mon, 15 Jan 2024 07:49:44 -0300 Subject: [PATCH 35/42] refactor: reduce cognitive complexity --- tools/input-segments/src/InputSegments.ts | 45 +++++++++++++---------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/tools/input-segments/src/InputSegments.ts b/tools/input-segments/src/InputSegments.ts index bcb56a1c358..11ea6d26d11 100644 --- a/tools/input-segments/src/InputSegments.ts +++ b/tools/input-segments/src/InputSegments.ts @@ -789,28 +789,43 @@ export class InputSegments extends TextfieldBase { let minute = this.minuteSegment?.value ?? this.currentDateTime.minute; let second = this.secondSegment?.value ?? this.currentDateTime.second; + let padMaxLength = 2; + switch (segment.type) { - case 'day': + case 'day': { day = segment.value; break; - case 'month': + } + case 'month': { month = segment.value; break; - case 'year': + } + case 'year': { year = segment.value; break; - case 'hour': + } + case 'hour': { hour = segment.value; + + if (this.is12HourClock) { + padMaxLength = 1; + } + break; - case 'minute': + } + case 'minute': { minute = segment.value; break; - case 'second': + } + case 'second': { second = segment.value; break; - case 'dayPeriod': + } + case 'dayPeriod': { hour = (segment.value ?? 0) + 1; + padMaxLength = 0; break; + } } /** @@ -843,6 +858,10 @@ export class InputSegments extends TextfieldBase { return; } + date.setHours(hour); + date.setMinutes(minute); + date.setSeconds(second); + const options: Intl.DateTimeFormatOptions = { month: '2-digit', day: '2-digit', @@ -851,22 +870,10 @@ export class InputSegments extends TextfieldBase { second: '2-digit', }; - date.setHours(hour); - date.setMinutes(minute); - date.setSeconds(second); - const formatted = new DateFormatter(this.locale, options) .formatToParts(date) .find((part) => part.type === segment.type)?.value; - let padMaxLength = 2; - - if (segment.type === 'hour' && this.is12HourClock) { - padMaxLength = 1; - } else if (segment.type === 'dayPeriod') { - padMaxLength = 0; - } - segment.formatted = formatted?.padStart(padMaxLength, '0'); } From e545b9cda29e1745d3c76065fd7fec7193159007 Mon Sep 17 00:00:00 2001 From: Paulo de Tarso Furtado Machado Date: Mon, 15 Jan 2024 14:41:24 -0300 Subject: [PATCH 36/42] refactor: calendar improvements + unit tests --- packages/calendar/src/Calendar.ts | 7 +- packages/calendar/stories/calendar.stories.ts | 38 +++- packages/calendar/test/calendar.test.ts | 199 ++++++++++-------- 3 files changed, 147 insertions(+), 97 deletions(-) diff --git a/packages/calendar/src/Calendar.ts b/packages/calendar/src/Calendar.ts index 0bb82ba32db..cf91b9a8199 100644 --- a/packages/calendar/src/Calendar.ts +++ b/packages/calendar/src/Calendar.ts @@ -89,8 +89,8 @@ export class Calendar extends SpectrumElement { @property({ type: Boolean, reflect: true }) padded = false; - @property({ attribute: false }) - currentDate!: CalendarDate; + @state() + private currentDate!: CalendarDate; @state() private minDate!: CalendarDate; @@ -314,12 +314,13 @@ export class Calendar extends SpectrumElement { class="spectrum-Calendar-tableCell" title=${currentDayTitle} tabindex=${ifDefined(!isOutsideMonth ? '-1' : undefined)} - aria-disabled=${isOutsideMonth || this.disabled} + aria-disabled=${isOutsideMonth || isDisabled} aria-selected=${isSelected} > this.handleDayClick(calendarDate)} > ${this.formatNumber(calendarDate.day)} diff --git a/packages/calendar/stories/calendar.stories.ts b/packages/calendar/stories/calendar.stories.ts index c3fcb0ea919..1baadee86ce 100644 --- a/packages/calendar/stories/calendar.stories.ts +++ b/packages/calendar/stories/calendar.stories.ts @@ -9,7 +9,6 @@ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTA OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -import { CalendarDate } from '@internationalized/date'; import { html, render, TemplateResult } from '@spectrum-web-components/base'; import { defaultLocale } from '@spectrum-web-components/story-decorator/src/StoryDecorator.js'; @@ -28,7 +27,6 @@ export default { }; type ComponentArgs = { - currentDate?: CalendarDate; selectedDate?: Date; min?: Date; max?: Date; @@ -48,13 +46,11 @@ const renderCalendar = ( title: string, args: StoryArgs = {} ): TemplateResult => { - const currentDate = new CalendarDate(2023, 11, 17); const story = html`

${title}


`; @@ -97,25 +93,47 @@ export const selectedDate = (args: StoryArgs = {}): TemplateResult => { }; export const minimumDate = (args: StoryArgs = {}): TemplateResult => { - const minimumDate = new Date(2023, 10, 12); + const today = new Date(); + const lastMonth = new Date( + today.getFullYear(), + today.getMonth() - 1, + today.getDate() + ); + + const formatted = Intl.DateTimeFormat(defaultLocale, { + day: 'numeric', + month: 'long', + year: 'numeric', + }).format(lastMonth); args = { ...args, - min: minimumDate, + min: lastMonth, }; - return renderCalendar(`Minimum Date: ${minimumDate.toDateString()}`, args); + return renderCalendar(`Minimum Date: ${formatted}`, args); }; export const maximumDate = (args: StoryArgs = {}): TemplateResult => { - const maxDate = new Date(2023, 10, 23); + const today = new Date(); + const nextMonth = new Date( + today.getFullYear(), + today.getMonth() + 1, + today.getDate() + ); + + const formatted = Intl.DateTimeFormat(defaultLocale, { + day: 'numeric', + month: 'long', + year: 'numeric', + }).format(nextMonth); args = { ...args, - max: maxDate, + max: nextMonth, }; - return renderCalendar(`Maximum Date: ${maxDate.toDateString()}`, args); + return renderCalendar(`Maximum Date: ${formatted}`, args); }; export const disabled = (args: StoryArgs = {}): TemplateResult => { diff --git a/packages/calendar/test/calendar.test.ts b/packages/calendar/test/calendar.test.ts index 0eb12d5d047..cf9a98c8d93 100644 --- a/packages/calendar/test/calendar.test.ts +++ b/packages/calendar/test/calendar.test.ts @@ -10,14 +10,24 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ import { elementUpdated, expect, fixture, html } from '@open-wc/testing'; +import { defaultLocale } from '@spectrum-web-components/story-decorator/src/StoryDecorator.js'; +import sinon, { spy } from 'sinon'; -import '../sp-calendar.js'; -import { Calendar } from '..'; import { testForLitDevWarnings } from '../../../test/testing-helpers.js'; -import { CalendarDate } from '@internationalized/date'; -import { spy } from 'sinon'; +import { Calendar } from '../src/Calendar.js'; + +import '@spectrum-web-components/calendar/sp-calendar.js'; +import '@spectrum-web-components/theme/sp-theme.js'; + +const CALENDAR_TITLE_SELECTOR = '[data-test-id="calendar-title"]'; +const NEXT_BUTTON_SELECTOR = '[data-test-id="next-btn"]'; +const PREV_BUTTON_SELECTOR = '[data-test-id="prev-btn"]'; +const FIRST_ACTIVE_DAY_SELECTOR = + '[data-test-id="calendar-day"]:not(:is(.is-disabled, .is-outsideMonth))'; describe('Calendar', () => { + const sandbox = sinon.createSandbox(); + testForLitDevWarnings( async () => await fixture( @@ -26,42 +36,40 @@ describe('Calendar', () => { ` ) ); - it('loads default calendar accessibly', async () => { - const el = await fixture( - html` - - ` - ); + async function getCalendar({ + locale = defaultLocale, + disabled = false, + } = {}): Promise { + const wrapped = await fixture(html` + + + + `); + const el = wrapped.querySelector('sp-calendar') as Calendar; await elementUpdated(el); + return el; + } - await expect(el).to.be.accessible(); + beforeEach(() => { + // Use this date as the current date for running the tests + sandbox.stub(Date, 'now').returns(new Date('2022-05-20').valueOf()); }); - it('should render calendar with correct month and year', async () => { - const el = await fixture( - html` - - ` - ); + afterEach(() => { + sandbox.restore(); + }); - await elementUpdated(el); + it('loads default calendar accessibly', async () => { + const el = await getCalendar(); - const monthYear = el.shadowRoot.querySelector( - '[data-test-id="calendar-title"]' - ); + await elementUpdated(el); - expect(monthYear?.innerHTML).contain('May 2022'); + await expect(el).to.be.accessible(); }); it('should render disabled calendar cells', async () => { - const el = await fixture( - html` - - ` - ); + const el = await getCalendar({ disabled: true }); await elementUpdated(el); @@ -72,69 +80,92 @@ describe('Calendar', () => { }); }); - it('should go to next month after "Next" button click', async () => { - const currentMonth = new CalendarDate(2022, 2, 20); // 20 Feb 2022 - const el = await fixture( - html` - - ` - ); - - await elementUpdated(el); - - const nextBtn = el.shadowRoot.querySelector( - '[data-test-id="next-btn"]' - ); - - const monthYear = el.shadowRoot.querySelector( - '[data-test-id="calendar-title"]' - ); - - nextBtn?.click(); - await elementUpdated(el); - - expect(monthYear?.innerHTML).to.contain('March 2022'); - }); - - it('should go to previous month after "Prev" button click', async () => { - const currentMonth = new CalendarDate(2022, 2, 20); // 20 Feb 2022 - const el = await fixture( - html` - - ` - ); - - await elementUpdated(el); - - const prevBtn = el.shadowRoot.querySelector( - '[data-test-id="prev-btn"]' - ); - - const monthYear = el.shadowRoot.querySelector( - '[data-test-id="calendar-title"]' - ); - - prevBtn?.click(); - await elementUpdated(el); - - expect(monthYear?.innerHTML).to.contain('January 2022'); - }); - it('should call "@change" event', async () => { const changeSpy = spy(); - const currentDate = new CalendarDate(2022, 2, 20); - const selectedDay = new CalendarDate(2022, 2, 3); - const el = await fixture( - html` - - ` + const el = await getCalendar(); + + const dayEl = el.shadowRoot.querySelector( + FIRST_ACTIVE_DAY_SELECTOR ); el.addEventListener('change', changeSpy); - el.handleDayClick(selectedDay); + dayEl?.click(); await elementUpdated(el); expect(changeSpy).to.be.calledOnce; }); + + const testCases = [ + { + locale: 'en-US', + current: 'May 2022', + next: 'June 2022', + prev: 'April 2022', + }, + { + locale: 'pt-BR', + current: 'maio de 2022', + next: 'junho de 2022', + prev: 'abril de 2022', + }, + { + locale: 'ko-KR', + current: '2022년 5월', + next: '2022년 6월', + prev: '2022년 4월', + }, + ]; + + testCases.forEach(({ locale, current, next, prev }) => { + describe(`given the locale is "${locale}"`, () => { + let el: Element; + let titleEl: HTMLElement | null | undefined; + + beforeEach(async () => { + el = await getCalendar({ locale }); + + titleEl = el.shadowRoot?.querySelector( + CALENDAR_TITLE_SELECTOR + ); + }); + + it('should render calendar with correct month and year', async () => { + expect( + titleEl?.innerHTML, + `Title of current month when locale is "${locale}"` + ).to.contain(current); + }); + + it('should update the title indicating the next month when clicking the "Next" button', async () => { + const nextBtn = + el.shadowRoot?.querySelector( + NEXT_BUTTON_SELECTOR + ); + + nextBtn?.click(); + await elementUpdated(el); + + expect( + titleEl?.innerHTML, + `Title of next month when locale is "${locale}"` + ).to.contain(next); + }); + + it('should update the title indicating the previous month when clicking the "Previous" button', async () => { + const prevBtn = + el.shadowRoot?.querySelector( + PREV_BUTTON_SELECTOR + ); + + prevBtn?.click(); + await elementUpdated(el); + + expect( + titleEl?.innerHTML, + `Title of previous month when locale is "${locale}"` + ).to.contain(prev); + }); + }); + }); }); From 2060e2ddfa1ecf788307d2d1b4bccdffa4f18f6f Mon Sep 17 00:00:00 2001 From: Paulo de Tarso Furtado Machado Date: Wed, 17 Jan 2024 09:56:58 -0300 Subject: [PATCH 37/42] refactor: invalid picker button styles --- .../date-time-picker/src/DateTimePicker.ts | 1 + .../date-time-picker/src/date-time-picker.css | 36 +++++++++++++++++++ .../test/date-time-picker.test.ts | 5 +-- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/packages/date-time-picker/src/DateTimePicker.ts b/packages/date-time-picker/src/DateTimePicker.ts index 7fa04b7e3c1..eb4174c434a 100644 --- a/packages/date-time-picker/src/DateTimePicker.ts +++ b/packages/date-time-picker/src/DateTimePicker.ts @@ -73,6 +73,7 @@ export class DateTimePicker extends InputSegments { ${this.renderStateIcons()} { testForLitDevWarnings( @@ -24,6 +24,7 @@ describe('DateTimePicker', () => { ` ) ); + it('loads default sp-date-time-picker accessibly', async () => { const el = await fixture( html` From 2b74de8c79cf7ecaa816f72c073df86a508b073b Mon Sep 17 00:00:00 2001 From: Paulo de Tarso Furtado Machado Date: Wed, 6 Mar 2024 20:43:04 +0000 Subject: [PATCH 38/42] chore: bump packages to 0.41.2 --- packages/date-time-picker/package.json | 12 +- yarn.lock | 280 +------------------------ 2 files changed, 14 insertions(+), 278 deletions(-) diff --git a/packages/date-time-picker/package.json b/packages/date-time-picker/package.json index 2eb6cea5426..557ee22e595 100644 --- a/packages/date-time-picker/package.json +++ b/packages/date-time-picker/package.json @@ -58,15 +58,15 @@ ], "dependencies": { "@spectrum-web-components/calendar": "^0.0.1", - "@spectrum-web-components/field-label": "^0.40.3", - "@spectrum-web-components/icons-workflow": "^0.40.3", + "@spectrum-web-components/field-label": "^0.41.2", + "@spectrum-web-components/icons-workflow": "^0.41.2", "@spectrum-web-components/input-segments": "^0.0.1", - "@spectrum-web-components/overlay": "^0.40.3", - "@spectrum-web-components/picker-button": "^0.40.3", - "@spectrum-web-components/popover": "^0.40.3" + "@spectrum-web-components/overlay": "^0.41.2", + "@spectrum-web-components/picker-button": "^0.41.2", + "@spectrum-web-components/popover": "^0.41.2" }, "devDependencies": { - "@spectrum-web-components/story-decorator": "^0.40.3" + "@spectrum-web-components/story-decorator": "^0.41.2" }, "types": "./src/index.d.ts", "customElements": "custom-elements.json", diff --git a/yarn.lock b/yarn.lock index c8e214d7eca..59c94c18411 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2068,13 +2068,6 @@ p-limit "^3.1.0" readable-stream "^4.0.0" -"@floating-ui/core@^1.0.0", "@floating-ui/core@^1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.0.tgz#fa41b87812a16bf123122bf945946bae3fdf7fc1" - integrity sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g== - dependencies: - "@floating-ui/utils" "^0.2.1" - "@floating-ui/core@^1.4.1": version "1.4.1" resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.4.1.tgz#0d633f4b76052668afb932492ac452f7ebe97f17" @@ -2082,6 +2075,13 @@ dependencies: "@floating-ui/utils" "^0.1.1" +"@floating-ui/core@^1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.0.tgz#fa41b87812a16bf123122bf945946bae3fdf7fc1" + integrity sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g== + dependencies: + "@floating-ui/utils" "^0.2.1" + "@floating-ui/dom@^1.5.1": version "1.5.1" resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.5.1.tgz#88b70defd002fe851f17b4a25efb2d3c04d7a8d7" @@ -2090,14 +2090,6 @@ "@floating-ui/core" "^1.4.1" "@floating-ui/utils" "^0.1.1" -"@floating-ui/dom@^1.5.4": - version "1.6.3" - resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.3.tgz#954e46c1dd3ad48e49db9ada7218b0985cee75ef" - integrity sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw== - dependencies: - "@floating-ui/core" "^1.0.0" - "@floating-ui/utils" "^0.2.0" - "@floating-ui/dom@^1.6.1": version "1.6.1" resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.1.tgz#d552e8444f77f2d88534372369b3771dc3a2fa5d" @@ -2118,7 +2110,7 @@ resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.1.1.tgz#1a5b1959a528e374e8037c4396c3e825d6cf4a83" integrity sha512-m0G6wlnhm/AX0H12IOWtK8gASEMffnX08RtKkCgTdHb9JpHKGloI7icFfLg9ZmQeavcvR0PKmzxClyuFPSjKWw== -"@floating-ui/utils@^0.2.0", "@floating-ui/utils@^0.2.1": +"@floating-ui/utils@^0.2.1": version "0.2.1" resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.1.tgz#16308cea045f0fc777b6ff20a9f25474dd8293d2" integrity sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q== @@ -5386,265 +5378,9 @@ resolved "https://registry.yarnpkg.com/@spectrum-css/vars/-/vars-9.0.8.tgz#6af3bcdace903b8461f5fcd4c9aa23e70128a456" integrity sha512-rGfd7jqXOdR69bEjrRP58ynuIeJU0czPfwQvzhtCzg7jKVukV+efNHqrs086sC6xutB3W4TF71K/dZMr3oyTyg== -"@spectrum-web-components/action-button@^0.40.5": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/action-button/-/action-button-0.40.5.tgz#2aea1dbcc8451364f263aaa72305e24dd591673e" - integrity sha512-HTtxmLL904ppWatUU7andrngSVJH7VdCp+Q0VxdVY7VntkiuDAiVk/53mH+I+UcKop1KKw0skzGfv2LprbzJ4g== - dependencies: - "@spectrum-web-components/base" "^0.40.5" - "@spectrum-web-components/button" "^0.40.5" - "@spectrum-web-components/icon" "^0.40.5" - "@spectrum-web-components/icons-ui" "^0.40.5" - "@spectrum-web-components/shared" "^0.40.5" - -"@spectrum-web-components/base@^0.40.5": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/base/-/base-0.40.5.tgz#5e67bab5aa835d5ec3fa141abd14aaf5344ab9ee" - integrity sha512-lGvAkpWzaPuLBdKfFqQW5J4dBTsn8I9OxpfKoEifR9OdNEELJshNVs+9iZY+3AYx3s3Y2WRLnsGrxtWuNg595g== - dependencies: - lit "^2.5.0" - -"@spectrum-web-components/button@^0.40.5": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/button/-/button-0.40.5.tgz#19424d1591390ca1b2255e4f6a3d60eacf4243bb" - integrity sha512-RWneeVltJgS3XWZlWd4cpzY6f8ZTaBRIJEy8RqPXeut90jb+VWZLdF/zhme8JpGK7hEfBcYGst31P06KebaIzw== - dependencies: - "@spectrum-web-components/base" "^0.40.5" - "@spectrum-web-components/clear-button" "^0.40.5" - "@spectrum-web-components/close-button" "^0.40.5" - "@spectrum-web-components/icon" "^0.40.5" - "@spectrum-web-components/icons-ui" "^0.40.5" - "@spectrum-web-components/shared" "^0.40.5" - -"@spectrum-web-components/checkbox@^0.40.5": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/checkbox/-/checkbox-0.40.5.tgz#be926517bc16ddbe2f4cb05eb6486d84af31145f" - integrity sha512-7DE58cSYpuvR8+wIaYw8fFBqUHnKq3H88xrLk+fF73LQvpiC1MAr/itXCuEQmcW/rQdv1hNoOjvH0zJ3zFKvBQ== - dependencies: - "@spectrum-web-components/base" "^0.40.5" - "@spectrum-web-components/icon" "^0.40.5" - "@spectrum-web-components/icons-ui" "^0.40.5" - "@spectrum-web-components/shared" "^0.40.5" - -"@spectrum-web-components/clear-button@^0.40.5": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/clear-button/-/clear-button-0.40.5.tgz#33c8d4ea19fc94bc4b2db6cb1076bd831011f855" - integrity sha512-5BzW9qGNYJj8O3WLaeVBVGt71bK60tpX6NTLQJWV/lcfSENMPEsO1ztziCrxJ5ENz8Y4hG20HTGlqamVfFmt6Q== - dependencies: - "@spectrum-web-components/base" "^0.40.5" - -"@spectrum-web-components/close-button@^0.40.5": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/close-button/-/close-button-0.40.5.tgz#63a32235b7d6cc3c0a0e3ea6c19318d59174a781" - integrity sha512-ooSiUg1C7+GB6y2CoNusLmBor2huBSABG3Exo3BrQM2/viPf2BRUwnRj5ROh37VjdLCu3EUCpjxQ+n8nEcFKAA== - dependencies: - "@spectrum-web-components/base" "^0.40.5" - -"@spectrum-web-components/divider@^0.40.5": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/divider/-/divider-0.40.5.tgz#d7392f7b2c3a8acf53df3546756d0f61b9b58a44" - integrity sha512-CVvo6MMdJrKFwpdOIq6B1OJqDF86zmPkdz36frrhzVrPYZQ/R88CzJrRpz6P56cnQaClM/xVYjPUvl4stekVIA== - dependencies: - "@spectrum-web-components/base" "^0.40.5" - "@spectrum-web-components/eslint-plugin@file:./linters/eslint": version "0.41.2" -"@spectrum-web-components/field-label@^0.40.3", "@spectrum-web-components/field-label@^0.40.5": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/field-label/-/field-label-0.40.5.tgz#7ca5e44a24fa613e2f0adfc6f1209667f4515cd5" - integrity sha512-lpw1j1+UHNsRAwKIvwsGQ/igfEp40JfteywF0gkgeHHi6XpN2moyZTaKw+p8RiVM6yaZyy8CvGJ+ATcgIjpalA== - dependencies: - "@spectrum-web-components/base" "^0.40.5" - "@spectrum-web-components/icon" "^0.40.5" - "@spectrum-web-components/icons-ui" "^0.40.5" - "@spectrum-web-components/reactive-controllers" "^0.40.5" - "@spectrum-web-components/shared" "^0.40.5" - -"@spectrum-web-components/icon@^0.40.5": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/icon/-/icon-0.40.5.tgz#901013ae5f44fe27a19fcf02e0f8a43fe3e0df8a" - integrity sha512-uWzrsZshOfUSy33aep5/ww9ZVoL2asKSUnUAIz6DTH4cmPiT9kNdJXJr0Srru+Xy0DhjGIrpKRCMGLThfYB8Ow== - dependencies: - "@spectrum-web-components/base" "^0.40.5" - "@spectrum-web-components/iconset" "^0.40.5" - -"@spectrum-web-components/icons-ui@^0.40.5": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/icons-ui/-/icons-ui-0.40.5.tgz#27b8e337fb162d090ea65ce7f1917a877bc1d226" - integrity sha512-bHYtTkFwAnz4jHWnmckOgvoEZPtskXfZXcM+us5J6kkOSfss4G6Npjra6+2Ud0OByGWD6KBilXbny3DBYLzAaA== - dependencies: - "@spectrum-web-components/base" "^0.40.5" - "@spectrum-web-components/icon" "^0.40.5" - "@spectrum-web-components/iconset" "^0.40.5" - -"@spectrum-web-components/icons-workflow@^0.40.3", "@spectrum-web-components/icons-workflow@^0.40.5": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/icons-workflow/-/icons-workflow-0.40.5.tgz#8de8dd715f7cada2a874289c8513aeec622e7058" - integrity sha512-gDYhC30iRp8FZrsvnudfsuXhBS6CKW0IM+fjAh4xZ9Hid6fv7GqRkT8rQ13Xkrx5d0ddZplDC1nNh6LMpuKEhw== - dependencies: - "@spectrum-web-components/base" "^0.40.5" - "@spectrum-web-components/icon" "^0.40.5" - -"@spectrum-web-components/iconset@^0.40.5": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/iconset/-/iconset-0.40.5.tgz#1b202059e26d4cbb7607596d3c4f7985494b1f01" - integrity sha512-MY0VFg7yH/j3M7BIIROFR0LGFNj3WJs8VVbV47Req4nQTx6VPOIndnK8uhjFFMleXqEX8w/jVSqZgiD1PQ6w/w== - dependencies: - "@spectrum-web-components/base" "^0.40.5" - -"@spectrum-web-components/menu@^0.40.5": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/menu/-/menu-0.40.5.tgz#b5dd794a7e2dfa24801fd4b9a0b76ef2cfe3ef3b" - integrity sha512-bh5B2Uuqv4TbprH22nrfPLbFf3Hkk511n15gcCrN/YH7T0O0W8s3QyZONOKS/cd0qdmUUR3itrRgCHS7JLPL8g== - dependencies: - "@lit-labs/observers" "^2.0.0" - "@spectrum-web-components/action-button" "^0.40.5" - "@spectrum-web-components/base" "^0.40.5" - "@spectrum-web-components/divider" "^0.40.5" - "@spectrum-web-components/icon" "^0.40.5" - "@spectrum-web-components/icons-ui" "^0.40.5" - "@spectrum-web-components/overlay" "^0.40.5" - "@spectrum-web-components/popover" "^0.40.5" - "@spectrum-web-components/shared" "^0.40.5" - -"@spectrum-web-components/modal@^0.40.5": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/modal/-/modal-0.40.5.tgz#03344c377e1307b72ffaf68ec3da727e24772485" - integrity sha512-1AC1tqXlZsvlJ/t0a/q0+3r9GVDfjk7cGmt3D2Pa+IOQ1V+Nt/IKNVzsIMLDlkWQ7skGBVNHq/zTfoDto2R5lg== - dependencies: - "@spectrum-web-components/base" "^0.40.5" - -"@spectrum-web-components/overlay@^0.40.3", "@spectrum-web-components/overlay@^0.40.5": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/overlay/-/overlay-0.40.5.tgz#5f7555f8463eb72107ec7e7a4ba6099c29af7f62" - integrity sha512-G4Lt/nVrjhpTRIX3YikGEK9xiulSJDSwoN+oIeymaGFiKsDJtd12gU2ex231FhipeLrwrDtx4xyc8h/nXUL9NQ== - dependencies: - "@floating-ui/dom" "^1.5.4" - "@floating-ui/utils" "^0.2.1" - "@spectrum-web-components/action-button" "^0.40.5" - "@spectrum-web-components/base" "^0.40.5" - "@spectrum-web-components/reactive-controllers" "^0.40.5" - "@spectrum-web-components/shared" "^0.40.5" - "@spectrum-web-components/theme" "^0.40.5" - -"@spectrum-web-components/picker-button@^0.40.3": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/picker-button/-/picker-button-0.40.5.tgz#8fdbe43c4d43cc442c105b20dc7de2d0bd12cad5" - integrity sha512-IKy7niIVenRbZd+LPX6tWU8OCKM3hOGKEEr+l22yqyLxQEhmjduA8zqcdOiZ0LjQPXLCBO7nJ9E2qZvSugsFDA== - dependencies: - "@spectrum-web-components/base" "^0.40.5" - "@spectrum-web-components/button" "^0.40.5" - "@spectrum-web-components/icon" "^0.40.5" - "@spectrum-web-components/icons-ui" "^0.40.5" - "@spectrum-web-components/shared" "^0.40.5" - -"@spectrum-web-components/picker@^0.40.5": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/picker/-/picker-0.40.5.tgz#d84c00607ab43df581c9a2afd10908fa513e6906" - integrity sha512-UlqEXpfDSyJQgez5rMNexmjE31Rreu3fVOKw+FV+6Wmj9Udm18dVXZt9EBEe+49bPy8BOnAoSKkjj14Z9CaPWw== - dependencies: - "@spectrum-web-components/base" "^0.40.5" - "@spectrum-web-components/button" "^0.40.5" - "@spectrum-web-components/icon" "^0.40.5" - "@spectrum-web-components/icons-ui" "^0.40.5" - "@spectrum-web-components/icons-workflow" "^0.40.5" - "@spectrum-web-components/menu" "^0.40.5" - "@spectrum-web-components/overlay" "^0.40.5" - "@spectrum-web-components/popover" "^0.40.5" - "@spectrum-web-components/reactive-controllers" "^0.40.5" - "@spectrum-web-components/shared" "^0.40.5" - "@spectrum-web-components/tooltip" "^0.40.5" - "@spectrum-web-components/tray" "^0.40.5" - -"@spectrum-web-components/popover@^0.40.3", "@spectrum-web-components/popover@^0.40.5": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/popover/-/popover-0.40.5.tgz#383f2583331a3a3f2862180a93277d2c65fefddd" - integrity sha512-G34spy2TJUx9R6JHHjVoNG+ldk/RcLOfEEpj1aXKQrWDSzN3tF7zxFm0DOSj7FZ982vI3PpHV5m+7RpmeI7l2w== - dependencies: - "@spectrum-web-components/base" "^0.40.5" - "@spectrum-web-components/overlay" "^0.40.5" - -"@spectrum-web-components/reactive-controllers@^0.40.5": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/reactive-controllers/-/reactive-controllers-0.40.5.tgz#2120977080c115893d7bb2ab258d5a33f14705c3" - integrity sha512-x2wPDhhmMw4Zoq0W7Jd6ECUnKwT1WTjDIRPsulArbLMbjJCMc0YTshAJibIMBVFxP9H06OVdALY/3HbwIKQKuQ== - dependencies: - lit "^2.5.0" - -"@spectrum-web-components/shared@^0.40.5": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/shared/-/shared-0.40.5.tgz#d02311beed2b058f9d0930d7c2e4d2db58d6c09b" - integrity sha512-JyeBukaNmaacvl8Q0ezdbFRzBm/o/2uHmF7kOmWjElpe1KGH6RQ7JgRP9eiUW4ofMYKTOu5F7X5qqeTdvG9Z3g== - dependencies: - "@lit-labs/observers" "^2.0.0" - "@spectrum-web-components/base" "^0.40.5" - focus-visible "^5.1.0" - -"@spectrum-web-components/story-decorator@^0.40.3": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/story-decorator/-/story-decorator-0.40.5.tgz#dcb4ebae188b31be95cffb4689c9cee5524ecf91" - integrity sha512-Qbse5BYDtLL+QTTK9hJvObl7tlXecqmW5QqCUNnoiR/6FwfVx6AawLDYBu5jEV3HXteuQgds/gPWEMXfBTyK/g== - dependencies: - "@spectrum-web-components/base" "^0.40.5" - "@spectrum-web-components/field-label" "^0.40.5" - "@spectrum-web-components/menu" "^0.40.5" - "@spectrum-web-components/overlay" "^0.40.5" - "@spectrum-web-components/picker" "^0.40.5" - "@spectrum-web-components/reactive-controllers" "^0.40.5" - "@spectrum-web-components/switch" "^0.40.5" - "@spectrum-web-components/theme" "^0.40.5" - -"@spectrum-web-components/styles@^0.40.5": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/styles/-/styles-0.40.5.tgz#1344c5eac02b229e29f882536fb4d29e3eabc1fb" - integrity sha512-rhYV8Ql8QV67+EDLEW9aj8x8uxV/zExuV4sUuFsGg00p/cKwsDNIMKIYI3IxPWa98N4QVv1SGDdMwbCzv4559g== - dependencies: - "@spectrum-web-components/base" "^0.40.5" - -"@spectrum-web-components/switch@^0.40.5": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/switch/-/switch-0.40.5.tgz#b9e0ee2c768017f0ee3a3cc643103dc72c54a382" - integrity sha512-ZMhnjTnF/u9cdGpN6ZwpLGQlGzCTguHsWFc41aPMudNxuTM11Ulva6a2tVJCqC72rFPGdikONCX/92WzRpz8Wg== - dependencies: - "@spectrum-web-components/base" "^0.40.5" - "@spectrum-web-components/checkbox" "^0.40.5" - -"@spectrum-web-components/theme@^0.40.5": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/theme/-/theme-0.40.5.tgz#e3a27bc1d1d94121ba7e81c930342dd351adb22a" - integrity sha512-tTBNvqwN0QlN+88qx3cZgRrSK6V6YUFdxhrv3WovrYMaF+94ZSGQufBfoLecWzpmv/W+fFXtQk0JkRQXuwpqww== - dependencies: - "@spectrum-web-components/base" "^0.40.5" - "@spectrum-web-components/styles" "^0.40.5" - -"@spectrum-web-components/tooltip@^0.40.5": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/tooltip/-/tooltip-0.40.5.tgz#7a446d09e986234f5898f6f25ab4867a4cab7f8a" - integrity sha512-Cs520zVPZ3jnrQz2lhDRkz9/jQDTyHn99ur7YEsAlK3AqER9u1kP9JA80D43z63BiYqXfIs38yb5Lcaq3ubYpg== - dependencies: - "@spectrum-web-components/base" "^0.40.5" - "@spectrum-web-components/overlay" "^0.40.5" - "@spectrum-web-components/shared" "^0.40.5" - -"@spectrum-web-components/tray@^0.40.5": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/tray/-/tray-0.40.5.tgz#7322c2db8b21c35b7eb7cc859a56b54d1e2c290e" - integrity sha512-RJ5qE4Ro4/7nXKxDO4rbOds8YeeOpXh+QFE5ngR3Z3vcDTxm/vGOvXnmI7iI6460+80OHF6npUz+5JeWEuq6Eg== - dependencies: - "@spectrum-web-components/base" "^0.40.5" - "@spectrum-web-components/modal" "^0.40.5" - "@spectrum-web-components/reactive-controllers" "^0.40.5" - "@spectrum-web-components/shared" "^0.40.5" - "@spectrum-web-components/underlay" "^0.40.5" - -"@spectrum-web-components/underlay@^0.40.5": - version "0.40.5" - resolved "https://registry.yarnpkg.com/@spectrum-web-components/underlay/-/underlay-0.40.5.tgz#36e806bcceced5a1e7c444d6be63f46581752b62" - integrity sha512-rJcNt9aSmjkH1TB4Mk++MQmTNxoy1mtx+XoIYx7omxKI6MT2mjXWU8ICyxIpxG6CZu3+ODtNatZG/UvtLxeSVQ== - dependencies: - "@spectrum-web-components/base" "^0.40.5" - "@storybook/addon-a11y@^7.5.0": version "7.6.17" resolved "https://registry.yarnpkg.com/@storybook/addon-a11y/-/addon-a11y-7.6.17.tgz#77209c23b6908d52dc470a3318d76a0ffe9d47cb" From c742b9aa1eeb5e055bb65ea9828af0dd40bf63f2 Mon Sep 17 00:00:00 2001 From: Mizga Ionut-Alexandru Date: Wed, 17 Jul 2024 16:06:20 +0300 Subject: [PATCH 39/42] refactor: small code improvements --- packages/calendar/src/Calendar.ts | 3 ++- .../date-time-picker/src/DateTimePicker.ts | 1 - tools/input-segments/src/InputSegments.ts | 22 +++++++------------ 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/packages/calendar/src/Calendar.ts b/packages/calendar/src/Calendar.ts index cf91b9a8199..cc48871e492 100644 --- a/packages/calendar/src/Calendar.ts +++ b/packages/calendar/src/Calendar.ts @@ -365,8 +365,9 @@ export class Calendar extends SpectrumElement { * defined location (Sunday, Monday, etc.) */ private setWeekdays(): void { + const weekStart = startOfWeek(this.currentDate, this.locale); + this.weekdays = [...new Array(daysInWeek).keys()].map((dayIndex) => { - const weekStart = startOfWeek(this.currentDate, this.locale); const date = weekStart.add({ days: dayIndex }); return { diff --git a/packages/date-time-picker/src/DateTimePicker.ts b/packages/date-time-picker/src/DateTimePicker.ts index eb4174c434a..1295d2794ee 100644 --- a/packages/date-time-picker/src/DateTimePicker.ts +++ b/packages/date-time-picker/src/DateTimePicker.ts @@ -24,7 +24,6 @@ import styles from './date-time-picker.css.js'; // TODO: Load dependencies lazily when possible import '@spectrum-web-components/calendar/sp-calendar.js'; -import '@spectrum-web-components/field-label/sp-field-label.js'; import '@spectrum-web-components/icons-workflow/icons/sp-icon-calendar.js'; import '@spectrum-web-components/overlay/sp-overlay.js'; import '@spectrum-web-components/picker-button/sp-picker-button.js'; diff --git a/tools/input-segments/src/InputSegments.ts b/tools/input-segments/src/InputSegments.ts index 11ea6d26d11..b033bbb54b7 100644 --- a/tools/input-segments/src/InputSegments.ts +++ b/tools/input-segments/src/InputSegments.ts @@ -404,17 +404,17 @@ export class InputSegments extends TextfieldBase { return; } + const typedValue = this.numberParser.parse(data); + if ( - data === ' ' || // Space is considered “valid number” by the following validations... 🤦🏻‍♂️ !this.numberParser.isValidPartialNumber(data) || - isNaN(Number(data)) + isNaN(typedValue) ) { this.updateContent(segment, event); return; } const isDate = dateSegmentTypes.includes(segment.type); - const typedValue = this.numberParser.parse(data); const isAmPmHour = this.is12HourClock && segment.type === 'hour'; segment.value = isAmPmHour @@ -776,8 +776,10 @@ export class InputSegments extends TextfieldBase { return; } - // We always use the first day of a month unless a specific day is specified - let day = this.daySegment?.value ?? 1; + // We always use the first day of the month unless a specific day is specified + let day = + this.daySegment?.value ?? + getMinimumDayInMonth(this.currentDateTime); // We always use the first month of the year unless a specific month is specified let month = @@ -862,15 +864,7 @@ export class InputSegments extends TextfieldBase { date.setMinutes(minute); date.setSeconds(second); - const options: Intl.DateTimeFormatOptions = { - month: '2-digit', - day: '2-digit', - hour: 'numeric', - minute: '2-digit', - second: '2-digit', - }; - - const formatted = new DateFormatter(this.locale, options) + const formatted = this.formatter .formatToParts(date) .find((part) => part.type === segment.type)?.value; From 597ad3d6871c877627a681543f06f4b768290a2d Mon Sep 17 00:00:00 2001 From: Mizga Ionut-Alexandru Date: Wed, 31 Jul 2024 09:56:06 +0300 Subject: [PATCH 40/42] chore: fix test imports --- packages/calendar/test/calendar.test.ts | 6 +++--- packages/date-time-picker/test/date-time-picker.test.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/calendar/test/calendar.test.ts b/packages/calendar/test/calendar.test.ts index cf9a98c8d93..6b7e1b3b337 100644 --- a/packages/calendar/test/calendar.test.ts +++ b/packages/calendar/test/calendar.test.ts @@ -10,15 +10,15 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ import { elementUpdated, expect, fixture, html } from '@open-wc/testing'; -import { defaultLocale } from '@spectrum-web-components/story-decorator/src/StoryDecorator.js'; import sinon, { spy } from 'sinon'; import { testForLitDevWarnings } from '../../../test/testing-helpers.js'; -import { Calendar } from '../src/Calendar.js'; +import { Calendar } from '@spectrum-web-components/calendar'; import '@spectrum-web-components/calendar/sp-calendar.js'; import '@spectrum-web-components/theme/sp-theme.js'; +const DEFAULT_LOCALE = 'en-US'; const CALENDAR_TITLE_SELECTOR = '[data-test-id="calendar-title"]'; const NEXT_BUTTON_SELECTOR = '[data-test-id="next-btn"]'; const PREV_BUTTON_SELECTOR = '[data-test-id="prev-btn"]'; @@ -38,7 +38,7 @@ describe('Calendar', () => { ); async function getCalendar({ - locale = defaultLocale, + locale = DEFAULT_LOCALE, disabled = false, } = {}): Promise { const wrapped = await fixture(html` diff --git a/packages/date-time-picker/test/date-time-picker.test.ts b/packages/date-time-picker/test/date-time-picker.test.ts index 0d6f2f4f889..2fd57e6b359 100644 --- a/packages/date-time-picker/test/date-time-picker.test.ts +++ b/packages/date-time-picker/test/date-time-picker.test.ts @@ -13,7 +13,7 @@ governing permissions and limitations under the License. import { elementUpdated, expect, fixture, html } from '@open-wc/testing'; import { testForLitDevWarnings } from '../../../test/testing-helpers.js'; -import { DateTimePicker } from '../src/DateTimePicker.js'; +import { DateTimePicker } from '@spectrum-web-components/date-time-picker'; describe('DateTimePicker', () => { testForLitDevWarnings( From 07a5cba6726f993d5ddc38a9c30e9c9e3e94ebc7 Mon Sep 17 00:00:00 2001 From: Mizga Ionut-Alexandru Date: Wed, 31 Jul 2024 10:21:05 +0300 Subject: [PATCH 41/42] chore: update golden img hash --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6278e07e253..4886a3cdac7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,7 +10,7 @@ executors: parameters: current_golden_images_hash: type: string - default: c70f3ed57c4e3536313872fd3d23510caa801a44 + default: 597ad3d6871c877627a681543f06f4b768290a2d wireit_cache_name: type: string default: wireit From 600c8182e2d619fda092e2cffef30a7113a7a638 Mon Sep 17 00:00:00 2001 From: Mizga Ionut-Alexandru Date: Wed, 31 Jul 2024 14:26:14 +0300 Subject: [PATCH 42/42] chore: update golden img hash --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4886a3cdac7..bb45cbc278d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,7 +10,7 @@ executors: parameters: current_golden_images_hash: type: string - default: 597ad3d6871c877627a681543f06f4b768290a2d + default: 07a5cba6726f993d5ddc38a9c30e9c9e3e94ebc7 wireit_cache_name: type: string default: wireit