Skip to content

Commit 156b75d

Browse files
committed
feat(multiple): add two-way binding for value prop
1 parent 515bf75 commit 156b75d

4 files changed

Lines changed: 99 additions & 45 deletions

File tree

projects/gradient-picker/src/lib/conic-gradient-picker.ts

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ import {
33
ChangeDetectionStrategy,
44
ChangeDetectorRef,
55
Component,
6+
EventEmitter,
67
forwardRef,
78
inject,
89
Input,
10+
Output,
911
ViewEncapsulation,
1012
} from '@angular/core';
1113
import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
@@ -58,20 +60,33 @@ import {
5860
export class ConicGradientPicker implements ControlValueAccessor {
5961
private cdr = inject(ChangeDetectorRef);
6062

63+
@Input()
64+
get value() {
65+
return this._value;
66+
}
67+
set value(newVal: string) {
68+
if (newVal !== this._value) {
69+
this._value = newVal || 'conic-gradient(transparent, #000000)';
70+
this.conicGradient = parseConicGradient(this._value);
71+
this.cdr.markForCheck();
72+
}
73+
}
74+
private _value = '';
75+
76+
@Output() valueChange = new EventEmitter<string>();
77+
6178
@Input({ transform: booleanAttribute }) disabled = false;
6279

6380
conicGradient: ConicGradientResult = {
6481
repeating: false,
65-
angle: '',
82+
angle: '0deg',
6683
position: {
6784
x: { type: 'keyword', value: 'center' },
6885
y: { type: 'keyword', value: 'center' },
6986
},
70-
stops: [{ color: '#000000' }],
87+
stops: [{ color: 'transparent' }, { color: '#000000' }],
7188
};
7289

73-
value = '';
74-
7590
angleUnits = angleUnits;
7691

7792
lengthUnits = lengthUnits;
@@ -95,9 +110,7 @@ export class ConicGradientPicker implements ControlValueAccessor {
95110
private onTouched: () => void = () => {};
96111

97112
writeValue(value: any): void {
98-
this.value = value || 'conic-gradient(transparent, #000000)';
99-
this.conicGradient = parseConicGradient(this.value);
100-
this.cdr.markForCheck();
113+
this.value = value;
101114
}
102115

103116
registerOnChange(fn: (value: string) => void): void {
@@ -114,8 +127,9 @@ export class ConicGradientPicker implements ControlValueAccessor {
114127
}
115128

116129
onGradientChange() {
117-
this.value = stringifyConicGradient(this.conicGradient);
118-
this.onChange(this.value);
130+
this._value = stringifyConicGradient(this.conicGradient);
131+
this.valueChange.emit(this._value);
132+
this.onChange(this._value);
119133
}
120134

121135
reverseStops() {

projects/gradient-picker/src/lib/gradient-picker.ts

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ import {
33
ChangeDetectionStrategy,
44
ChangeDetectorRef,
55
Component,
6+
EventEmitter,
67
forwardRef,
78
inject,
89
Input,
10+
Output,
911
ViewEncapsulation,
1012
} from '@angular/core';
1113
import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
@@ -45,8 +47,6 @@ import { parseGradient, stringifyGradient } from './utils';
4547
export class GradientPicker implements ControlValueAccessor {
4648
private cdr = inject(ChangeDetectorRef);
4749

48-
@Input({ transform: booleanAttribute }) disabled = false;
49-
5050
types = [
5151
{ label: 'Linear', value: 'linear' },
5252
{ label: 'Radial', value: 'radial' },
@@ -61,25 +61,36 @@ export class GradientPicker implements ControlValueAccessor {
6161
conic: 'conic-gradient(transparent, #000000)',
6262
};
6363

64-
value = this.gradient[this.type];
64+
@Input()
65+
get value() {
66+
return this._value;
67+
}
68+
set value(newVal: string) {
69+
if (newVal !== this._value) {
70+
if (!newVal) {
71+
this.type = 'linear';
72+
} else if (newVal.includes('linear')) {
73+
this.type = 'linear';
74+
} else if (newVal.includes('radial')) {
75+
this.type = 'radial';
76+
} else if (newVal.includes('conic')) {
77+
this.type = 'conic';
78+
}
79+
this._value = this.gradient[this.type] = newVal || 'linear-gradient(transparent, #000000)';
80+
this.cdr.markForCheck();
81+
}
82+
}
83+
private _value = this.gradient[this.type];
84+
85+
@Output() valueChange = new EventEmitter<string>();
86+
87+
@Input({ transform: booleanAttribute }) disabled = false;
6588

6689
private onChange: (value: string) => void = () => {};
6790
private onTouched: () => void = () => {};
6891

6992
writeValue(value: any): void {
70-
if (!value) {
71-
this.type = 'linear';
72-
} else if (value.includes('linear')) {
73-
this.type = 'linear';
74-
} else if (value.includes('radial')) {
75-
this.type = 'radial';
76-
} else if (value.includes('conic')) {
77-
this.type = 'conic';
78-
}
79-
if (value) {
80-
this.value = this.gradient[this.type] = value;
81-
}
82-
this.cdr.markForCheck();
93+
this.value = value;
8394
}
8495

8596
registerOnChange(fn: (value: string) => void): void {
@@ -96,8 +107,9 @@ export class GradientPicker implements ControlValueAccessor {
96107
}
97108

98109
onValueChange() {
99-
this.value = this.gradient[this.type];
100-
this.onChange(this.value);
110+
this._value = this.gradient[this.type];
111+
this.valueChange.emit(this._value);
112+
this.onChange(this._value);
101113
}
102114

103115
onTypeChange() {

projects/gradient-picker/src/lib/linear-gradient-picker.ts

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ import {
33
ChangeDetectionStrategy,
44
ChangeDetectorRef,
55
Component,
6+
EventEmitter,
67
forwardRef,
78
inject,
89
Input,
10+
Output,
911
ViewEncapsulation,
1012
} from '@angular/core';
1113
import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
@@ -55,16 +57,29 @@ import {
5557
export class LinearGradientPicker implements ControlValueAccessor {
5658
private cdr = inject(ChangeDetectorRef);
5759

60+
@Input()
61+
get value() {
62+
return this._value;
63+
}
64+
set value(newVal: string) {
65+
if (newVal !== this._value) {
66+
this._value = newVal || 'linear-gradient(transparent, #000000)';
67+
this.linearGradient = parseLinearGradient(this._value);
68+
this.cdr.markForCheck();
69+
}
70+
}
71+
private _value = '';
72+
73+
@Output() valueChange = new EventEmitter<string>();
74+
5875
@Input({ transform: booleanAttribute }) disabled = false;
5976

6077
linearGradient: LinearGradientResult = {
6178
repeating: false,
62-
orientation: { type: 'directional', value: '' },
63-
stops: [{ color: '#000000' }],
79+
orientation: { type: 'directional', value: 'bottom' },
80+
stops: [{ color: 'transparent' }, { color: '#000000' }],
6481
};
6582

66-
value = '';
67-
6883
angleUnits = angleUnits;
6984

7085
directionOptions = [
@@ -93,9 +108,7 @@ export class LinearGradientPicker implements ControlValueAccessor {
93108
private onTouched: () => void = () => {};
94109

95110
writeValue(value: any): void {
96-
this.value = value || 'linear-gradient(transparent, #000000)';
97-
this.linearGradient = parseLinearGradient(this.value);
98-
this.cdr.markForCheck();
111+
this.value = value;
99112
}
100113

101114
registerOnChange(fn: (value: string) => void): void {
@@ -112,8 +125,9 @@ export class LinearGradientPicker implements ControlValueAccessor {
112125
}
113126

114127
onGradientChange() {
115-
this.value = stringifyLinearGradient(this.linearGradient);
116-
this.onChange(this.value);
128+
this._value = stringifyLinearGradient(this.linearGradient);
129+
this.valueChange.emit(this._value);
130+
this.onChange(this._value);
117131
}
118132

119133
reverseStops() {

projects/gradient-picker/src/lib/radial-gradient-picker.ts

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ import {
33
ChangeDetectionStrategy,
44
ChangeDetectorRef,
55
Component,
6+
EventEmitter,
67
forwardRef,
78
inject,
89
Input,
10+
Output,
911
ViewEncapsulation,
1012
} from '@angular/core';
1113
import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
@@ -61,21 +63,34 @@ import {
6163
export class RadialGradientPicker implements ControlValueAccessor {
6264
private cdr = inject(ChangeDetectorRef);
6365

66+
@Input()
67+
get value() {
68+
return this._value;
69+
}
70+
set value(newVal: string) {
71+
if (newVal !== this._value) {
72+
this._value = newVal || 'radial-gradient(transparent, #000000)';
73+
this.radialGradient = parseRadialGradient(this.value);
74+
this.cdr.markForCheck();
75+
}
76+
}
77+
private _value = '';
78+
79+
@Output() valueChange = new EventEmitter<string>();
80+
6481
@Input({ transform: booleanAttribute }) disabled = false;
6582

6683
radialGradient: RadialGradientResult = {
6784
repeating: false,
6885
shape: 'ellipse',
69-
size: [],
86+
size: [{ type: 'keyword', value: 'farthest-corner' }],
7087
position: {
7188
x: { type: 'keyword', value: 'center' },
7289
y: { type: 'keyword', value: 'center' },
7390
},
74-
stops: [{ color: '#000000' }],
91+
stops: [{ color: 'transparent' }, { color: '#000000' }],
7592
};
7693

77-
value = '';
78-
7994
sizeKeywords = ['farthest-corner', 'farthest-side', 'closest-corner', 'closest-side'];
8095

8196
lengthUnits = lengthUnits;
@@ -99,9 +114,7 @@ export class RadialGradientPicker implements ControlValueAccessor {
99114
private onTouched: () => void = () => {};
100115

101116
writeValue(value: any): void {
102-
this.value = value || 'radial-gradient(transparent, #000000)';
103-
this.radialGradient = parseRadialGradient(this.value);
104-
this.cdr.markForCheck();
117+
this.value = value;
105118
}
106119

107120
registerOnChange(fn: (value: string) => void): void {
@@ -118,8 +131,9 @@ export class RadialGradientPicker implements ControlValueAccessor {
118131
}
119132

120133
onGradientChange() {
121-
this.value = stringifyRadialGradient(this.radialGradient);
122-
this.onChange(this.value);
134+
this._value = stringifyRadialGradient(this.radialGradient);
135+
this.valueChange.emit(this._value);
136+
this.onChange(this._value);
123137
}
124138

125139
reverseStops() {

0 commit comments

Comments
 (0)