feat: add input color (#2257)

* feat: add input color

* patterns will always be there

---------

Co-authored-by: Matt Hill <matthewonthemoon@gmail.com>
This commit is contained in:
Alex Inkin
2023-04-27 06:22:52 +03:00
committed by Aiden McClelland
parent 833c1f22a3
commit e0ee89bdd9
17 changed files with 151 additions and 6 deletions

View File

@@ -19,6 +19,8 @@
"@angular/router": "^14.1.0",
"@angular/service-worker": "^14.2.2",
"@ionic/angular": "^6.1.15",
"@maskito/angular": "^0.10.0",
"@maskito/core": "^0.10.0",
"@materia-ui/ngx-monaco-editor": "^6.0.0",
"@ng-web-apis/common": "^2.0.0",
"@ng-web-apis/mutation-observer": "^2.0.0",
@@ -3498,6 +3500,26 @@
"integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==",
"dev": true
},
"node_modules/@maskito/angular": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/@maskito/angular/-/angular-0.10.0.tgz",
"integrity": "sha512-RpwN4zj//IV1Lnm1kkDlxej7XuhSlkr3VfkG+dAkl7gJsqdnLnrSFesnId564vwI6oxXZHEGzSpujXdQwje7Kg==",
"dependencies": {
"tslib": "^2.3.0"
},
"peerDependencies": {
"@angular/common": ">=12.0.0",
"@angular/core": ">=12.0.0",
"@angular/forms": ">=12.0.0",
"@maskito/core": "^0.10.0",
"rxjs": ">=6.0.0"
}
},
"node_modules/@maskito/core": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/@maskito/core/-/core-0.10.0.tgz",
"integrity": "sha512-ChCGFiA5uIOVetctbFaWjv1EDj4WdHW2cWtOFuqGbTB4+NcIn//ubccjuTEV41Pb/gR4pyO0Fkv2RRzV+cLOmA=="
},
"node_modules/@materia-ui/ngx-monaco-editor": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/@materia-ui/ngx-monaco-editor/-/ngx-monaco-editor-6.0.0.tgz",

View File

@@ -44,6 +44,8 @@
"@angular/router": "^14.1.0",
"@angular/service-worker": "^14.2.2",
"@ionic/angular": "^6.1.15",
"@maskito/angular": "^0.10.0",
"@maskito/core": "^0.10.0",
"@materia-ui/ngx-monaco-editor": "^6.0.0",
"@ng-web-apis/common": "^2.0.0",
"@ng-web-apis/mutation-observer": "^2.0.0",

View File

@@ -6,6 +6,10 @@ export abstract class Control<Spec extends ValueSpec, Value> {
private readonly control: FormControlComponent<Spec, Value> =
inject(FormControlComponent)
get invalid(): boolean {
return this.control.touched && this.control.invalid
}
get spec(): Spec {
return this.control.spec
}

View File

@@ -0,0 +1,29 @@
<tui-input
[maskito]="mask"
[tuiTextfieldCustomContent]="color"
[tuiTextfieldCleaner]="false"
[tuiHintContent]="spec.description"
[pseudoInvalid]="invalid"
[(ngModel)]="value"
(focusedChange)="onFocus($event)"
>
{{ spec.name }}
<span *ngIf="spec.required">*</span>
</tui-input>
<ng-template #color>
<div class="wrapper" [style.color]="value">
<input
type="color"
class="color"
tabindex="-1"
[(ngModel)]="value"
(click.stop)="(0)"
/>
<tui-svg
src="tuiIconPaintLarge"
tuiWrapper
appearance="icon"
class="icon"
></tui-svg>
</div>
</ng-template>

View File

@@ -0,0 +1,33 @@
@import '@taiga-ui/core/styles/taiga-ui-local';
.wrapper {
position: relative;
width: 1.5rem;
height: 1.5rem;
pointer-events: auto;
&::after {
content: '';
position: absolute;
height: 0.3rem;
width: 1.4rem;
bottom: 0.125rem;
background: currentColor;
border-radius: 0.125rem;
pointer-events: none;
}
}
.color {
@include fullsize();
opacity: 0;
}
.icon {
@include fullsize();
pointer-events: none;
input:hover + & {
opacity: 1;
}
}

View File

@@ -0,0 +1,15 @@
import { Component } from '@angular/core'
import { ValueSpecColor } from 'start-sdk/lib/config/configTypes'
import { Control } from '../control'
import { MaskitoOptions } from '@maskito/core'
@Component({
selector: 'form-color',
templateUrl: './form-color.component.html',
styleUrls: ['./form-color.component.scss'],
})
export class FormColorComponent extends Control<ValueSpecColor, string> {
readonly mask: MaskitoOptions = {
mask: ['#', ...Array(6).fill(/[0-9a-f]/i)],
}
}

View File

@@ -1,11 +1,12 @@
<ng-container [ngSwitch]="spec.type">
<form-text *ngSwitchCase="'text'"></form-text>
<form-color *ngSwitchCase="'color'"></form-color>
<form-file *ngSwitchCase="'file'"></form-file>
<form-multiselect *ngSwitchCase="'multiselect'"></form-multiselect>
<form-number *ngSwitchCase="'number'"></form-number>
<form-select *ngSwitchCase="'select'"></form-select>
<form-text *ngSwitchCase="'text'"></form-text>
<form-textarea *ngSwitchCase="'textarea'"></form-textarea>
<form-toggle *ngSwitchCase="'toggle'"></form-toggle>
<form-select *ngSwitchCase="'select'"></form-select>
<form-multiselect *ngSwitchCase="'multiselect'"></form-multiselect>
<form-file *ngSwitchCase="'file'"></form-file>
</ng-container>
<tui-error [error]="order | tuiFieldError | async"></tui-error>
<ng-template *ngIf="spec.warning" #warning let-completeWith="completeWith">

View File

@@ -39,7 +39,7 @@ interface ValidatorsPatternError {
pattern: ({ requiredPattern }: ValidatorsPatternError) =>
control.spec.patterns.find(
({ regex }) => String(regex) === String(requiredPattern),
)?.description || 'Invalid pattern',
)?.description || 'Invalid format',
}),
},
],

