diff --git a/addon/components/o-s-s/email-input.hbs b/addon/components/o-s-s/email-input.hbs index 3f14d5e16..7aab2bd55 100644 --- a/addon/components/o-s-s/email-input.hbs +++ b/addon/components/o-s-s/email-input.hbs @@ -1,3 +1,7 @@ + @value={{@value}} + @placeholder={{this.placeholder}} + @errorMessage={{this.errorMessage}} + @onChange={{this.onChangeHandler}} + ...attributes +/> diff --git a/addon/components/o-s-s/email-input.ts b/addon/components/o-s-s/email-input.ts index 34727f43c..287b5c112 100644 --- a/addon/components/o-s-s/email-input.ts +++ b/addon/components/o-s-s/email-input.ts @@ -44,17 +44,24 @@ export default class OSSEmailInput extends Component { return this.args.errorMessage || this.regexError || null; } + get onChangeHandler() { + return (value: string | null) => this.validateInput(value); + } + @action - validateInput(): void { - this.regexError = ''; - this.args.onChange?.(this.args.value ? this.args.value.toLowerCase() : this.args.value); + validateInput(value: string | null): void { + const normalizedValue = value ? value.toLowerCase() : value; + + this.args.onChange?.(normalizedValue); - if (!this._runValidation || !this.args.value) { + if (!this._runValidation || !value) { + this.regexError = ''; this.args.validates?.(true); - } else if (!EMAIL_REGEXP.test(this.args.value)) { + } else if (!EMAIL_REGEXP.test(value)) { this.regexError = this.intl.t('oss-components.email-input.regex_error'); this.args.validates?.(false); } else { + this.regexError = ''; this.args.validates?.(true); } } diff --git a/addon/components/o-s-s/input-container.hbs b/addon/components/o-s-s/input-container.hbs index a8aeb7259..e7cc2bb98 100644 --- a/addon/components/o-s-s/input-container.hbs +++ b/addon/components/o-s-s/input-container.hbs @@ -15,14 +15,15 @@ {{yield to="input"}} {{else}} - {{/if}} diff --git a/addon/components/o-s-s/input-container.ts b/addon/components/o-s-s/input-container.ts index 7e42cc3e5..7228cc0ad 100644 --- a/addon/components/o-s-s/input-container.ts +++ b/addon/components/o-s-s/input-container.ts @@ -16,7 +16,7 @@ interface OSSInputContainerArgs { placeholder?: string; type?: string; autocomplete?: 'on' | 'off'; - onChange?(value: string): void; + onChange?(value: string | null): void; } export const AutocompleteValues = ['on', 'off']; @@ -51,9 +51,15 @@ export default class OSSInputContainer extends Component } @action - _onChange(value: string): void { - if (this.args.onChange) { - this.args.onChange(value); + onInput(event: Event): void { + const input = event.target as HTMLInputElement; + this.args.onChange?.(input.value); + } + + @action + onKeyUp(event: KeyboardEvent): void { + if (event.key === 'Backspace' && this.args.value === null) { + this.args.onChange?.(null); } } diff --git a/addon/components/o-s-s/number-input.hbs b/addon/components/o-s-s/number-input.hbs index 256f17997..5d48b816c 100644 --- a/addon/components/o-s-s/number-input.hbs +++ b/addon/components/o-s-s/number-input.hbs @@ -2,9 +2,9 @@ {{! template-lint-disable no-triple-curlies}} - - + \ No newline at end of file diff --git a/addon/components/o-s-s/number-input.ts b/addon/components/o-s-s/number-input.ts index 9bce0d59c..f0c55f3b2 100644 --- a/addon/components/o-s-s/number-input.ts +++ b/addon/components/o-s-s/number-input.ts @@ -74,7 +74,11 @@ export default class OSSNumberInput extends Component { } @action - checkUserInput(): void { + checkUserInput(value?: string): void { + if (value !== undefined) { + this.localValue = Number(value); + } + if (this.args.min !== undefined && Number(this.localValue) < this.args.min) { this.localValue = this.args.min; } diff --git a/addon/components/o-s-s/slider.hbs b/addon/components/o-s-s/slider.hbs index 6b0d4f328..376cbd995 100644 --- a/addon/components/o-s-s/slider.hbs +++ b/addon/components/o-s-s/slider.hbs @@ -41,6 +41,7 @@ @disabled={{@disabled}} @autocomplete={{this.sliderOptions.autocomplete}} {{on "input" this.onNumberInput}} + {{did-insert this.initializeNumberInput}} /> {{else}} {{/if}} diff --git a/addon/components/o-s-s/slider.ts b/addon/components/o-s-s/slider.ts index 7b9ecf7eb..dc316be41 100644 --- a/addon/components/o-s-s/slider.ts +++ b/addon/components/o-s-s/slider.ts @@ -34,6 +34,8 @@ export default class SliderComponent extends Component { @tracked displayTooltip: boolean = false; @tracked inputRangeElement: HTMLElement | null = null; @tracked tooltipElement: HTMLElement | null = null; + @tracked numberInputElement: HTMLElement | null = null; + @tracked actualInputValue: string | null = null; get defaultValue(): string { return this.args.defaultValue ?? DEFAULT_VALUE; @@ -70,7 +72,15 @@ export default class SliderComponent extends Component { } get activeBackgroundWidth(): ReturnType { - const percentage = Math.round(this.getPercentage(this.args.value ?? '0') * 100); + let valueForBackground: string; + + if (this.actualInputValue !== null) { + valueForBackground = this.actualInputValue; + } else { + valueForBackground = this.currentRangeValue; + } + + const percentage = Math.round(this.getPercentage(valueForBackground) * 100); return htmlSafe(`--range-percentage: ${percentage}%`); } @@ -94,6 +104,7 @@ export default class SliderComponent extends Component { @action onNumberInput(event: InputEvent): void { const value = (event.target as HTMLInputElement).value; + this.actualInputValue = value; this.checkUserInput(value); } @@ -117,22 +128,25 @@ export default class SliderComponent extends Component { this.tooltipElement = element; } + @action + initializeNumberInput(element: HTMLElement): void { + this.numberInputElement = element; + } + private getPercentage(value: string): number { let correction = 0; const convertedValue = parseFloat(isBlank(value) ? '0' : value); + const min = this.args.min ?? 0; + const max = this.args.max ?? 100; if (this.args.step) { correction = convertedValue % this.args.step >= this.args.step / 2 ? this.args.step - (convertedValue % this.args.step) - : -value % this.args.step; + : -convertedValue % this.args.step; } - return Math.min( - Math.max(convertedValue + correction - this.sliderOptions.min, 0) / - (this.sliderOptions.max - this.sliderOptions.min), - 1 - ); + return Math.min(Math.max(convertedValue + correction - min, 0) / (max - min), 1); } private checkUserInput(value: string | null): void { diff --git a/addon/components/o-s-s/url-input.hbs b/addon/components/o-s-s/url-input.hbs index 22610a253..e98cc7246 100644 --- a/addon/components/o-s-s/url-input.hbs +++ b/addon/components/o-s-s/url-input.hbs @@ -1,3 +1,10 @@ - + \ No newline at end of file diff --git a/tests/integration/components/o-s-s/slider-test.ts b/tests/integration/components/o-s-s/slider-test.ts index 8bf45a5a0..e4ebe30ec 100644 --- a/tests/integration/components/o-s-s/slider-test.ts +++ b/tests/integration/components/o-s-s/slider-test.ts @@ -229,13 +229,14 @@ module('Integration | Component | o-s-s/slider', function (hooks) { assert.strictEqual(element.style.getPropertyValue('--range-percentage'), '0%'); }); - test('it renders the slider with a maximum value when @min is provided', async function (assert) { + test('it renders the slider with a maximum value when @max is provided', async function (assert) { this.max = 1000; + this.inputOptions = { max: this.max - 1 }; await render( - hbs`` + hbs`` ); - await fillIn('.oss-slider__number-input input', '1000'); + await fillIn('.oss-slider__number-input input', this.max); const element = this.element.querySelector('.oss-slider__range'); assert.strictEqual(element.style.getPropertyValue('--range-percentage'), '100%'); }); diff --git a/tests/integration/components/o-s-s/url-input-test.ts b/tests/integration/components/o-s-s/url-input-test.ts index cc2183fce..50a535f45 100644 --- a/tests/integration/components/o-s-s/url-input-test.ts +++ b/tests/integration/components/o-s-s/url-input-test.ts @@ -28,7 +28,7 @@ module('Integration | Component | o-s-s/url-input', function (hooks) { @validationRegex={{this.subdomainRegex}} />`); await fillIn('input', 'fakedomai'); await typeIn('input', 'n'); - assert.true(this.onChange.calledOnceWithExactly('fakedomain', true)); + assert.true(this.onChange.lastCall.calledWith('fakedomain', true)); }); module("When the text doesn't match the Regex", () => {