From 5863a155262d6ba6898f82bff49aed55a6eae4f4 Mon Sep 17 00:00:00 2001 From: Westbrook Johnson Date: Fri, 11 Nov 2022 09:00:28 -0500 Subject: [PATCH] fix: ensure reactivity of resolved language --- packages/number-field/src/NumberField.ts | 21 +++++++++++++++--- packages/slider/src/SliderHandle.ts | 16 ++++++++++---- packages/slider/stories/slider.stories.ts | 22 +++++++++++++++++++ .../src/LanguageResolution.ts | 10 ++++++++- 4 files changed, 61 insertions(+), 8 deletions(-) diff --git a/packages/number-field/src/NumberField.ts b/packages/number-field/src/NumberField.ts index 21b6ca0980..4660b3394b 100644 --- a/packages/number-field/src/NumberField.ts +++ b/packages/number-field/src/NumberField.ts @@ -20,7 +20,10 @@ import { property, query, } from '@spectrum-web-components/base/src/decorators.js'; -import { LanguageResolutionController } from '@spectrum-web-components/reactive-controllers/src/LanguageResolution.js'; +import { + LanguageResolutionController, + languageResolverUpdatedSymbol, +} from '@spectrum-web-components/reactive-controllers/src/LanguageResolution.js'; import { streamingListener } from '@spectrum-web-components/base/src/streaming-listener.js'; import { NumberFormatter, NumberParser } from '@internationalized/number'; @@ -162,7 +165,16 @@ export class NumberField extends TextfieldBase { private convertValueToNumber(value: string): number { if (isIPhone() && this.inputElement.inputMode === 'decimal') { - value = value.replace(',', '.'); + const parts = this.numberFormatter.formatToParts(1000.1); + const sourceDecimal = value + .split('') + .find((char) => char === ',' || char === '.'); + const replacementDecimal = parts.find( + (part) => part.type === 'decimal' + )?.value; + if (sourceDecimal && replacementDecimal) { + value = value.replace(sourceDecimal, replacementDecimal); + } } return this.numberParser.parse(value); } @@ -580,8 +592,11 @@ export class NumberField extends TextfieldBase { super.update(changes); } - public override willUpdate(): void { + public override willUpdate(changes: PropertyValues): void { this.multiline = false; + if (changes.has(languageResolverUpdatedSymbol)) { + this.clearNumberFormatterCache(); + } } protected override firstUpdated(changes: PropertyValues): void { diff --git a/packages/slider/src/SliderHandle.ts b/packages/slider/src/SliderHandle.ts index 8c0ac9902a..5c81861257 100644 --- a/packages/slider/src/SliderHandle.ts +++ b/packages/slider/src/SliderHandle.ts @@ -13,7 +13,10 @@ governing permissions and limitations under the License. import { PropertyValues } from '@spectrum-web-components/base'; import { property } from '@spectrum-web-components/base/src/decorators.js'; import { Focusable } from '@spectrum-web-components/shared/src/focusable.js'; -import { LanguageResolutionController } from '@spectrum-web-components/reactive-controllers/src/LanguageResolution.js'; +import { + LanguageResolutionController, + languageResolverUpdatedSymbol, +} from '@spectrum-web-components/reactive-controllers/src/LanguageResolution.js'; import { NumberFormatOptions, NumberFormatter, @@ -138,8 +141,11 @@ export class SliderHandle extends Focusable { } } } - - if (changes.has('formatOptions') || changes.has('resolvedLanguage')) { + + if ( + changes.has('formatOptions') || + changes.has(languageResolverUpdatedSymbol) + ) { delete this._numberFormatCache; } if (changes.has('value')) { @@ -154,7 +160,9 @@ export class SliderHandle extends Focusable { super.update(changes); } - protected override firstUpdated(changedProperties: PropertyValues): void { + protected override firstUpdated( + changedProperties: PropertyValues + ): void { super.firstUpdated(changedProperties); this.dispatchEvent(new CustomEvent('sp-slider-handle-ready')); } diff --git a/packages/slider/stories/slider.stories.ts b/packages/slider/stories/slider.stories.ts index 8c493bdf3e..22fda61dcc 100644 --- a/packages/slider/stories/slider.stories.ts +++ b/packages/slider/stories/slider.stories.ts @@ -244,6 +244,28 @@ const editableDecorator = (story: () => TemplateResult): TemplateResult => { `; }; +export const max20 = (args: StoryArgs = {}): TemplateResult => { + return html` +
+ + Max 20 + +
+ `; +}; +max20.swc_vrt = { + skip: true, +}; + export const editable = (args: StoryArgs = {}): TemplateResult => { return html`
diff --git a/tools/reactive-controllers/src/LanguageResolution.ts b/tools/reactive-controllers/src/LanguageResolution.ts index dc8d437d68..7dd7fe446b 100644 --- a/tools/reactive-controllers/src/LanguageResolution.ts +++ b/tools/reactive-controllers/src/LanguageResolution.ts @@ -13,6 +13,10 @@ governing permissions and limitations under the License. import type { ReactiveController, ReactiveElement } from 'lit'; import { ProvideLang } from '@spectrum-web-components/theme'; +export const languageResolverUpdatedSymbol = Symbol( + 'language resolver updated' +); + export class LanguageResolutionController implements ReactiveController { private host: ReactiveElement; language = document.documentElement.lang || navigator.language; @@ -39,9 +43,13 @@ export class LanguageResolutionController implements ReactiveController { composed: true, detail: { callback: (lang: string, unsubscribe: () => void) => { + const previous = this.language; this.language = lang; this.unsubscribe = unsubscribe; - this.host.requestUpdate(); + this.host.requestUpdate( + languageResolverUpdatedSymbol, + previous + ); }, }, cancelable: true,