10 changed files with 380 additions and 11 deletions
@ -0,0 +1,18 @@ |
|||
<div fxLayoutAlign="row"> |
|||
<div fxLayoutAlign="row"> |
|||
<mat-form-field class="mat-block"> |
|||
<input matInput type="number" pattern="[0-9]*" min="0" max="255" [value]="value?.getRed().toString()" (input)="onInputChange($event, 'R')"> |
|||
</mat-form-field> |
|||
<mat-form-field class="mat-block"> |
|||
<input matInput type="number" pattern="[0-9]*" min="0" max="255" [value]="value?.getGreen().toString()" (input)="onInputChange($event, 'G')"> |
|||
</mat-form-field> |
|||
<mat-form-field class="mat-block"> |
|||
<input matInput type="number" pattern="[0-9]*" min="0" max="255" [value]="value?.getBlue().toString()" (input)="onInputChange($event, 'B')"> |
|||
</mat-form-field> |
|||
</div> |
|||
|
|||
<mat-form-field class="mat-block"> |
|||
<input matInput type="number" min="0" max="1" [value]="value?.getAlpha().toString()" (input)="onInputChange($event, 'A')"> |
|||
</mat-form-field> |
|||
</div> |
|||
|
|||
@ -0,0 +1,70 @@ |
|||
import { |
|||
ChangeDetectionStrategy, |
|||
ChangeDetectorRef, |
|||
Component, |
|||
EventEmitter, |
|||
Input, |
|||
OnInit, |
|||
Output |
|||
} from '@angular/core'; |
|||
import { Color } from '@iplab/ngx-color-picker'; |
|||
import { ColorType } from '@shared/components/color-picker/color-picker.component'; |
|||
|
|||
@Component({ |
|||
selector: `tb-color-picker-input-component`, |
|||
templateUrl: `./color-picker-input.component.html`, |
|||
styleUrls: [], |
|||
changeDetection: ChangeDetectionStrategy.OnPush |
|||
}) |
|||
export class ColorPickerInputComponent { |
|||
|
|||
@Input() |
|||
public hue: Color; |
|||
|
|||
@Output() |
|||
public hueChange = new EventEmitter<Color>(false); |
|||
|
|||
@Input() |
|||
public color: Color; |
|||
|
|||
@Output() |
|||
public colorChange = new EventEmitter<Color>(false); |
|||
|
|||
public labelVisible: boolean; |
|||
|
|||
@Input() |
|||
public set label(value) { |
|||
this.labelVisible = true; |
|||
} |
|||
|
|||
@Input() |
|||
public colorFormat: string; |
|||
|
|||
public isAlphaVisible = true; |
|||
|
|||
@Input() |
|||
public set alpha(isVisible: boolean) { |
|||
this.isAlphaVisible = isVisible; |
|||
} |
|||
|
|||
public get value() { |
|||
return this.color ? this.color.getRgba() : null; |
|||
} |
|||
|
|||
constructor() { |
|||
} |
|||
|
|||
public onInputChange(newValue, color: 'R' | 'G' | 'B' | 'A') { |
|||
const value = this.value; |
|||
const red = color === 'R' ? newValue : value.red; |
|||
const green = color === 'G' ? newValue : value.green; |
|||
const blue = color === 'B' ? newValue : value.blue; |
|||
const alpha = color === 'A' ? newValue : value.alpha; |
|||
|
|||
const newColor = new Color().setRgba(red, green, blue, alpha); |
|||
const hue = new Color().setHsva(newColor.getHsva().hue); |
|||
|
|||
this.hueChange.emit(hue); |
|||
this.colorChange.emit(newColor); |
|||
} |
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
<saturation-component class="saturation-component" [hue]="control.hue" [(color)]="control.value"></saturation-component> |
|||
|
|||
<div class="controls"> |
|||
<div class="controls-row hue-alpha"> |
|||
<div class="column"> |
|||
<indicator-component [colorType]="presentations[selectedPresentation]" [color]="control.value"></indicator-component> |
|||
</div> |
|||
<div class="column" class="hue-alpha-range"> |
|||
<hue-component [(hue)]="control.hue" [(color)]="control.value"></hue-component> |
|||
<alpha-component *ngIf="control.alphaChannelVisibilityChanges | async" [(color)]="control.value"></alpha-component> |
|||
</div> |
|||
</div> |
|||
|
|||
<mat-form-field class="mat-block"> |
|||
<mat-select [(value)]="this.control.initType" (valueChange)="changeColorFormat($event)"> |
|||
<mat-option *ngFor="let type of presentations" [value]="type"> |
|||
{{type}} |
|||
</mat-option> |
|||
</mat-select> |
|||
</mat-form-field> |
|||
|
|||
<tb-color-picker-input-component [alpha]="control.alphaChannelVisibilityChanges | async" [colorFormat]="this.control.initType" [(color)]="control.value" [(hue)]="control.hue"> |
|||
</tb-color-picker-input-component> |
|||
|
|||
<!-- <div class="controls-row presentation">--> |
|||
<!-- <div class="column" [ngSwitch]="presentations[selectedPresentation]">--> |
|||
<!-- <rgba-input-component *ngSwitchCase="'rgba'" [alpha]="control.alphaChannelVisibilityChanges | async" label [(color)]="control.value" [(hue)]="control.hue"></rgba-input-component>--> |
|||
<!-- <hsla-input-component *ngSwitchCase="'hsla'" [alpha]="control.alphaChannelVisibilityChanges | async" label [(color)]="control.value" [(hue)]="control.hue"></hsla-input-component>--> |
|||
<!-- <hex-input-component *ngSwitchCase="'hex'" label prefix="#" [(color)]="control.value" [(hue)]="control.hue"></hex-input-component>--> |
|||
<!-- </div>--> |
|||
<!-- <div class="column type-column">--> |
|||
<!-- <span class="type-btn" (click)="changePresentation()"></span>--> |
|||
<!-- </div>--> |
|||
<!-- </div>--> |
|||
</div> |
|||
|
|||
<!--<color-presets-component *ngIf="control.presetsVisibilityChanges | async" [(color)]="control.value" [colorPresets]="control.presets" [(hue)]="control.hue"></color-presets-component>--> |
|||
@ -0,0 +1,110 @@ |
|||
:host { |
|||
display: block; |
|||
width: 100%; |
|||
max-width: 320px; |
|||
min-width: 100%; |
|||
border-radius: 2px; |
|||
background: #fff; |
|||
|
|||
::ng-deep { |
|||
.saturation-component { |
|||
height: 200px; |
|||
border-radius: 8px; |
|||
div.pointer { |
|||
border-width: 2px; |
|||
width: 16px; |
|||
height: 16px; |
|||
} |
|||
} |
|||
|
|||
indicator-component { |
|||
svg { |
|||
vertical-align: -70% !important; |
|||
} |
|||
} |
|||
|
|||
.hue-alpha-range { |
|||
alpha-component, hue-component { |
|||
height: 18px; |
|||
border: 1px solid rgba(0, 0, 0, 0.1); |
|||
.pointer { |
|||
height: 18px; |
|||
width: 18px; |
|||
background: none; |
|||
border: 2px solid #fff; |
|||
} |
|||
.gradient-color { |
|||
border-radius: 24px; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
.controls { |
|||
padding: 15px 0; |
|||
} |
|||
|
|||
.controls-row { |
|||
display: table; |
|||
width: 100%; |
|||
} |
|||
|
|||
.column { |
|||
display: table-cell; |
|||
vertical-align: middle; |
|||
} |
|||
|
|||
.hue-alpha .column:first-child { |
|||
width: 42px; |
|||
padding: 0 10px 0 0; |
|||
} |
|||
|
|||
indicator-component { |
|||
height: 48px; |
|||
width: 48px; |
|||
border-radius: 8px; |
|||
background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMUlEQVQ4T2NkYGAQYcAP3uCTZhw1gGGYhAGBZIA/nYDCgBDAm9BGDWAAJyRCgLaBCAAgXwixzAS0pgAAAABJRU5ErkJggg==') repeat; |
|||
} |
|||
|
|||
.hue-alpha-range { |
|||
hue-component, alpha-component { |
|||
border-radius: 24px; |
|||
} |
|||
} |
|||
|
|||
hue-component { |
|||
margin-bottom: 16px; |
|||
} |
|||
|
|||
color-presets-component { |
|||
border-top: 1px solid #d0d0d0; |
|||
padding: 12px; |
|||
|
|||
::ng-deep .presets-row { |
|||
padding: 12px 0 0; |
|||
} |
|||
} |
|||
|
|||
.type-btn { |
|||
display: inline-block; |
|||
height: 20px; |
|||
width: 20px; |
|||
background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAgCAYAAAAffCjxAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAACewAAAnsB01CO3AAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAIASURBVEiJ7ZY9axRRFIafsxMStrLQJpAgpBFhi+C9w1YSo00I6RZ/g9vZpBf/QOr4GyRgkSKNSrAadsZqQGwCkuAWyRZJsySwvhZ7N/vhzrgbLH3Ld8597jlzz50zJokyxXH8DqDVar0qi6v8BbItqSGpEcfxdlmsFWXkvX8AfAVWg3UKPEnT9GKujMzsAFgZsVaCN1VTQd77XUnrgE1kv+6935268WRpzrnHZvYRWC7YvC3pRZZl3wozqtVqiyH9IgjAspkd1Gq1xUJQtVrdB9ZKIAOthdg/Qc65LUk7wNIMoCVJO865rYFhkqjX6/d7vV4GPJwBMqofURS5JEk6FYBer/eeYb/Mo9WwFnPOvQbeAvfuAAK4BN4sAJtAG/gJIElmNuiJyba3EGNmZiPeZuEVmVell/Y/6N+CzDn3AXhEOOo7Hv/3BeAz8IzQkMPnJbuPx1wC+yYJ7/0nYIP5S/0FHKdp+rwCEEXRS/rf5Hl1Gtb2M0iSpCOpCZzPATmX1EySpHMLAsiy7MjMDoHrGSDXZnaYZdnRwBh7J91utwmczAA6CbG3GgPleX4jqUH/a1CktqRGnuc3hSCAMB32gKspkCtgb3KCQMmkjeP4WNJThrNNZval1WptTIsv7JtQ4tmIdRa8qSoEpWl6YWZNoAN0zKxZNPehpLSBZv2t+Q0CJ9lLnARQLAAAAABJRU5ErkJggg==') no-repeat center; |
|||
background-size: 6px 12px; |
|||
|
|||
&:hover { |
|||
background-color: #eee; |
|||
} |
|||
} |
|||
|
|||
.type-column { |
|||
width: 25px; |
|||
text-align: right; |
|||
} |
|||
|
|||
.presentation { |
|||
padding: 12px 0 0; |
|||
} |
|||
@ -0,0 +1,106 @@ |
|||
import { |
|||
ChangeDetectionStrategy, |
|||
ChangeDetectorRef, |
|||
Component, |
|||
EventEmitter, |
|||
Input, |
|||
OnChanges, |
|||
OnDestroy, |
|||
OnInit, |
|||
Output, SimpleChanges |
|||
} from '@angular/core'; |
|||
import { Color, ColorPickerControl } from '@iplab/ngx-color-picker'; |
|||
import { Subscription } from 'rxjs'; |
|||
export enum ColorType { |
|||
hex = 'hex', |
|||
hexa = 'hexa', |
|||
rgba = 'rgba', |
|||
rgb = 'rgb', |
|||
hsla = 'hsla', |
|||
hsl = 'hsl', |
|||
cmyk = 'cmyk' |
|||
} |
|||
|
|||
@Component({ |
|||
selector: `tb-color-picker`, |
|||
templateUrl: `./color-picker.component.html`, |
|||
styleUrls: [`./color-picker.component.scss`], |
|||
changeDetection: ChangeDetectionStrategy.OnPush |
|||
}) |
|||
export class ColorPickerComponent implements OnInit, OnChanges, OnDestroy { |
|||
|
|||
public selectedPresentation = 0; |
|||
public presentations = [ColorType.hex, ColorType.hexa, ColorType.rgb, ColorType.rgba, ColorType.hsl, ColorType.hsla]; |
|||
|
|||
@Input() |
|||
public color: string; |
|||
|
|||
@Input() |
|||
public control: ColorPickerControl; |
|||
|
|||
@Output() |
|||
public colorChange: EventEmitter<string> = new EventEmitter(false); |
|||
|
|||
private subscriptions: Array<Subscription> = []; |
|||
|
|||
constructor(private readonly cdr: ChangeDetectorRef) { |
|||
} |
|||
|
|||
public ngOnInit(): void { |
|||
if (!this.control) { |
|||
this.control = new ColorPickerControl(); |
|||
} |
|||
|
|||
if (this.color) { |
|||
this.control.setValueFrom(this.color); |
|||
} |
|||
|
|||
this.subscriptions.push( |
|||
this.control.valueChanges.subscribe((value) => { |
|||
this.cdr.markForCheck(); |
|||
this.colorChange.emit(this.getValueByType(value, this.control.initType)); |
|||
}) |
|||
); |
|||
} |
|||
|
|||
changeColorFormat(event: Event) { |
|||
this.colorChange.emit(this.getValueByType(this.control.value, this.control.initType)); |
|||
} |
|||
|
|||
public ngOnDestroy(): void { |
|||
this.cdr.detach(); |
|||
this.subscriptions.forEach((subscription) => subscription.unsubscribe()); |
|||
this.subscriptions.length = 0; |
|||
} |
|||
|
|||
public ngOnChanges(changes: SimpleChanges): void { |
|||
if (this.color && this.control && this.getValueByType(this.control.value, this.control.initType) !== this.color) { |
|||
this.control.setValueFrom(this.color); |
|||
} |
|||
} |
|||
|
|||
public changePresentation(): void { |
|||
this.selectedPresentation = |
|||
this.selectedPresentation === this.presentations.length - 1 ? 0 : this.selectedPresentation + 1; |
|||
} |
|||
|
|||
getValueByType(color: Color, type: ColorType): string { |
|||
switch (type) { |
|||
case ColorType.hex: |
|||
return color.toHexString(); |
|||
case ColorType.hexa: |
|||
return color.toHexString(true); |
|||
case ColorType.rgb: |
|||
return color.toRgbString(); |
|||
case ColorType.rgba: |
|||
return color.toRgbaString(); |
|||
case ColorType.hsl: |
|||
return color.toHslString(); |
|||
case ColorType.hsla: |
|||
return color.toHslaString(); |
|||
default: |
|||
return color.toRgbaString(); |
|||
} |
|||
} |
|||
|
|||
} |
|||
Loading…
Reference in new issue