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