From d100d6b3a766850be422f1e89ef0c9846371c096 Mon Sep 17 00:00:00 2001 From: Nikita Barsukov Date: Thu, 26 Dec 2024 16:06:10 +0300 Subject: [PATCH 1/4] refactor(kit): new version of `InputNumber` has `[step]` feature --- projects/cdk/constants/allow-signal-writes.ts | 5 + projects/cdk/constants/index.ts | 1 + .../utils/miscellaneous/directive-binding.ts | 18 +-- .../components/input-number/index.html | 10 ++ .../modules/components/input-number/index.ts | 1 + .../input-number/input-number.component.ts | 105 +++++++++++------- .../input-number/input-number.options.ts | 10 ++ .../input-number/input-number.style.less | 80 +++++++++++++ .../input-number/input-number.template.html | 36 ++++++ 9 files changed, 213 insertions(+), 53 deletions(-) create mode 100644 projects/cdk/constants/allow-signal-writes.ts create mode 100644 projects/kit/components/input-number/input-number.style.less create mode 100644 projects/kit/components/input-number/input-number.template.html diff --git a/projects/cdk/constants/allow-signal-writes.ts b/projects/cdk/constants/allow-signal-writes.ts new file mode 100644 index 000000000000..ba07ee73ea44 --- /dev/null +++ b/projects/cdk/constants/allow-signal-writes.ts @@ -0,0 +1,5 @@ +import type {CreateEffectOptions} from '@angular/core'; +import {VERSION} from '@angular/core'; + +export const TUI_ALLOW_SIGNAL_WRITES: CreateEffectOptions = + parseInt(VERSION.major, 10) >= 19 ? {} : {allowSignalWrites: true}; diff --git a/projects/cdk/constants/index.ts b/projects/cdk/constants/index.ts index 67e3ab384ea1..0dad6fd65324 100644 --- a/projects/cdk/constants/index.ts +++ b/projects/cdk/constants/index.ts @@ -1,3 +1,4 @@ +export * from './allow-signal-writes'; export * from './empty'; export * from './handlers'; export * from './matchers'; diff --git a/projects/cdk/utils/miscellaneous/directive-binding.ts b/projects/cdk/utils/miscellaneous/directive-binding.ts index b6c702b30b4b..c48b64daae7e 100644 --- a/projects/cdk/utils/miscellaneous/directive-binding.ts +++ b/projects/cdk/utils/miscellaneous/directive-binding.ts @@ -1,11 +1,6 @@ -import type { - CreateEffectOptions, - InjectOptions, - ProviderToken, - Signal, - WritableSignal, -} from '@angular/core'; -import {effect, inject, isSignal, signal, VERSION} from '@angular/core'; +import type {InjectOptions, ProviderToken, Signal, WritableSignal} from '@angular/core'; +import {effect, inject, isSignal, signal} from '@angular/core'; +import {TUI_ALLOW_SIGNAL_WRITES} from '@taiga-ui/cdk/constants'; type SignalLikeTypeOf = T extends Signal ? R : T; @@ -24,11 +19,6 @@ export function tuiDirectiveBinding< const result: any = isSignal(initial) ? initial : signal(initial); const directive: any = inject(token, options); const output = directive[`${key.toString()}Change`]; - const angularVersion = parseInt(VERSION.major, 10); - const isAngular19 = angularVersion >= 19; - const effectOptions: CreateEffectOptions = isAngular19 - ? {} - : {allowSignalWrites: true}; // TODO: Figure out why effects are executed all the time and not just when result changes (check with Angular 18) let previous: any; @@ -49,7 +39,7 @@ export function tuiDirectiveBinding< directive.ngOnChanges?.({}); output?.emit?.(value); previous = value; - }, effectOptions); + }, TUI_ALLOW_SIGNAL_WRITES); return result; } diff --git a/projects/demo/src/modules/components/input-number/index.html b/projects/demo/src/modules/components/input-number/index.html index bfa7f99c660b..6d379290c711 100644 --- a/projects/demo/src/modules/components/input-number/index.html +++ b/projects/demo/src/modules/components/input-number/index.html @@ -23,6 +23,7 @@ [postfix]="postfix" [prefix]="prefix" [readOnly]="controlDoc.readonly" + [step]="step" [tuiDisabled]="controlDoc.disabled" [tuiNumberFormat]="{ thousandSeparator: numberFormatDoc.thousandSeparator(), @@ -57,6 +58,15 @@ The greatest value in the range of permitted values + + Step to increase/decrease value with keyboard and buttons on the side + + { - private readonly element = tuiInjectElement(); private readonly isIOS = inject(TUI_IS_IOS); - private readonly options = inject(TUI_INPUT_NUMBER_OPTIONS); private readonly numberFormat = toSignal(inject(TUI_NUMBER_FORMAT), { initialValue: TUI_DEFAULT_NUMBER_FORMAT, }); - private readonly min = signal(this.options.min); - private readonly max = signal(this.options.max); - private readonly prefix = signal(this.options.prefix); - private readonly postfix = signal(this.options.postfix); - private readonly precision = computed(() => Number.isNaN(this.numberFormat().precision) ? 2 : this.numberFormat().precision, ); @@ -75,7 +82,39 @@ export class TuiInputNumber extends TuiControl { return value < 0 ? value > this.max() : value < this.min(); }); - protected textfieldValue = signal(this.element.value || ''); + protected readonly onChangeEffect = effect(() => { + const value = maskitoParseNumber( + this.textfieldValue(), + this.numberFormat().decimalSeparator, + ); + + if (Number.isNaN(value)) { + this.onChange(null); + + return; + } + + if ( + this.isIntermediateState() || + value < this.min() || + value > this.max() || + this.value() === value + ) { + return; + } + + this.onChange(value); + }, TUI_ALLOW_SIGNAL_WRITES); + + protected readonly options = inject(TUI_INPUT_NUMBER_OPTIONS); + protected readonly min = signal(this.options.min); + protected readonly max = signal(this.options.max); + protected readonly step = signal(this.options.step); + protected readonly prefix = signal(this.options.prefix); + protected readonly postfix = signal(this.options.postfix); + protected readonly textfieldOptions = inject(TUI_TEXTFIELD_OPTIONS); + protected readonly element = tuiInjectElement(); + protected readonly textfieldValue = signal(this.element.value || ''); protected readonly inputMode = computed(() => { if (this.isIOS && this.min() < 0) { @@ -132,37 +171,17 @@ export class TuiInputNumber extends TuiControl { this.postfix.set(x); } + // TODO(v5): replace with signal input + @Input('step') + public set stepSetter(x: number) { + this.step.set(x); + } + public override writeValue(value: number | null): void { super.writeValue(value); this.textfieldValue.set(this.formatNumber(value)); } - protected onInput(): void { - const value = this.element.value; - const parsedValue = maskitoParseNumber( - value, - this.numberFormat().decimalSeparator, - ); - - this.textfieldValue.set(value); - - if (Number.isNaN(parsedValue)) { - this.onChange(null); - - return; - } - - if ( - this.isIntermediateState() || - parsedValue < this.min() || - parsedValue > this.max() - ) { - return; - } - - this.onChange(parsedValue); - } - protected onBlur(): void { this.onTouched(); @@ -182,6 +201,14 @@ export class TuiInputNumber extends TuiControl { } } + protected onStep(step: number): void { + this.textfieldValue.set( + this.formatNumber( + tuiClamp((this.value() ?? 0) + step, this.min(), this.max()), + ), + ); + } + private formatNumber(value: number | null): string { if (value === null) { return ''; diff --git a/projects/kit/components/input-number/input-number.options.ts b/projects/kit/components/input-number/input-number.options.ts index 52b54960cc54..89ad00eb55b6 100644 --- a/projects/kit/components/input-number/input-number.options.ts +++ b/projects/kit/components/input-number/input-number.options.ts @@ -6,6 +6,11 @@ export interface TuiInputNumberOptions { readonly min: number; readonly prefix: string; readonly postfix: string; + readonly step: number; + readonly icons: Readonly<{ + down: string; + up: string; + }>; readonly valueTransformer: TuiValueTransformer | null; } @@ -14,6 +19,11 @@ export const TUI_INPUT_NUMBER_DEFAULT_OPTIONS: TuiInputNumberOptions = { max: Number.MAX_SAFE_INTEGER, prefix: '', postfix: '', + step: 0, + icons: { + up: '@tui.plus', + down: '@tui.minus', + }, valueTransformer: null, }; diff --git a/projects/kit/components/input-number/input-number.style.less b/projects/kit/components/input-number/input-number.style.less new file mode 100644 index 000000000000..b61c04215081 --- /dev/null +++ b/projects/kit/components/input-number/input-number.style.less @@ -0,0 +1,80 @@ +/* +TODO: if :has() is supported by all browsers + - use tui-textfield:has([tuiInputNumber]) .t-input-number {...} + - rename .t-input-number-buttons => .t-buttons + */ +.t-input-number { + &-buttons { + position: absolute; + right: 0; + display: flex; + block-size: var(--t-height); + flex-direction: column; + gap: 0.125rem; + border-radius: inherit; + + tui-textfield[data-size='s'] & { + flex-direction: row-reverse; + } + + & > * { + flex: 1 1 0; + border-radius: 0; + + &:first-child { + border-start-end-radius: inherit; + } + + &:last-child { + border-end-end-radius: inherit; + } + + tui-textfield[data-size='s'] & { + &:first-child { + border-start-end-radius: inherit; + border-end-end-radius: inherit; + } + + &:last-child { + border-radius: 0; + } + } + } + } +} + +[tuiInputNumber]._with-buttons { + border-start-end-radius: 0; + border-end-end-radius: 0; +} + +/* +TODO: if :has() is supported by all browsers + - use tui-textfield:has([tuiInputNumber]) {...} + - rename --t-input-number-offset-end => --t-offset-end + */ +tui-textfield { + &[data-size='l'] { + --t-input-number-offset-end: calc( + var(--tui-height-m) // width of step button + + 0.125rem + ); + } + + &[data-size='m'] { + --t-input-number-offset-end: calc(var(--tui-height-s) + 0.125rem); + } + + &[data-size='s'] { + --t-input-number-offset-end: calc(2 * var(--tui-height-s) + 0.25rem); + } +} + +[tuiInputNumber]._with-buttons, +[tuiInputNumber]._with-buttons ~ .t-template { + inline-size: calc(100% - var(--t-input-number-offset-end)); +} + +[tuiInputNumber]._with-buttons ~ .t-content { + margin-inline-end: var(--t-input-number-offset-end); +} diff --git a/projects/kit/components/input-number/input-number.template.html b/projects/kit/components/input-number/input-number.template.html new file mode 100644 index 000000000000..55348afa4cad --- /dev/null +++ b/projects/kit/components/input-number/input-number.template.html @@ -0,0 +1,36 @@ + +
+ + + +
+
From 0e21eece7c1b78ef801561bbc028f47b902c0ae4 Mon Sep 17 00:00:00 2001 From: taiga-family-bot Date: Thu, 26 Dec 2024 15:17:30 +0000 Subject: [PATCH 2/4] chore: icons have changed [bot] --- projects/cdk/constants/used-icons.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/cdk/constants/used-icons.ts b/projects/cdk/constants/used-icons.ts index bf844a986999..cba2ee5f5ebe 100644 --- a/projects/cdk/constants/used-icons.ts +++ b/projects/cdk/constants/used-icons.ts @@ -47,6 +47,7 @@ export const TUI_USED_ICONS = [ '@tui.minus', '@tui.file', '@tui.trash', + '@tui.plus', '@tui.phone', '@tui.heart', '@tui.heart-filled', @@ -55,7 +56,6 @@ export const TUI_USED_ICONS = [ '@tui.rotate-ccw-square', '@tui.arrow-left', '@tui.arrow-right', - '@tui.plus', '@tui.minimize', '@tui.filter', '@tui.layout-grid', From 9427b605e928e0a60293441daf3a0976299fd7f2 Mon Sep 17 00:00:00 2001 From: Nikita Barsukov Date: Fri, 27 Dec 2024 11:02:10 +0300 Subject: [PATCH 3/4] chore(demo-playwright): new tests --- projects/demo-playwright/playwright.config.ts | 18 +- .../kit/input-number/input-number.pw.spec.ts | 617 +++++++++++++----- .../utils/page-objects/index.ts | 1 + .../utils/page-objects/input-number.po.ts | 9 + 4 files changed, 459 insertions(+), 186 deletions(-) create mode 100644 projects/demo-playwright/utils/page-objects/input-number.po.ts diff --git a/projects/demo-playwright/playwright.config.ts b/projects/demo-playwright/playwright.config.ts index 4ae5a073e0a3..6e9c3e2e9a56 100644 --- a/projects/demo-playwright/playwright.config.ts +++ b/projects/demo-playwright/playwright.config.ts @@ -46,14 +46,16 @@ export default defineConfig({ viewport: DEFAULT_VIEWPORT, }, }, - { - name: 'webkit', - use: { - ...devices['Desktop Safari'], - viewport: DEFAULT_VIEWPORT, - }, - }, - ], + process.env.CI + ? { + name: 'webkit', + use: { + ...devices['Desktop Safari'], + viewport: DEFAULT_VIEWPORT, + }, + } + : null, + ].filter((x: T | null): x is T => !!x), expect: { toHaveScreenshot: { animations: 'disabled', diff --git a/projects/demo-playwright/tests/kit/input-number/input-number.pw.spec.ts b/projects/demo-playwright/tests/kit/input-number/input-number.pw.spec.ts index 0e51794475a2..39a21d242995 100644 --- a/projects/demo-playwright/tests/kit/input-number/input-number.pw.spec.ts +++ b/projects/demo-playwright/tests/kit/input-number/input-number.pw.spec.ts @@ -5,6 +5,7 @@ import { CHAR_HYPHEN, CHAR_MINUS, CMD, + InputNumberPO, TuiDocumentationApiPagePO, tuiGoto, } from '@demo-playwright/utils'; @@ -15,40 +16,54 @@ const {describe, beforeEach} = test; describe('InputNumber', () => { let example: Locator; - let textfield: Locator; + let inputNumber: InputNumberPO; describe('API', () => { beforeEach(({page}) => { example = new TuiDocumentationApiPagePO(page).apiPageExample; - textfield = example.locator('[tuiInputNumber]'); + inputNumber = new InputNumberPO( + example.locator('tui-textfield:has([tuiInputNumber])'), + ); }); describe('[min] prop', () => { describe('[min] property is positive number', () => { test('rejects minus sign', async ({page}) => { await tuiGoto(page, `${DemoRoute.InputNumber}/API?min=5`); - await textfield.fill( + await inputNumber.textfield.fill( `${CHAR_MINUS}${CHAR_HYPHEN}${CHAR_EN_DASH}${CHAR_EM_DASH}9`, ); - await expect(textfield).toHaveValue('9'); - await expect(textfield).toHaveJSProperty('selectionStart', 1); - await expect(textfield).toHaveJSProperty('selectionEnd', 1); + await expect(inputNumber.textfield).toHaveValue('9'); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionStart', + 1, + ); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionEnd', + 1, + ); }); test('validates positive value (less than [min]) only on blur', async ({ page, }) => { await tuiGoto(page, `${DemoRoute.InputNumber}/API?min=5`); - await textfield.fill('2'); + await inputNumber.textfield.fill('2'); - await expect(textfield).toHaveValue('2'); - await expect(textfield).toHaveJSProperty('selectionStart', 1); - await expect(textfield).toHaveJSProperty('selectionEnd', 1); + await expect(inputNumber.textfield).toHaveValue('2'); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionStart', + 1, + ); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionEnd', + 1, + ); - await textfield.blur(); + await inputNumber.textfield.blur(); - await expect(textfield).toHaveValue('5'); + await expect(inputNumber.textfield).toHaveValue('5'); }); test('allows to enter multi-length positive value (which is less than [min])', async ({ @@ -56,17 +71,17 @@ describe('InputNumber', () => { }) => { await tuiGoto(page, `${DemoRoute.InputNumber}/API?min=100`); - await textfield.fill('3'); // less than min + await inputNumber.textfield.fill('3'); // less than min - await expect(textfield).toHaveValue('3'); + await expect(inputNumber.textfield).toHaveValue('3'); - await textfield.pressSequentially('3'); // still less than min + await inputNumber.textfield.pressSequentially('3'); // still less than min - await expect(textfield).toHaveValue('33'); + await expect(inputNumber.textfield).toHaveValue('33'); - await textfield.fill('333'); // more than min + await inputNumber.textfield.fill('333'); // more than min - await expect(textfield).toHaveValue('333'); + await expect(inputNumber.textfield).toHaveValue('333'); }); }); @@ -74,37 +89,55 @@ describe('InputNumber', () => { beforeEach(async ({page}) => { await tuiGoto(page, `${DemoRoute.InputNumber}/API?min=-5`); - await textfield.clear(); + await inputNumber.textfield.clear(); }); test('immediately validates negative value', async () => { - await textfield.fill('-10'); // less than [min] + await inputNumber.textfield.fill('-10'); // less than [min] - await expect(textfield).toHaveJSProperty('selectionStart', 2); - await expect(textfield).toHaveJSProperty('selectionEnd', 2); - await expect(textfield).toHaveValue(`${CHAR_MINUS}5`); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionStart', + 2, + ); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionEnd', + 2, + ); + await expect(inputNumber.textfield).toHaveValue(`${CHAR_MINUS}5`); }); test('do not touch any positive value', async ({page}) => { - await textfield.fill('1'); + await inputNumber.textfield.fill('1'); - await expect(textfield).toHaveJSProperty('selectionStart', 1); - await expect(textfield).toHaveJSProperty('selectionEnd', 1); - await expect(textfield).toHaveValue('1'); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionStart', + 1, + ); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionEnd', + 1, + ); + await expect(inputNumber.textfield).toHaveValue('1'); - await textfield.pressSequentially('0'); + await inputNumber.textfield.pressSequentially('0'); - await expect(textfield).toHaveJSProperty('selectionStart', 2); - await expect(textfield).toHaveJSProperty('selectionEnd', 2); - await expect(textfield).toHaveValue('10'); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionStart', + 2, + ); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionEnd', + 2, + ); + await expect(inputNumber.textfield).toHaveValue('10'); - await textfield.blur(); + await inputNumber.textfield.blur(); - await expect(textfield).toHaveValue('10'); + await expect(inputNumber.textfield).toHaveValue('10'); await page.waitForTimeout(100); // to be sure that value is not changed even in case of some async validation - await expect(textfield).toHaveValue('10'); + await expect(inputNumber.textfield).toHaveValue('10'); }); }); }); @@ -116,18 +149,30 @@ describe('InputNumber', () => { }); test('validates negative value only on blur', async ({page}) => { - await textfield.fill('-1'); // more than [max] + await inputNumber.textfield.fill('-1'); // more than [max] await page.waitForTimeout(100); // to be sure that value is not changed even in case of some async validation - await expect(textfield).toHaveValue(`${CHAR_MINUS}1`); - await expect(textfield).toHaveJSProperty('selectionStart', 2); - await expect(textfield).toHaveJSProperty('selectionEnd', 2); + await expect(inputNumber.textfield).toHaveValue(`${CHAR_MINUS}1`); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionStart', + 2, + ); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionEnd', + 2, + ); - await textfield.blur(); + await inputNumber.textfield.blur(); - await expect(textfield).toHaveValue(`${CHAR_MINUS}5`); - await expect(textfield).toHaveJSProperty('selectionStart', 2); - await expect(textfield).toHaveJSProperty('selectionEnd', 2); + await expect(inputNumber.textfield).toHaveValue(`${CHAR_MINUS}5`); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionStart', + 2, + ); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionEnd', + 2, + ); }); }); @@ -137,31 +182,202 @@ describe('InputNumber', () => { }); test('immediately validates positive value', async () => { - await textfield.fill('19'); // more than max + await inputNumber.textfield.fill('19'); // more than max - await expect(textfield).toHaveValue('12'); - await expect(textfield).toHaveJSProperty('selectionStart', 2); - await expect(textfield).toHaveJSProperty('selectionEnd', 2); + await expect(inputNumber.textfield).toHaveValue('12'); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionStart', + 2, + ); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionEnd', + 2, + ); }); test('do not touch any negative value', async ({page}) => { - await textfield.fill('-1'); + await inputNumber.textfield.fill('-1'); - await expect(textfield).toHaveValue(`${CHAR_MINUS}1`); - await expect(textfield).toHaveJSProperty('selectionStart', 2); - await expect(textfield).toHaveJSProperty('selectionEnd', 2); + await expect(inputNumber.textfield).toHaveValue(`${CHAR_MINUS}1`); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionStart', + 2, + ); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionEnd', + 2, + ); await page.keyboard.down('9'); - await expect(textfield).toHaveJSProperty('selectionStart', 3); - await expect(textfield).toHaveJSProperty('selectionEnd', 3); - await expect(textfield).toHaveValue(`${CHAR_MINUS}19`); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionStart', + 3, + ); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionEnd', + 3, + ); + await expect(inputNumber.textfield).toHaveValue(`${CHAR_MINUS}19`); await page.waitForTimeout(100); // to ensure that value is not changed even in case of some async validation - await expect(textfield).toHaveValue(`${CHAR_MINUS}19`); - await expect(textfield).toHaveJSProperty('selectionStart', 3); - await expect(textfield).toHaveJSProperty('selectionEnd', 3); + await expect(inputNumber.textfield).toHaveValue(`${CHAR_MINUS}19`); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionStart', + 3, + ); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionEnd', + 3, + ); + }); + }); + }); + + describe('[step] prop', () => { + test.use({viewport: {width: 350, height: 500}}); + + describe('[step]=1 & initially empty textfield', () => { + beforeEach(async ({page}) => { + await tuiGoto(page, `${DemoRoute.InputNumber}/API?step=1`); + + await expect(inputNumber.textfield).toHaveValue(''); + }); + + test('sets 1 on increase button click', async () => { + await inputNumber.stepUp.click(); + + await expect(inputNumber.textfield).toHaveValue('1'); + }); + + test('sets 1 on keyboard ArrowUp press', async () => { + await inputNumber.textfield.press('ArrowUp'); + + await expect(inputNumber.textfield).toHaveValue('1'); + }); + + test('sets -1 on decrease button click', async () => { + await inputNumber.stepDown.click(); + + await expect(inputNumber.textfield).toHaveValue(`${CHAR_MINUS}1`); + }); + + test('sets -1 on keyboard ArrowDown press', async () => { + await inputNumber.textfield.press('ArrowDown'); + + await expect(inputNumber.textfield).toHaveValue(`${CHAR_MINUS}1`); + }); + }); + + describe('[step]=3', () => { + beforeEach(async ({page}) => { + await tuiGoto(page, `${DemoRoute.InputNumber}/API?step=3`); + }); + + test('Click on increase button x3 times => value is 9', async () => { + await inputNumber.stepUp.click(); + await inputNumber.stepUp.click(); + await inputNumber.stepUp.click(); + + await expect(inputNumber.textfield).toHaveValue('9'); + }); + + test('Click on decrease button x6 times => value is -18', async () => { + for (let i = 0; i < 6; i++) { + await inputNumber.stepDown.click(); + } + + await expect(inputNumber.textfield).toHaveValue(`${CHAR_MINUS}18`); + }); + + test('Click on decrease button x1 & click increase x2 time => value is 3', async () => { + await inputNumber.stepDown.click(); + await inputNumber.stepUp.click(); + await inputNumber.stepUp.click(); + + await expect(inputNumber.textfield).toHaveValue('3'); + }); + }); + + describe('[min=0] & [max=0] & [step]=4', () => { + beforeEach(async ({page}) => { + await tuiGoto( + page, + `${DemoRoute.InputNumber}/API?min=0&max=10&step=4`, + ); + }); + + test('Maximum limit cannot be violated via steps', async () => { + await inputNumber.stepUp.click(); + await inputNumber.textfield.press('ArrowUp'); + + await expect(inputNumber.textfield).toHaveValue('8'); + + await inputNumber.stepUp.click(); + + await expect(inputNumber.textfield).toHaveValue('10'); + + await expect(inputNumber.stepUp).toBeDisabled(); + + await inputNumber.stepUp.click({force: true}); + await inputNumber.stepUp.press('ArrowUp'); + + await expect(inputNumber.textfield).toHaveValue('10'); + await expect(inputNumber.host).toHaveScreenshot( + 'input-number-with-disabled-step-up.png', + ); + }); + + test('Minimum limit cannot be violated via steps', async () => { + await expect(inputNumber.stepDown).toBeDisabled(); + + await inputNumber.stepDown.click({force: true}); + await inputNumber.textfield.press('ArrowDown'); + + await expect(inputNumber.textfield).toHaveValue('0'); + await expect(inputNumber.host).toHaveScreenshot( + 'input-number-with-disabled-step-down.png', + ); + + await inputNumber.textfield.fill('2'); + await inputNumber.stepDown.click(); + + await expect(inputNumber.textfield).toHaveValue('0'); + await expect(inputNumber.stepDown).toBeDisabled(); + }); + }); + + describe('different size of the textfield has different size of the step buttons', () => { + describe('empty textfield', () => { + ['s', 'm', 'l'].forEach((size) => { + test(`[size]=${size} & empty textfield`, async ({page}) => { + await tuiGoto( + page, + `${DemoRoute.InputNumber}/API?step=1&tuiTextfieldSize=${size}`, + ); + + await expect(inputNumber.host).toHaveScreenshot( + `input-number-with-step-no-value-tuiTextfieldSize=${size}.png`, + ); + }); + }); + }); + + describe('textfield has value', () => { + ['s', 'm', 'l'].forEach((size) => { + test(`[size]=${size} & empty textfield`, async ({page}) => { + await tuiGoto( + page, + `${DemoRoute.InputNumber}/API?step=1&tuiTextfieldSize=${size}`, + ); + await inputNumber.textfield.fill('42'); + + await expect(inputNumber.host).toHaveScreenshot( + `input-number-with-step-with-value-tuiTextfieldSize=${size}.png`, + ); + }); + }); }); }); }); @@ -183,13 +399,13 @@ describe('InputNumber', () => { }); test('does not show suffixes for unfocused empty textfield', async () => { - await expect(textfield).toHaveValue(''); + await expect(inputNumber.textfield).toHaveValue(''); }); test('shows suffixes for empty textfield on focus', async () => { - await textfield.focus(); + await inputNumber.textfield.focus(); - await expect(textfield).toHaveValue(prefix + postfix); + await expect(inputNumber.textfield).toHaveValue(prefix + postfix); }); test('does not shows prefix for READONLY empty textfield on focus', async ({ @@ -199,72 +415,90 @@ describe('InputNumber', () => { page, `${DemoRoute.InputNumber}/API?prefix=${prefix}&postfix=${postfix}&readOnly=true`, ); - await textfield.focus(); + await inputNumber.textfield.focus(); - await expect(textfield).toHaveValue(''); + await expect(inputNumber.textfield).toHaveValue(''); - await textfield.click(); + await inputNumber.textfield.click(); - await expect(textfield).toHaveValue(''); + await expect(inputNumber.textfield).toHaveValue(''); }); describe('forbids to erase prefix', () => { test('using Backspace many times', async () => { - await textfield.focus(); - await textfield.press('Backspace'); - await textfield.press('Backspace'); + await inputNumber.textfield.focus(); + await inputNumber.textfield.press('Backspace'); + await inputNumber.textfield.press('Backspace'); - await expect(textfield).toHaveValue(prefix + postfix); + await expect(inputNumber.textfield).toHaveValue( + prefix + postfix, + ); - await textfield.pressSequentially('42'); + await inputNumber.textfield.pressSequentially('42'); - await expect(textfield).toHaveValue(`${prefix}42${postfix}`); + await expect(inputNumber.textfield).toHaveValue( + `${prefix}42${postfix}`, + ); - await textfield.press('Backspace'); - await textfield.press('Backspace'); - await textfield.press('Backspace'); - await textfield.press('Backspace'); - await textfield.press('Backspace'); + await inputNumber.textfield.press('Backspace'); + await inputNumber.textfield.press('Backspace'); + await inputNumber.textfield.press('Backspace'); + await inputNumber.textfield.press('Backspace'); + await inputNumber.textfield.press('Backspace'); - await expect(textfield).toHaveValue(prefix + postfix); + await expect(inputNumber.textfield).toHaveValue( + prefix + postfix, + ); }); test('select all + Backspace', async ({page}) => { - await textfield.focus(); + await inputNumber.textfield.focus(); await page.keyboard.press(`${CMD}+A`); await page.keyboard.press('Backspace'); - await expect(textfield).toHaveValue(prefix + postfix); + await expect(inputNumber.textfield).toHaveValue( + prefix + postfix, + ); - await textfield.pressSequentially('42'); + await inputNumber.textfield.pressSequentially('42'); - await expect(textfield).toHaveValue(`${prefix}42${postfix}`); + await expect(inputNumber.textfield).toHaveValue( + `${prefix}42${postfix}`, + ); await page.keyboard.press(`${CMD}+A`); await page.keyboard.press('Backspace'); - await expect(textfield).toHaveValue(prefix + postfix); + await expect(inputNumber.textfield).toHaveValue( + prefix + postfix, + ); }); test('select all + Delete', async ({page}) => { - await textfield.focus(); + await inputNumber.textfield.focus(); await page.keyboard.press(`${CMD}+A`); await page.keyboard.press('Delete'); - await expect(textfield).toHaveValue(prefix + postfix); + await expect(inputNumber.textfield).toHaveValue( + prefix + postfix, + ); - await textfield.pressSequentially('42'); + await inputNumber.textfield.pressSequentially('42'); - await expect(textfield).toHaveValue(`${prefix}42${postfix}`); + await expect(inputNumber.textfield).toHaveValue( + `${prefix}42${postfix}`, + ); await page.keyboard.press(`${CMD}+A`); await page.keyboard.press('Delete'); - await expect(textfield).toHaveValue(prefix + postfix); + await expect(inputNumber.textfield).toHaveValue( + prefix + postfix, + ); }); }); - test('textfield does not contain any digit (only suffixes) => clear textfield value on blur', async ({ + test('textfield does not contain any digit (only suffixes) => clear inputNumber.textfield value on blur', async ({ browserName, }) => { // TODO @@ -273,21 +507,21 @@ describe('InputNumber', () => { 'Investigate why it fails in Safari', ); - await textfield.focus(); + await inputNumber.textfield.focus(); - await expect(textfield).toHaveValue(prefix + postfix); - await expect(textfield).toHaveJSProperty( + await expect(inputNumber.textfield).toHaveValue(prefix + postfix); + await expect(inputNumber.textfield).toHaveJSProperty( 'selectionStart', prefix.length, ); - await expect(textfield).toHaveJSProperty( + await expect(inputNumber.textfield).toHaveJSProperty( 'selectionEnd', prefix.length, ); - await textfield.blur(); + await inputNumber.textfield.blur(); - await expect(textfield).toHaveValue(''); + await expect(inputNumber.textfield).toHaveValue(''); }); }); }); @@ -296,36 +530,36 @@ describe('InputNumber', () => { describe('[precision] prop', () => { test('[precision]=0', async ({page}) => { await tuiGoto(page, `${DemoRoute.InputNumber}/API?precision=0`); - await textfield.focus(); - await textfield.pressSequentially(',.'); + await inputNumber.textfield.focus(); + await inputNumber.textfield.pressSequentially(',.'); - await expect(textfield).toHaveValue(''); + await expect(inputNumber.textfield).toHaveValue(''); - await textfield.pressSequentially('0,.'); + await inputNumber.textfield.pressSequentially('0,.'); - await expect(textfield).toHaveValue('0'); + await expect(inputNumber.textfield).toHaveValue('0'); }); test('[precision]=2', async ({page}) => { await tuiGoto(page, `${DemoRoute.InputNumber}/API?precision=2`); - await textfield.focus(); - await textfield.pressSequentially(',.'); + await inputNumber.textfield.focus(); + await inputNumber.textfield.pressSequentially(',.'); - await expect(textfield).toHaveValue('0.'); + await expect(inputNumber.textfield).toHaveValue('0.'); - await textfield.pressSequentially('12345'); + await inputNumber.textfield.pressSequentially('12345'); - await expect(textfield).toHaveValue('0.12'); + await expect(inputNumber.textfield).toHaveValue('0.12'); }); }); describe('[thousandSeparator] prop', () => { test('_', async ({page}) => { await tuiGoto(page, `${DemoRoute.InputNumber}/API?thousandSeparator=_`); - await textfield.focus(); - await textfield.pressSequentially('1234567890'); + await inputNumber.textfield.focus(); + await inputNumber.textfield.pressSequentially('1234567890'); - await expect(textfield).toHaveValue('1_234_567_890'); + await expect(inputNumber.textfield).toHaveValue('1_234_567_890'); }); test('.', async ({page}) => { @@ -337,10 +571,10 @@ describe('InputNumber', () => { */ `${DemoRoute.InputNumber}/API?precision=0&thousandSeparator=.&decimalSeparator=,`, ); - await textfield.focus(); - await textfield.pressSequentially('1234567890'); + await inputNumber.textfield.focus(); + await inputNumber.textfield.pressSequentially('1234567890'); - await expect(textfield).toHaveValue('1.234.567.890'); + await expect(inputNumber.textfield).toHaveValue('1.234.567.890'); }); }); @@ -350,16 +584,16 @@ describe('InputNumber', () => { page, `${DemoRoute.InputNumber}/API?precision=4&decimalSeparator=.`, ); - await textfield.focus(); - await textfield.pressSequentially('.1234567890'); + await inputNumber.textfield.focus(); + await inputNumber.textfield.pressSequentially('.1234567890'); - await expect(textfield).toHaveValue('0.1234'); + await expect(inputNumber.textfield).toHaveValue('0.1234'); - await textfield.clear(); + await inputNumber.textfield.clear(); - await textfield.pressSequentially(',42'); + await inputNumber.textfield.pressSequentially(',42'); - await expect(textfield).toHaveValue('0.42'); + await expect(inputNumber.textfield).toHaveValue('0.42'); }); }); @@ -370,12 +604,12 @@ describe('InputNumber', () => { `${DemoRoute.InputNumber}/API?precision=2&decimalMode=not-zero`, ); - await textfield.fill('42'); + await inputNumber.textfield.fill('42'); - await expect(textfield).toHaveValue('42'); - await expect(textfield).toHaveJSProperty('selectionStart', 2); - await expect(textfield).toHaveJSProperty('selectionEnd', 2); - await expect(textfield).toHaveValue('42'); + await expect(inputNumber.textfield).toHaveValue('42'); + await expect(inputNumber.textfield).toHaveJSProperty('selectionStart', 2); + await expect(inputNumber.textfield).toHaveJSProperty('selectionEnd', 2); + await expect(inputNumber.textfield).toHaveValue('42'); }); test('decimalMode=not-zero | 42.1 => Blur => 42.1', async ({page}) => { @@ -384,15 +618,15 @@ describe('InputNumber', () => { `${DemoRoute.InputNumber}/API?precision=2&decimalMode=not-zero`, ); - await textfield.fill('42.1'); + await inputNumber.textfield.fill('42.1'); - await expect(textfield).toHaveValue('42.1'); - await expect(textfield).toHaveJSProperty('selectionStart', 4); - await expect(textfield).toHaveJSProperty('selectionEnd', 4); + await expect(inputNumber.textfield).toHaveValue('42.1'); + await expect(inputNumber.textfield).toHaveJSProperty('selectionStart', 4); + await expect(inputNumber.textfield).toHaveJSProperty('selectionEnd', 4); - await textfield.blur(); + await inputNumber.textfield.blur(); - await expect(textfield).toHaveValue('42.1'); + await expect(inputNumber.textfield).toHaveValue('42.1'); }); test('decimalMode=not-zero | 42.00 => Blur => 42', async ({page}) => { @@ -401,17 +635,20 @@ describe('InputNumber', () => { `${DemoRoute.InputNumber}/API?precision=2&decimalMode=not-zero`, ); - await textfield.fill('42.00'); + await inputNumber.textfield.fill('42.00'); - await expect(textfield).toHaveJSProperty( + await expect(inputNumber.textfield).toHaveJSProperty( 'selectionStart', '42.00'.length, ); - await expect(textfield).toHaveJSProperty('selectionEnd', '42.00'.length); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionEnd', + '42.00'.length, + ); - await textfield.blur(); + await inputNumber.textfield.blur(); - await expect(textfield).toHaveValue('42'); + await expect(inputNumber.textfield).toHaveValue('42'); }); test('decimalMode=pad | 42.1 => Blur => 42.10', async ({page}) => { @@ -420,15 +657,21 @@ describe('InputNumber', () => { `${DemoRoute.InputNumber}/API?precision=2&decimalMode=pad`, ); - await textfield.fill('42.1'); + await inputNumber.textfield.fill('42.1'); - await expect(textfield).toHaveValue('42.1'); - await expect(textfield).toHaveJSProperty('selectionStart', '42.1'.length); - await expect(textfield).toHaveJSProperty('selectionEnd', '42.1'.length); + await expect(inputNumber.textfield).toHaveValue('42.1'); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionStart', + '42.1'.length, + ); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionEnd', + '42.1'.length, + ); - await textfield.blur(); + await inputNumber.textfield.blur(); - await expect(textfield).toHaveValue('42.10'); + await expect(inputNumber.textfield).toHaveValue('42.10'); }); test('decimalMode=always | Enter 42 => 42.00', async ({page}) => { @@ -436,11 +679,11 @@ describe('InputNumber', () => { page, `${DemoRoute.InputNumber}/API?precision=2&decimalMode=always`, ); - await textfield.fill('42'); + await inputNumber.textfield.fill('42'); - await expect(textfield).toHaveValue('42.00'); - await expect(textfield).toHaveJSProperty('selectionStart', 2); - await expect(textfield).toHaveJSProperty('selectionEnd', 2); + await expect(inputNumber.textfield).toHaveValue('42.00'); + await expect(inputNumber.textfield).toHaveJSProperty('selectionStart', 2); + await expect(inputNumber.textfield).toHaveJSProperty('selectionEnd', 2); }); }); @@ -452,37 +695,37 @@ describe('InputNumber', () => { `${DemoRoute.InputNumber}/API?decimalMode=always&precision=2`, ); - await textfield.clear(); - await textfield.fill('105.00'); + await inputNumber.textfield.clear(); + await inputNumber.textfield.fill('105.00'); }); test('105.00| => Backspace => 105.0|0', async ({page}) => { await page.keyboard.press('Backspace'); - await expect(textfield).toHaveJSProperty( + await expect(inputNumber.textfield).toHaveJSProperty( 'selectionStart', '105.0'.length, ); - await expect(textfield).toHaveJSProperty( + await expect(inputNumber.textfield).toHaveJSProperty( 'selectionEnd', '105.0'.length, ); - await expect(textfield).toHaveValue('105.00'); + await expect(inputNumber.textfield).toHaveValue('105.00'); }); test('105.0|0 => Backspace => 105.|00', async ({page}) => { await page.keyboard.press('ArrowLeft'); await page.keyboard.press('Backspace'); - await expect(textfield).toHaveJSProperty( + await expect(inputNumber.textfield).toHaveJSProperty( 'selectionStart', '105.'.length, ); - await expect(textfield).toHaveJSProperty( + await expect(inputNumber.textfield).toHaveJSProperty( 'selectionEnd', '105.'.length, ); - await expect(textfield).toHaveValue('105.00'); + await expect(inputNumber.textfield).toHaveValue('105.00'); }); test('105.|00 => Backspace => 105|.00', async ({page}) => { @@ -490,15 +733,15 @@ describe('InputNumber', () => { await page.keyboard.press('ArrowLeft'); await page.keyboard.press('Backspace'); - await expect(textfield).toHaveJSProperty( + await expect(inputNumber.textfield).toHaveJSProperty( 'selectionStart', '105'.length, ); - await expect(textfield).toHaveJSProperty( + await expect(inputNumber.textfield).toHaveJSProperty( 'selectionEnd', '105'.length, ); - await expect(textfield).toHaveValue('105.00'); + await expect(inputNumber.textfield).toHaveValue('105.00'); }); test('105.|00 => Delete => 105.0|0', async ({page}) => { @@ -506,15 +749,15 @@ describe('InputNumber', () => { await page.keyboard.press('ArrowLeft'); await page.keyboard.press('Delete'); - await expect(textfield).toHaveJSProperty( + await expect(inputNumber.textfield).toHaveJSProperty( 'selectionStart', '105.0'.length, ); - await expect(textfield).toHaveJSProperty( + await expect(inputNumber.textfield).toHaveJSProperty( 'selectionEnd', '105.0'.length, ); - await expect(textfield).toHaveValue('105.00'); + await expect(inputNumber.textfield).toHaveValue('105.00'); }); }); @@ -525,50 +768,68 @@ describe('InputNumber', () => { `${DemoRoute.InputNumber}/API?decimalMode=not-zero`, ); - await textfield.fill('1000'); + await inputNumber.textfield.fill('1000'); }); test('1| 000 => Delete => 1 |000', async ({page}) => { - const length = (await textfield.inputValue()).length; + const length = (await inputNumber.textfield.inputValue()).length; for (let i = 0; i < length; i++) { await page.keyboard.press('ArrowLeft'); } - await expect(textfield).toHaveJSProperty('selectionStart', 0); - await expect(textfield).toHaveJSProperty('selectionEnd', 0); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionStart', + 0, + ); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionEnd', + 0, + ); await page.keyboard.press('ArrowRight'); await page.keyboard.press('Delete'); - await expect(textfield).toHaveJSProperty( + await expect(inputNumber.textfield).toHaveJSProperty( 'selectionStart', '1 '.length, ); - await expect(textfield).toHaveJSProperty('selectionEnd', '1 '.length); - await expect(textfield).toHaveValue('1 000'); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionEnd', + '1 '.length, + ); + await expect(inputNumber.textfield).toHaveValue('1 000'); }); test('1 |000 => Backspace => 1| 000', async ({page}) => { - const length = (await textfield.inputValue()).length; + const length = (await inputNumber.textfield.inputValue()).length; for (let i = 0; i < length; i++) { await page.keyboard.press('ArrowLeft'); } - await expect(textfield).toHaveJSProperty('selectionStart', 0); - await expect(textfield).toHaveJSProperty('selectionEnd', 0); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionStart', + 0, + ); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionEnd', + 0, + ); await page.keyboard.press('ArrowRight'); await page.keyboard.press('ArrowRight'); await page.keyboard.press('Backspace'); - await expect(textfield).toHaveJSProperty( + await expect(inputNumber.textfield).toHaveJSProperty( 'selectionStart', '1'.length, ); - await expect(textfield).toHaveJSProperty('selectionEnd', '1'.length); - await expect(textfield).toHaveValue('1 000'); + await expect(inputNumber.textfield).toHaveJSProperty( + 'selectionEnd', + '1'.length, + ); + await expect(inputNumber.textfield).toHaveValue('1 000'); }); }); }); @@ -583,12 +844,12 @@ describe('InputNumber', () => { `${DemoRoute.InputNumber}/API?tuiTextfieldSize=${size}`, ); - await expect(textfield).toHaveValue(''); + await expect(inputNumber.textfield).toHaveValue(''); await expect(example).toHaveScreenshot( `input-number-unfocused-empty-size-${size}.png`, ); - await textfield.focus(); + await inputNumber.textfield.focus(); await expect(example).toHaveScreenshot( `input-number-focused-empty-size-${size}.png`, @@ -601,14 +862,14 @@ describe('InputNumber', () => { `${DemoRoute.InputNumber}/API?precision=2&tuiTextfieldSize=${size}`, ); - await textfield.fill('12.34'); + await inputNumber.textfield.fill('12.34'); - await expect(textfield).toHaveValue('12.34'); + await expect(inputNumber.textfield).toHaveValue('12.34'); await expect(example).toHaveScreenshot( `input-number-focused-with-value-size-${size}.png`, ); - await textfield.blur(); + await inputNumber.textfield.blur(); await expect(example).toHaveScreenshot( `input-number-unfocused-with-value-size-${size}.png`, @@ -622,15 +883,15 @@ describe('InputNumber', () => { page, `${DemoRoute.InputNumber}/API?thousandSeparator=_&precision=2`, ); - await textfield.focus(); - await textfield.clear(); - await textfield.pressSequentially('123456789012345.6789'); + await inputNumber.textfield.focus(); + await inputNumber.textfield.clear(); + await inputNumber.textfield.pressSequentially('123456789012345.6789'); - await expect(textfield).toHaveValue('123_456_789_012_345.67'); + await expect(inputNumber.textfield).toHaveValue('123_456_789_012_345.67'); - await textfield.blur(); + await inputNumber.textfield.blur(); - await expect(textfield).toHaveValue('123_456_789_012_345.67'); + await expect(inputNumber.textfield).toHaveValue('123_456_789_012_345.67'); }); }); }); diff --git a/projects/demo-playwright/utils/page-objects/index.ts b/projects/demo-playwright/utils/page-objects/index.ts index 478c42399d06..e654bf186617 100644 --- a/projects/demo-playwright/utils/page-objects/index.ts +++ b/projects/demo-playwright/utils/page-objects/index.ts @@ -11,6 +11,7 @@ export * from './input-date-range.po'; export * from './input-date-time.po'; export * from './input-month.po'; export * from './input-month-range.po'; +export * from './input-number.po'; export * from './input-phone.po'; export * from './input-phone-international.po'; export * from './input-range.po'; diff --git a/projects/demo-playwright/utils/page-objects/input-number.po.ts b/projects/demo-playwright/utils/page-objects/input-number.po.ts new file mode 100644 index 000000000000..0de35a2f411e --- /dev/null +++ b/projects/demo-playwright/utils/page-objects/input-number.po.ts @@ -0,0 +1,9 @@ +import type {Locator} from '@playwright/test'; + +export class InputNumberPO { + public readonly textfield: Locator = this.host.getByRole('textbox'); + public stepUp = this.host.locator('button', {hasText: '+'}); + public stepDown = this.host.locator('button', {hasText: '-'}); + + constructor(public readonly host: Locator) {} +} From 6a0458d1f049fb6ccef5921e71b0012b67cbdf65 Mon Sep 17 00:00:00 2001 From: Nikita Barsukov Date: Fri, 27 Dec 2024 11:51:21 +0300 Subject: [PATCH 4/4] chore: rename `down` / `up` => `decrease` / `increase` --- .../demo-playwright/utils/page-objects/input-number.po.ts | 4 ++-- .../kit/components/input-number/input-number.options.ts | 8 ++++---- .../components/input-number/input-number.template.html | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/projects/demo-playwright/utils/page-objects/input-number.po.ts b/projects/demo-playwright/utils/page-objects/input-number.po.ts index 0de35a2f411e..e0d470750c32 100644 --- a/projects/demo-playwright/utils/page-objects/input-number.po.ts +++ b/projects/demo-playwright/utils/page-objects/input-number.po.ts @@ -2,8 +2,8 @@ import type {Locator} from '@playwright/test'; export class InputNumberPO { public readonly textfield: Locator = this.host.getByRole('textbox'); - public stepUp = this.host.locator('button', {hasText: '+'}); - public stepDown = this.host.locator('button', {hasText: '-'}); + public readonly stepUp = this.host.locator('button', {hasText: '+'}); + public readonly stepDown = this.host.locator('button', {hasText: '-'}); constructor(public readonly host: Locator) {} } diff --git a/projects/kit/components/input-number/input-number.options.ts b/projects/kit/components/input-number/input-number.options.ts index 89ad00eb55b6..1ded84e8b1d1 100644 --- a/projects/kit/components/input-number/input-number.options.ts +++ b/projects/kit/components/input-number/input-number.options.ts @@ -8,8 +8,8 @@ export interface TuiInputNumberOptions { readonly postfix: string; readonly step: number; readonly icons: Readonly<{ - down: string; - up: string; + decrease: string; + increase: string; }>; readonly valueTransformer: TuiValueTransformer | null; } @@ -21,8 +21,8 @@ export const TUI_INPUT_NUMBER_DEFAULT_OPTIONS: TuiInputNumberOptions = { postfix: '', step: 0, icons: { - up: '@tui.plus', - down: '@tui.minus', + increase: '@tui.plus', + decrease: '@tui.minus', }, valueTransformer: null, }; diff --git a/projects/kit/components/input-number/input-number.template.html b/projects/kit/components/input-number/input-number.template.html index 55348afa4cad..67356ed2d6cb 100644 --- a/projects/kit/components/input-number/input-number.template.html +++ b/projects/kit/components/input-number/input-number.template.html @@ -10,7 +10,7 @@ class="t-button" [appearance]="textfieldOptions.appearance()" [disabled]="!interactive() || value()! >= max()" - [iconStart]="options.icons.up" + [iconStart]="options.icons.increase" [size]="textfieldOptions.size() === 'l' ? 'm' : 's'" (click.prevent)="onStep(step())" (mousedown.prevent)="element.focus()" @@ -25,7 +25,7 @@ class="t-button" [appearance]="textfieldOptions.appearance()" [disabled]="!interactive() || value()! <= min()" - [iconStart]="options.icons.down" + [iconStart]="options.icons.decrease" [size]="textfieldOptions.size() === 'l' ? 'm' : 's'" (click.prevent)="onStep(-step())" (mousedown.prevent)="element.focus()"