-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
308 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
61 changes: 61 additions & 0 deletions
61
projects/demo-app/src/app/pages/example-sf-input-page/example-sf-input-page.component.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
<app-example-wrapper [controls]="controls" [state]="prepareControlsData.state"> | ||
<label> | ||
<span | ||
class="typography-text-sm font-medium" | ||
[ngClass]="{ | ||
'cursor-not-allowed text-disabled-500': prepareControlsData.state().disabled | ||
}" | ||
> | ||
{{ prepareControlsData.state().label }} | ||
</span> | ||
<sf-input | ||
class="w-full" | ||
[size]="prepareControlsData.state().size" | ||
[placeholder]="prepareControlsData.state().placeholder" | ||
[ngModel]="prepareControlsData.state().value" | ||
[disabled]="prepareControlsData.state().disabled" | ||
[ngClass]="{ | ||
'!bg-disabled-100 !ring-disabled-300 !ring-1 !text-disabled-500': | ||
prepareControlsData.state().disabled, | ||
'!bg-disabled-100 !ring-disabled-300 !ring-1 !text-neutral-500': | ||
prepareControlsData.state().readonly, | ||
'ng-dirty ng-invalid': prepareControlsData.state().invalid | ||
}" | ||
(ngModelChange)="handleValueChange($event)" | ||
></sf-input> | ||
</label> | ||
<div class="flex justify-between"> | ||
<div> | ||
<p | ||
*ngIf="prepareControlsData.state().invalid && !prepareControlsData.state().disabled" | ||
class="typography-text-sm text-negative-700 font-medium mt-0.5" | ||
> | ||
{{ prepareControlsData.state().errorText }} | ||
</p> | ||
<p | ||
*ngIf="prepareControlsData.state().helpText" | ||
class="typography-text-xs mt-0.5" | ||
[ngClass]="[ | ||
prepareControlsData.state().disabled ? 'text-disabled-500' : 'text-neutral-500' | ||
]" | ||
> | ||
{{ prepareControlsData.state().helpText }} | ||
</p> | ||
<p | ||
*ngIf="prepareControlsData.state().requiredText && prepareControlsData.state().required" | ||
class="mt-1 typography-text-sm font-normal text-neutral-500 before:content-['*']" | ||
> | ||
{{ prepareControlsData.state().requiredText }} | ||
</p> | ||
</div> | ||
<p | ||
*ngIf="prepareControlsData.state().characterLimit && !prepareControlsData.state().readonly" | ||
class="typography-text-xs mt-0.5" | ||
[ngClass]="[ | ||
prepareControlsData.state().disabled ? 'text-disabled-500' : characterLimitClass() | ||
]" | ||
> | ||
{{ charsCount() }} | ||
</p> | ||
</div> | ||
</app-example-wrapper> |
111 changes: 111 additions & 0 deletions
111
projects/demo-app/src/app/pages/example-sf-input-page/example-sf-input-page.component.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import { ChangeDetectionStrategy, Component, computed, signal } from '@angular/core'; | ||
import { CommonModule } from '@angular/common'; | ||
import { ExampleWrapperComponent } from '../../components/example-wrapper/example-wrapper.component'; | ||
import { SfInputComponent, SfInputSize } from 'projects/ng-storefront-ui'; | ||
import { ControlService } from '../../services/control.service'; | ||
import { Controls } from '../../components/controls/controls.types'; | ||
import { FormsModule } from '@angular/forms'; | ||
|
||
@Component({ | ||
standalone: true, | ||
imports: [CommonModule, FormsModule, ExampleWrapperComponent, SfInputComponent], | ||
templateUrl: './example-sf-input-page.component.html', | ||
changeDetection: ChangeDetectionStrategy.OnPush, | ||
providers: [ControlService], | ||
}) | ||
export class ExampleSfInputPageComponent { | ||
characterLimit = signal(12); | ||
|
||
inputValue = signal(''); | ||
|
||
isAboveLimit = computed(() => this.inputValue().length > this.characterLimit()); | ||
|
||
charsCount = computed(() => this.characterLimit() - this.inputValue().length); | ||
|
||
characterLimitClass = computed(() => | ||
this.isAboveLimit() ? 'text-negative-700 font-medium' : 'text-neutral-500' | ||
); | ||
|
||
controls: Controls = [ | ||
{ | ||
type: 'select', | ||
modelName: 'size', | ||
propDefaultValue: 'SfInputSize.base', | ||
propType: 'SfInputSize', | ||
options: Object.keys(SfInputSize), | ||
}, | ||
{ | ||
type: 'text', | ||
propType: 'string', | ||
modelName: 'label', | ||
}, | ||
{ | ||
type: 'text', | ||
propType: 'string', | ||
modelName: 'placeholder', | ||
}, | ||
{ | ||
type: 'text', | ||
propType: 'string', | ||
modelName: 'helpText', | ||
}, | ||
{ | ||
type: 'text', | ||
propType: 'string', | ||
modelName: 'requiredText', | ||
}, | ||
{ | ||
type: 'text', | ||
propType: 'string', | ||
modelName: 'errorText', | ||
}, | ||
{ | ||
type: 'text', | ||
propType: 'number', | ||
modelName: 'characterLimit', | ||
}, | ||
{ | ||
type: 'boolean', | ||
propType: 'boolean', | ||
modelName: 'disabled', | ||
}, | ||
{ | ||
type: 'boolean', | ||
propType: 'boolean', | ||
modelName: 'required', | ||
}, | ||
{ | ||
type: 'boolean', | ||
propType: 'boolean', | ||
modelName: 'invalid', | ||
description: 'Support with Reactive Forms, `ng-invalid`', | ||
}, | ||
{ | ||
type: 'boolean', | ||
propType: 'boolean', | ||
modelName: 'readonly', | ||
}, | ||
]; | ||
|
||
prepareControlsData = this.controlService.prepareControls(this.controls, { | ||
size: SfInputSize.base, | ||
disabled: false, | ||
required: false, | ||
invalid: false, | ||
readonly: false, | ||
placeholder: 'Placeholder text', | ||
helpText: 'Help text', | ||
requiredText: 'Required text', | ||
errorText: 'Error text', | ||
label: 'Label', | ||
characterLimit: this.characterLimit(), | ||
value: this.inputValue(), | ||
}); | ||
|
||
constructor(private controlService: ControlService) {} | ||
|
||
handleValueChange(value: string) { | ||
console.log(this.characterLimit(), this.prepareControlsData.state().characterLimit); | ||
this.inputValue.set(value); | ||
} | ||
} |
9 changes: 6 additions & 3 deletions
9
projects/demo-app/src/app/pages/forms-showcase-page/forms-showcase-page.component.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,6 @@ | ||
<div class="p-6"> | ||
<textarea sf-textarea [formControl]="textareaControl"></textarea> | ||
</div> | ||
<app-example-wrapper> | ||
<div class="flex flex-col gap-4"> | ||
<sf-input [formControl]="inputControl" placeholder="Please input here"></sf-input> | ||
<textarea sf-textarea [formControl]="textareaControl"></textarea> | ||
</div> | ||
</app-example-wrapper> |
14 changes: 11 additions & 3 deletions
14
projects/demo-app/src/app/pages/forms-showcase-page/forms-showcase-page.component.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,23 @@ | ||
import { ChangeDetectionStrategy, Component } from '@angular/core'; | ||
import { CommonModule } from '@angular/common'; | ||
import { SfTextareaComponent } from 'projects/ng-storefront-ui'; | ||
import { SfInputComponent, SfTextareaComponent } from 'projects/ng-storefront-ui'; | ||
import { FormControl, ReactiveFormsModule, Validators } from '@angular/forms'; | ||
import { ExampleWrapperComponent } from '../../components/example-wrapper/example-wrapper.component'; | ||
|
||
@Component({ | ||
standalone: true, | ||
imports: [CommonModule, SfTextareaComponent, ReactiveFormsModule], | ||
imports: [ | ||
CommonModule, | ||
ExampleWrapperComponent, | ||
SfInputComponent, | ||
SfTextareaComponent, | ||
ReactiveFormsModule, | ||
], | ||
templateUrl: './forms-showcase-page.component.html', | ||
styles: [], | ||
changeDetection: ChangeDetectionStrategy.OnPush, | ||
}) | ||
export class FormsShowcasePageComponent { | ||
inputControl = new FormControl('This input is required', { validators: Validators.required }); | ||
|
||
textareaControl = new FormControl('', { validators: Validators.required }); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
projects/ng-storefront-ui/src/lib/sf-input/sf-input.component.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { ComponentFixture, TestBed } from '@angular/core/testing'; | ||
|
||
import { SfInputComponent } from './sf-input.component'; | ||
|
||
describe('SfInputComponent', () => { | ||
let component: SfInputComponent; | ||
let fixture: ComponentFixture<SfInputComponent>; | ||
|
||
beforeEach(() => { | ||
TestBed.configureTestingModule({ | ||
imports: [SfInputComponent], | ||
}); | ||
fixture = TestBed.createComponent(SfInputComponent); | ||
component = fixture.componentInstance; | ||
fixture.detectChanges(); | ||
}); | ||
|
||
it('should create', () => { | ||
expect(component).toBeTruthy(); | ||
}); | ||
}); |
82 changes: 82 additions & 0 deletions
82
projects/ng-storefront-ui/src/lib/sf-input/sf-input.component.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import { ChangeDetectionStrategy, Component, HostBinding, Input, forwardRef } from '@angular/core'; | ||
import { CommonModule } from '@angular/common'; | ||
import { SfInputSize } from '../../types'; | ||
import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms'; | ||
|
||
@Component({ | ||
selector: 'sf-input', | ||
standalone: true, | ||
imports: [CommonModule, FormsModule], | ||
template: ` | ||
<ng-content select="[prefix]" /> | ||
<input | ||
data-testid="input-field" | ||
class="min-w-[80px] w-full text-base outline-none appearance-none text-neutral-900 disabled:cursor-not-allowed disabled:bg-transparent read-only:bg-transparent" | ||
[ngModel]="value" | ||
[disabled]="disabled" | ||
[size]="1" | ||
[type]="type" | ||
[placeholder]="placeholder" | ||
(ngModelChange)="handleValueChange($event)" | ||
/> | ||
<ng-content select="[suffix]" /> | ||
`, | ||
styleUrls: ['../../../styles/form-fields.css'], | ||
changeDetection: ChangeDetectionStrategy.OnPush, | ||
providers: [ | ||
{ | ||
provide: NG_VALUE_ACCESSOR, | ||
multi: true, | ||
useExisting: forwardRef(() => SfInputComponent), | ||
}, | ||
], | ||
}) | ||
export class SfInputComponent implements ControlValueAccessor { | ||
@Input() size: keyof typeof SfInputSize = SfInputSize.base; | ||
|
||
@Input() value: unknown = ''; | ||
|
||
@Input() disabled: boolean = false; | ||
|
||
@Input() type: string = ''; | ||
|
||
@Input() placeholder: string = ''; | ||
|
||
@Input() onChange: (value: unknown) => void = () => {}; | ||
|
||
@Input() onTouched: (value: unknown) => void = () => {}; | ||
|
||
sizeClasses = { | ||
[SfInputSize.sm]: ' h-[32px]', | ||
[SfInputSize.base]: 'h-[40px]', | ||
[SfInputSize.lg]: 'h-[48px]', | ||
}; | ||
|
||
@HostBinding('class') get hostClass() { | ||
return [ | ||
'flex items-center gap-2 px-4 bg-white rounded-md ring-1 text-neutral-500 hover:ring-primary-700 focus-within:caret-primary-700 active:caret-primary-700 active:ring-primary-700 active:ring-2 focus-within:ring-primary-700 focus-within:ring-2 ring-1 ring-neutral-200', | ||
this.sizeClasses[this.size], | ||
].join(' '); | ||
} | ||
|
||
handleValueChange(value: string) { | ||
this.writeValue(value); | ||
this.onChange(value); | ||
} | ||
|
||
writeValue(value: string) { | ||
this.value = value; | ||
} | ||
|
||
registerOnChange(onChange: (value: unknown) => void) { | ||
this.onChange = onChange; | ||
} | ||
|
||
registerOnTouched(onTouched: (value: unknown) => void) { | ||
this.onTouched = onTouched; | ||
} | ||
|
||
setDisabledState?(isDisabled: boolean) { | ||
this.disabled = isDisabled; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export enum SfInputSize { | ||
sm = 'sm', | ||
base = 'base', | ||
lg = 'lg', | ||
} |