diff --git a/projects/ion/src/lib/core/types/input-counter.ts b/projects/ion/src/lib/core/types/input-counter.ts index 002922760..0e60821ee 100644 --- a/projects/ion/src/lib/core/types/input-counter.ts +++ b/projects/ion/src/lib/core/types/input-counter.ts @@ -2,4 +2,9 @@ export type InputCountSize = 'sm' | 'md'; export interface IonInputCount { inputSize: InputCountSize; + minValue?: number; + maxValue?: number; + maxDigits?: number; + disabled?: boolean; + count?: number; } diff --git a/projects/ion/src/lib/input-counter/input-counter.component.html b/projects/ion/src/lib/input-counter/input-counter.component.html index ea5a193a6..013df6419 100644 --- a/projects/ion/src/lib/input-counter/input-counter.component.html +++ b/projects/ion/src/lib/input-counter/input-counter.component.html @@ -1,5 +1,6 @@
{ const inputCounter = screen.getByTestId('input-count') as HTMLInputElement; const value = '111'; userEvent.type(inputCounter, value); + fireEvent.blur(inputCounter); expect(inputCounter.value).toBe(value); userEvent.type(inputCounter, 'abc'); expect(inputCounter.value).toBe(value); @@ -96,3 +97,46 @@ describe('InputCounter / Size', () => { ); }); }); + +describe('InputCounter / Limits', () => { + it('should set the maximum value when a bigger number is texted', async () => { + const maxValue = 50; + await sut({ maxValue }); + const inputCounter = screen.getByTestId('input-count') as HTMLInputElement; + userEvent.type(inputCounter, '1588'); + fireEvent.blur(inputCounter); + expect(inputCounter).toHaveValue(maxValue.toString()); + }); + + it('should set the minimum value when a smaller number is texted', async () => { + const minValue = 50; + await sut({ minValue }); + const inputCounter = screen.getByTestId('input-count') as HTMLInputElement; + userEvent.clear(inputCounter); + userEvent.type(inputCounter, '10'); + fireEvent.blur(inputCounter); + expect(inputCounter).toHaveValue(minValue.toString()); + }); + + it('should dont exceed the max value by the increase button when it is clicked', async () => { + const maxValue = 100; + await sut({ maxValue, count: maxValue }); + const inputCounter = screen.getByTestId('input-count') as HTMLInputElement; + const addButton = screen.getByTestId('iconAdd'); + userEvent.click(addButton.firstChild as HTMLElement); + expect(inputCounter).toHaveValue(maxValue.toString()); + }); +}); + +describe('InputCounter / Disabled', () => { + it('should show the disabled state when it is setted', async () => { + await sut({ disabled: true }); + const inputCounter = screen.getByTestId('input-count') as HTMLInputElement; + const subButton = screen.getByTestId('iconSub'); + const addButton = screen.getByTestId('iconAdd'); + + expect(inputCounter).toBeDisabled(); + expect(subButton.firstChild).toBeDisabled(); + expect(addButton.firstChild).toBeDisabled(); + }); +}); diff --git a/projects/ion/src/lib/input-counter/input-counter.component.ts b/projects/ion/src/lib/input-counter/input-counter.component.ts index 3f644d2d8..5e6cef01e 100644 --- a/projects/ion/src/lib/input-counter/input-counter.component.ts +++ b/projects/ion/src/lib/input-counter/input-counter.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, Output, EventEmitter } from '@angular/core'; +import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core'; import { IonInputCount } from '../core/types'; @Component({ @@ -6,12 +6,20 @@ import { IonInputCount } from '../core/types'; templateUrl: './input-counter.component.html', styleUrls: ['./input-counter.component.scss'], }) -export class IonInputCounterComponent { +export class IonInputCounterComponent implements OnInit { @Input() inputSize: IonInputCount['inputSize'] = 'md'; + @Input() maxValue?: number; + @Input() minValue = 0; + @Input() disabled = false; @Input() count = 0; + @Input() maxDigits = 9; @Output() changedValue = new EventEmitter(); - private minValue = 0; + ngOnInit(): void { + if (this.minValue && !this.count) { + this.count = this.minValue; + } + } public emitEvent(): void { this.changedValue.emit({ newValue: this.count }); @@ -25,6 +33,7 @@ export class IonInputCounterComponent { } public countIncrement(): void { + if (this.maxValue && this.maxValue === this.count) return; this.count++; this.emitEvent(); } @@ -33,7 +42,20 @@ export class IonInputCounterComponent { const countNumeric = Number(count); if (!isNaN(countNumeric)) { this.count = countNumeric; - this.emitEvent(); } } + + public onBlurInput(): void { + this.count = this.getValidCount(); + this.emitEvent(); + } + + private getValidCount(): number { + if (this.count < this.minValue) { + return this.minValue; + } else if (this.maxValue && this.count > this.maxValue) { + return this.maxValue; + } + return this.count; + } } diff --git a/stories/InputCounter.stories.ts b/stories/InputCounter.stories.ts index 1a8c54206..fdac32b1c 100644 --- a/stories/InputCounter.stories.ts +++ b/stories/InputCounter.stories.ts @@ -1,33 +1,50 @@ -import { Meta } from '@storybook/angular/types-6-0'; -import { moduleMetadata, Story } from '@storybook/angular'; +import { Meta, StoryObj } from '@storybook/angular/types-6-0'; +import { moduleMetadata } from '@storybook/angular'; import { IonInputCounterComponent } from '../projects/ion/src/lib/input-counter/input-counter.component'; import { FormsModule } from '@angular/forms'; import { IonButtonModule } from '../projects/ion/src/lib/button/button.module'; +import { InputCountSize } from 'ion/public-api'; +import { CommonModule } from '@angular/common'; export default { title: 'Ion/Data Entry/Input-Counter', component: IonInputCounterComponent, + argTypes: { + inputSize: { + options: ['sm', 'md'] as InputCountSize[], + control: { type: 'radio' }, + }, + }, decorators: [ moduleMetadata({ - imports: [FormsModule, IonButtonModule], + imports: [FormsModule, IonButtonModule, CommonModule], declarations: [], }), ], -} as Meta; +} as Meta; -const Template: Story = ( - args: IonInputCounterComponent -) => ({ - component: IonInputCounterComponent, - props: args, -}); +type Story = StoryObj; + +export const Medium: Story = { + args: {}, +}; + +export const Small: Story = { + args: { + inputSize: 'sm', + }, +}; -export const Small = Template.bind({}); -Small.args = { - InputSize: 'sm', +export const Disabled: Story = { + args: { + disabled: true, + }, }; -export const Medium = Template.bind({}); -Medium.args = { - InputSize: 'md', +export const WithMaxAndMinValues: Story = { + name: 'With max and min values', + args: { + maxValue: 100, + minValue: 1, + }, };