View File

@@ -1,5 +1,5 @@
<tui-input-files
[pseudoInvalid]="true"
[pseudoInvalid]="invalid"
[(ngModel)]="value"
(focusedChange)="onFocus($event)"
>

View File

@@ -1,5 +1,6 @@
<tui-multi-select
[tuiHintContent]="spec.description"
[pseudoInvalid]="invalid"
[editable]="false"
[disabledItemHandler]="disabledItemHandler"
[(ngModel)]="selected"

View File

@@ -2,6 +2,7 @@
<tui-input-number
[tuiHintContent]="spec.description"
[tuiTextfieldPostfix]="spec.units || ''"
[pseudoInvalid]="invalid"
[precision]="Infinity"
[decimal]="spec.integer ? 'never' : 'not-zero'"
[min]="spec.min ?? -Infinity"

View File

@@ -1,6 +1,7 @@
<tui-select
[tuiHintContent]="spec.description"
[tuiTextfieldCleaner]="!spec.required"
[pseudoInvalid]="invalid"
[(ngModel)]="selected"
(focusedChange)="onFocus($event)"
>

View File

@@ -1,6 +1,7 @@
<tui-input
[tuiTextfieldCustomContent]="spec.masked ? toggle : ''"
[tuiHintContent]="spec.description"
[pseudoInvalid]="invalid"
[(ngModel)]="value"
(focusedChange)="onFocus($event)"
>

View File

@@ -1,5 +1,6 @@
<tui-text-area
[tuiHintContent]="spec.description"
[pseudoInvalid]="invalid"
[expandable]="true"
[rows]="6"
[maxLength]="spec.maxLength"

View File

@@ -9,8 +9,10 @@ import {
TuiHintModule,
TuiLinkModule,
TuiModeModule,
TuiSvgModule,
TuiTextfieldControllerModule,
TuiTooltipModule,
TuiWrapperModule,
} from '@taiga-ui/core'
import {
TuiElasticContainerModule,
@@ -40,6 +42,8 @@ import { FormArrayComponent } from './form-array/form-array.component'
import { FormControlComponent } from './form-control/form-control.component'
import { MustachePipe } from './mustache.pipe'
import { ControlDirective } from './control.directive'
import { FormColorComponent } from './form-color/form-color.component'
import { MaskitoModule } from '@maskito/angular'
@NgModule({
imports: [
@@ -66,10 +70,14 @@ import { ControlDirective } from './control.directive'
TuiFieldErrorPipeModule,
TuiValueChangesModule,
TuiElasticContainerModule,
MaskitoModule,
TuiSvgModule,
TuiWrapperModule,
],
declarations: [
FormGroupComponent,
FormControlComponent,
FormColorComponent,
FormTextComponent,
FormToggleComponent,
FormTextareaComponent,

View File

@@ -766,6 +766,14 @@ export module Mock {
},
},
},
background: {
name: 'Background',
type: 'color',
description: 'Background color for the service',
warning: null,
required: false,
default: '#000000',
},
advanced: {
name: 'Advanced',
type: 'object',

View File

@@ -28,6 +28,7 @@ import {
unionSelectKey,
ValueSpecTextarea,
unionValueKey,
ValueSpecColor,
} from 'start-sdk/lib/config/configTypes'
const Mustache = require('mustache')
@@ -123,6 +124,13 @@ export class FormService {
value = spec.default || null
}
return this.formBuilder.control(value, numberValidators(spec))
case 'color':
if (currentValue !== undefined) {
value = currentValue
} else {
value = spec.default || null
}
return this.formBuilder.control(value, colorValidators(spec))
case 'object':
return this.getFormGroup(spec.spec, [], currentValue)
case 'list':
@@ -198,6 +206,16 @@ function textareaValidators(spec: ValueSpecTextarea): ValidatorFn[] {
return validators
}
function colorValidators({ required }: ValueSpecColor): ValidatorFn[] {
const validators: ValidatorFn[] = [Validators.pattern(/^#[0-9a-f]{6}$/i)]
if (required) {
validators.push(Validators.required)
}
return validators
}
function numberValidators(
spec: ValueSpecNumber | ListValueSpecNumber,
): ValidatorFn[] {