1- import { Component , computed , effect , inject } from '@angular/core' ;
1+ import { Component , computed , inject } from '@angular/core' ;
22import { CommonModule } from '@angular/common' ;
33import { FormsModule } from '@angular/forms' ;
4- import { ConfigStoreService } from '../../../services/config-store.service' ;
54import { ColorThemesService } from '../../../services/color-themes.service' ;
65import { KittyColorConfig } from '../../../models/kitty-types' ;
76import { VersionBadgeComponent } from '../../shared/version-badge/version-badge.component' ;
87import { ColorInputComponent } from '../../shared/color-input/color-input.component' ;
98import { SliderInputComponent } from '../../shared/slider-input/slider-input.component' ;
9+ import { createFormHelper } from '../../../utils/form-helpers' ;
1010import { KittyVersionService } from '../../../services/kitty-version.service' ;
1111
1212@Component ( {
@@ -50,35 +50,35 @@ import { KittyVersionService } from '../../../services/kitty-version.service';
5050 <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
5151 <div class="form-group">
5252 <label class="block text-sm font-medium text-kitty-text mb-2">Foreground</label>
53- <app-color-input [value]="colors.foreground || '#000000'" (valueChange)="updateColor ('foreground', $event)" />
53+ <app-color-input [value]="colors() .foreground || '#000000'" (valueChange)="helper.updateField ('foreground', $event)" />
5454 </div>
5555
5656 <div class="form-group">
5757 <label class="block text-sm font-medium text-kitty-text mb-2">Background</label>
58- <app-color-input [value]="colors.background || '#ffffff'" (valueChange)="updateColor ('background', $event)" />
58+ <app-color-input [value]="colors() .background || '#ffffff'" (valueChange)="helper.updateField ('background', $event)" />
5959 </div>
6060 </div>
6161
6262 <div class="mt-6 form-group">
6363 <label class="block text-sm font-medium text-kitty-text mb-2">
6464 Background Opacity
65- <span class="text-kitty-accent font-bold ml-2">{{ (colors.background_opacity * 100).toFixed(0) }}%</span>
65+ <span class="text-kitty-accent font-bold ml-2">{{ (colors() .background_opacity * 100).toFixed(0) }}%</span>
6666 <span class="text-kitty-text-dim text-xs ml-2">Requires compositor support (e.g. picom, KWin)</span>
6767 </label>
6868 <app-slider-input
69- [value]="colors.background_opacity"
70- (valueChange)="updateNumberColor ('background_opacity', $event)"
69+ [value]="colors() .background_opacity"
70+ (valueChange)="helper.updateField ('background_opacity', $event)"
7171 [min]="0" [max]="1" [step]="0.05" />
7272 </div>
7373
74- @if (advancedMode()) {
74+ @if (helper. advancedMode()) {
7575 <div class="mt-4 form-group" [class.opacity-60]="!dynamicBackgroundOpacityAvailable()">
7676 <div class="flex items-center gap-2">
7777 <label class="flex items-center gap-3 cursor-pointer">
7878 <input
7979 type="checkbox"
80- [(ngModel)]="colors.dynamic_background_opacity"
81- (ngModelChange)="updateColors( )"
80+ [(ngModel)]="colors() .dynamic_background_opacity"
81+ (ngModelChange)="helper.updateField('dynamic_background_opacity', $event )"
8282 [disabled]="!dynamicBackgroundOpacityAvailable()"
8383 class="w-5 h-5 rounded flex-shrink-0 disabled:opacity-50"
8484 />
@@ -103,8 +103,8 @@ import { KittyVersionService } from '../../../services/kitty-version.service';
103103 </label>
104104 <input
105105 type="text"
106- [(ngModel)]="colors.background_image"
107- (ngModelChange)="updateColors( )"
106+ [(ngModel)]="colors() .background_image"
107+ (ngModelChange)="helper.updateField('background_image', $event )"
108108 class="w-full px-4 py-2 bg-kitty-bg border border-kitty-border rounded-lg text-kitty-text focus:outline-none focus:ring-2 focus:ring-kitty-primary font-mono text-sm"
109109 placeholder="none or /path/to/image.png"
110110 />
@@ -114,8 +114,8 @@ import { KittyVersionService } from '../../../services/kitty-version.service';
114114 <div class="form-group">
115115 <label class="block text-sm font-medium text-kitty-text mb-2">Image Layout</label>
116116 <select
117- [(ngModel)]="colors.background_image_layout"
118- (ngModelChange)="updateColors( )"
117+ [(ngModel)]="colors() .background_image_layout"
118+ (ngModelChange)="helper.updateField('background_image_layout', $event )"
119119 class="w-full px-4 py-2 bg-kitty-bg border border-kitty-border rounded-lg text-kitty-text focus:outline-none focus:ring-2 focus:ring-kitty-primary"
120120 >
121121 <option value="tiled">tiled</option>
@@ -131,8 +131,8 @@ import { KittyVersionService } from '../../../services/kitty-version.service';
131131 <label class="flex items-center gap-3 cursor-pointer mt-6">
132132 <input
133133 type="checkbox"
134- [(ngModel)]="colors.background_image_linear"
135- (ngModelChange)="updateColors( )"
134+ [(ngModel)]="colors() .background_image_linear"
135+ (ngModelChange)="helper.updateField('background_image_linear', $event )"
136136 class="w-5 h-5 rounded flex-shrink-0"
137137 />
138138 <div>
@@ -150,46 +150,46 @@ import { KittyVersionService } from '../../../services/kitty-version.service';
150150 <div class="form-group">
151151 <label class="block text-sm font-medium text-kitty-text mb-2">
152152 Background Blur
153- <span class="text-kitty-accent ml-2">{{ colors.background_blur }}px</span>
153+ <span class="text-kitty-accent ml-2">{{ colors() .background_blur }}px</span>
154154 </label>
155155 <app-slider-input
156- [value]="colors.background_blur"
157- (valueChange)="updateNumberColor ('background_blur', $event)"
156+ [value]="colors() .background_blur"
157+ (valueChange)="helper.updateField ('background_blur', $event)"
158158 [min]="0" [max]="64" [step]="1" />
159159 </div>
160160
161161 <div class="form-group">
162162 <label class="block text-sm font-medium text-kitty-text mb-2">
163163 Background Tint
164- <span class="text-kitty-accent ml-2">{{ (colors.background_tint * 100).toFixed(0) }}%</span>
164+ <span class="text-kitty-accent ml-2">{{ (colors() .background_tint * 100).toFixed(0) }}%</span>
165165 </label>
166166 <app-slider-input
167- [value]="colors.background_tint"
168- (valueChange)="updateNumberColor ('background_tint', $event)"
167+ [value]="colors() .background_tint"
168+ (valueChange)="helper.updateField ('background_tint', $event)"
169169 [min]="0" [max]="1" [step]="0.05" />
170170 </div>
171171
172172 <div class="form-group">
173173 <label class="block text-sm font-medium text-kitty-text mb-2">
174174 Background Tint Gaps
175- <span class="text-kitty-accent ml-2">{{ (colors.background_tint_gaps * 100).toFixed(0) }}%</span>
175+ <span class="text-kitty-accent ml-2">{{ (colors() .background_tint_gaps * 100).toFixed(0) }}%</span>
176176 <span class="text-kitty-text-dim text-xs ml-1">(padding color tinting)</span>
177177 </label>
178178 <app-slider-input
179- [value]="colors.background_tint_gaps"
180- (valueChange)="updateNumberColor ('background_tint_gaps', $event)"
179+ [value]="colors() .background_tint_gaps"
180+ (valueChange)="helper.updateField ('background_tint_gaps', $event)"
181181 [min]="0" [max]="1" [step]="0.05" />
182182 </div>
183183
184184 <div class="form-group">
185185 <label class="block text-sm font-medium text-kitty-text mb-2">
186186 Dim Opacity
187- <span class="text-kitty-accent ml-2">{{ (colors.dim_opacity * 100).toFixed(0) }}%</span>
187+ <span class="text-kitty-accent ml-2">{{ (colors() .dim_opacity * 100).toFixed(0) }}%</span>
188188 <span class="text-kitty-text-dim text-xs ml-1">(inactive panes)</span>
189189 </label>
190190 <app-slider-input
191- [value]="colors.dim_opacity"
192- (valueChange)="updateNumberColor ('dim_opacity', $event)"
191+ [value]="colors() .dim_opacity"
192+ (valueChange)="helper.updateField ('dim_opacity', $event)"
193193 [min]="0" [max]="1" [step]="0.05" />
194194 </div>
195195 </div>
@@ -200,12 +200,12 @@ import { KittyVersionService } from '../../../services/kitty-version.service';
200200 <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
201201 <div class="form-group">
202202 <label class="block text-sm font-medium text-kitty-text mb-2">Selection Foreground</label>
203- <app-color-input [value]="colors.selection_foreground || '#000000'" (valueChange)="updateColor ('selection_foreground', $event)" />
203+ <app-color-input [value]="colors() .selection_foreground || '#000000'" (valueChange)="helper.updateField ('selection_foreground', $event)" />
204204 </div>
205205
206206 <div class="form-group">
207207 <label class="block text-sm font-medium text-kitty-text mb-2">Selection Background</label>
208- <app-color-input [value]="colors.selection_background || '#ffffff'" (valueChange)="updateColor ('selection_background', $event)" />
208+ <app-color-input [value]="colors() .selection_background || '#ffffff'" (valueChange)="helper.updateField ('selection_background', $event)" />
209209 </div>
210210 </div>
211211 </div>
@@ -220,7 +220,7 @@ import { KittyVersionService } from '../../../services/kitty-version.service';
220220 <p class="text-kitty-text-dim text-sm mb-4">Set per-color transparency. Format: color@opacity (e.g., red@0.5, #ff0000@0.3)</p>
221221 <div class="form-group">
222222 <textarea
223- [ngModel]="colors.transparent_background_colors.join('\n')"
223+ [ngModel]="colors() .transparent_background_colors.join('\n')"
224224 (ngModelChange)="setTransparentColors($event)"
225225 [disabled]="!transparentBackgroundColorsAvailable()"
226226 rows="3"
@@ -283,74 +283,53 @@ import { KittyVersionService } from '../../../services/kitty-version.service';
283283 styles : [ ]
284284} )
285285export class ColorsFormComponent {
286- private readonly configStore = inject ( ConfigStoreService ) ;
287286 private readonly versionService = inject ( KittyVersionService ) ;
288287 readonly colorThemesService = inject ( ColorThemesService ) ;
289288
290- readonly advancedMode = computed ( ( ) => this . configStore . advancedMode ( ) ) ;
289+ readonly helper = createFormHelper ( 'colors' ) ;
290+ readonly colors = this . helper . state . asReadonly ( ) ;
291291 readonly transparentBackgroundColorsAvailable = computed ( ( ) => this . versionService . isOptionAvailable ( 'transparent_background_colors' ) ) ;
292292 readonly dynamicBackgroundOpacityAvailable = computed ( ( ) => this . versionService . isOptionAvailable ( 'dynamic_background_opacity' ) ) ;
293- colors : KittyColorConfig = { ...this . configStore . configState ( ) . colors } ;
294293 readonly colorIndices = Array . from ( { length : 16 } , ( _ , i ) => i ) ;
295294 readonly colorNames = [ 'black' , 'red' , 'green' , 'yellow' , 'blue' , 'magenta' , 'cyan' , 'white' ,
296295 'br.black' , 'br.red' , 'br.green' , 'br.yellow' , 'br.blue' , 'br.magenta' , 'br.cyan' , 'br.white' ] ;
297296
298- constructor ( ) {
299- effect ( ( ) => {
300- this . colors = { ...this . configStore . configState ( ) . colors } ;
301- } ) ;
302- }
303-
304297 applyTheme ( themeName : string ) : void {
305298 const theme = this . colorThemesService . getTheme ( themeName ) ;
306299 if ( theme ) {
307- this . colors = { ...this . colors , ...theme . colors } ;
308- this . updateColors ( ) ;
300+ const updatedColors = { ...this . colors ( ) , ...theme . colors } ;
301+ this . helper . state . set ( updatedColors ) ;
302+ this . helper . update ( ) ;
309303 }
310304 }
311305
312- updateColors ( ) : void {
313- this . configStore . updateSection ( 'colors' , { ...this . colors } ) ;
314- }
315-
316- updateColor ( key : keyof KittyColorConfig , value : string ) : void {
317- this . colors = { ...this . colors , [ key ] : value } ;
318- this . updateColors ( ) ;
319- }
320-
321- updateNumberColor ( key : keyof KittyColorConfig , value : number ) : void {
322- this . colors = { ...this . colors , [ key ] : value } ;
323- this . updateColors ( ) ;
324- }
325-
326- getThemeColor ( colors : Partial < KittyColorConfig > , index : number ) : string {
327- const color = colors [ `color${ index } ` as keyof KittyColorConfig ] ;
306+ getThemeColor ( themeColors : Partial < KittyColorConfig > , index : number ) : string {
307+ const color = themeColors [ `color${ index } ` as keyof KittyColorConfig ] ;
328308 return typeof color === 'string' ? color : '#000' ;
329309 }
330310
331311 getColorValue ( index : number ) : string {
332- return ( this . colors as unknown as Record < string , unknown > ) [ `color${ index } ` ] as string || '#000000' ;
312+ return ( this . colors ( ) as unknown as Record < string , unknown > ) [ `color${ index } ` ] as string || '#000000' ;
333313 }
334314
335315 setColorValue ( index : number , value : string ) : void {
336- ( this . colors as unknown as Record < string , unknown > ) [ `color${ index } ` ] = value ;
337- this . updateColors ( ) ;
316+ const key = `color${ index } ` as keyof KittyColorConfig ;
317+ this . helper . updateField ( key , value ) ;
338318 }
339319
340320 getMarkColor ( group : number , type : 'foreground' | 'background' ) : string {
341321 const key = `mark${ group } _${ type } ` as keyof KittyColorConfig ;
342- const val = this . colors [ key ] as string ;
322+ const val = this . colors ( ) [ key ] as string ;
343323 return val || ( type === 'foreground' ? '#000000' : '#ffffff' ) ;
344324 }
345325
346326 setMarkColor ( group : number , type : 'foreground' | 'background' , value : string ) : void {
347327 const key = `mark${ group } _${ type } ` as keyof KittyColorConfig ;
348- ( this . colors as unknown as Record < string , unknown > ) [ key ] = value ;
349- this . updateColors ( ) ;
328+ this . helper . updateField ( key , value ) ;
350329 }
351330
352331 setTransparentColors ( value : string ) : void {
353- this . colors = { ... this . colors , transparent_background_colors : value . split ( '\n' ) . filter ( l => l . trim ( ) ) } ;
354- this . updateColors ( ) ;
332+ const colors = value . split ( '\n' ) . filter ( l => l . trim ( ) ) ;
333+ this . helper . updateField ( 'transparent_background_colors' , colors ) ;
355334 }
356335}
0 commit comments