feat(project-editor): migrate theme section to Select/ColorPicker/SectionCard

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
sdarbinyan
2026-07-16 02:01:34 +04:00
parent 3bf1f31a3c
commit ccbf8c6e5c
2 changed files with 39 additions and 41 deletions

View File

@@ -1,35 +1,20 @@
@if (bootstrap(); as bootstrap) { @if (bootstrap(); as bootstrap) {
<section class="editor-section-card"> <app-section-card [title]="'builder.theme' | translate">
<h2>{{ 'builder.theme' | translate }}</h2>
<div class="editor-grid two"> <div class="editor-grid two">
<app-form-field [label]="'builder.primaryColor' | translate" [hint]="'builder.primaryColorDesc' | translate"><input type="color" [ngModel]="bootstrap.theme.palette.primary" (ngModelChange)="updatePalette('primary', $event)" /></app-form-field> <app-form-field [label]="'builder.primaryColor' | translate" [hint]="'builder.primaryColorDesc' | translate"><app-color-picker [ngModel]="bootstrap.theme.palette.primary" (ngModelChange)="updatePalette('primary', $event)" /></app-form-field>
<app-form-field [label]="'builder.secondaryColor' | translate" [hint]="'builder.secondaryColorDesc' | translate"><input type="color" [ngModel]="bootstrap.theme.palette.secondary" (ngModelChange)="updatePalette('secondary', $event)" /></app-form-field> <app-form-field [label]="'builder.secondaryColor' | translate" [hint]="'builder.secondaryColorDesc' | translate"><app-color-picker [ngModel]="bootstrap.theme.palette.secondary" (ngModelChange)="updatePalette('secondary', $event)" /></app-form-field>
<app-form-field [label]="'builder.backgroundColor' | translate" [hint]="'builder.backgroundColorDesc' | translate"><input type="color" [ngModel]="bootstrap.theme.palette.backgroundPrimary" (ngModelChange)="updatePalette('backgroundPrimary', $event)" /></app-form-field> <app-form-field [label]="'builder.backgroundColor' | translate" [hint]="'builder.backgroundColorDesc' | translate"><app-color-picker [ngModel]="bootstrap.theme.palette.backgroundPrimary" (ngModelChange)="updatePalette('backgroundPrimary', $event)" /></app-form-field>
<app-form-field [label]="'builder.surfaceColor' | translate" [hint]="'builder.surfaceColorDesc' | translate"><input type="color" [ngModel]="bootstrap.theme.palette.backgroundSecondary" (ngModelChange)="updatePalette('backgroundSecondary', $event)" /></app-form-field> <app-form-field [label]="'builder.surfaceColor' | translate" [hint]="'builder.surfaceColorDesc' | translate"><app-color-picker [ngModel]="bootstrap.theme.palette.backgroundSecondary" (ngModelChange)="updatePalette('backgroundSecondary', $event)" /></app-form-field>
<app-form-field [label]="'builder.textColor' | translate" [hint]="'builder.textColorDesc' | translate"><input type="color" [ngModel]="bootstrap.theme.palette.textPrimary" (ngModelChange)="updatePalette('textPrimary', $event)" /></app-form-field> <app-form-field [label]="'builder.textColor' | translate" [hint]="'builder.textColorDesc' | translate"><app-color-picker [ngModel]="bootstrap.theme.palette.textPrimary" (ngModelChange)="updatePalette('textPrimary', $event)" /></app-form-field>
<app-form-field [label]="'builder.successColor' | translate" [hint]="'builder.successColorDesc' | translate"><input type="color" [ngModel]="bootstrap.theme.palette.success" (ngModelChange)="updatePalette('success', $event)" /></app-form-field> <app-form-field [label]="'builder.successColor' | translate" [hint]="'builder.successColorDesc' | translate"><app-color-picker [ngModel]="bootstrap.theme.palette.success" (ngModelChange)="updatePalette('success', $event)" /></app-form-field>
<app-form-field [label]="'builder.warningColor' | translate" [hint]="'builder.warningColorDesc' | translate"><input type="color" [ngModel]="bootstrap.theme.palette.warning" (ngModelChange)="updatePalette('warning', $event)" /></app-form-field> <app-form-field [label]="'builder.warningColor' | translate" [hint]="'builder.warningColorDesc' | translate"><app-color-picker [ngModel]="bootstrap.theme.palette.warning" (ngModelChange)="updatePalette('warning', $event)" /></app-form-field>
<app-form-field [label]="'builder.dangerColor' | translate" [hint]="'builder.dangerColorDesc' | translate"><input type="color" [ngModel]="bootstrap.theme.palette.danger" (ngModelChange)="updatePalette('danger', $event)" /></app-form-field> <app-form-field [label]="'builder.dangerColor' | translate" [hint]="'builder.dangerColorDesc' | translate"><app-color-picker [ngModel]="bootstrap.theme.palette.danger" (ngModelChange)="updatePalette('danger', $event)" /></app-form-field>
<label> <app-form-field [label]="'builder.themeModeLabel' | translate" [hint]="'builder.themeModeDesc' | translate">
<span>{{ 'builder.themeModeLabel' | translate }}</span> <app-select [options]="themeModeSelectOptions()" [ngModel]="bootstrap.theme.mode" (ngModelChange)="updateThemeMode($event)" />
<small class="field-desc">{{ 'builder.themeModeDesc' | translate }}</small> </app-form-field>
<select [ngModel]="bootstrap.theme.mode" (ngModelChange)="updateThemeMode($event)"> <app-form-field [label]="'builder.siteLayoutLabel' | translate" [hint]="'builder.siteLayoutDesc' | translate">
@for (option of themeModeOptions; track option.value) { <app-select [options]="siteLayoutSelectOptions()" [ngModel]="bootstrap.layout?.type || 'default'" (ngModelChange)="updateSiteLayout($event)" />
<option [value]="option.value">{{ option.labelKey | translate }}</option> </app-form-field>
}
</select>
<small class="field-desc">{{ themeModeDescKey(bootstrap.theme.mode) | translate }}</small>
</label>
<label>
<span>{{ 'builder.siteLayoutLabel' | translate }}</span>
<small class="field-desc">{{ 'builder.siteLayoutDesc' | translate }}</small>
<select [ngModel]="bootstrap.layout?.type || 'default'" (ngModelChange)="updateSiteLayout($event)">
@for (option of siteLayoutOptions; track option.value) {
<option [value]="option.value">{{ option.labelKey | translate }}</option>
}
</select>
<small class="field-desc">{{ siteLayoutDescKey(bootstrap.layout?.type || 'default') | translate }}</small>
</label>
</div> </div>
</section> </app-section-card>
} }

View File

@@ -1,9 +1,13 @@
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; import { ChangeDetectionStrategy, Component, computed, inject } from '@angular/core';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { ProjectEditorFacade } from '../facade/project-editor.facade'; import { ProjectEditorFacade } from '../facade/project-editor.facade';
import { TranslatePipe } from '../../../i18n/translate.pipe'; import { TranslatePipe } from '../../../i18n/translate.pipe';
import { TranslateService } from '../../../i18n/translate.service';
import { PlatformLayoutType, ThemePaletteConfig } from '../../../shared/models/config'; import { PlatformLayoutType, ThemePaletteConfig } from '../../../shared/models/config';
import { FormFieldComponent } from '../../../shared/ui/form-field/form-field.component'; import { FormFieldComponent } from '../../../shared/ui/form-field/form-field.component';
import { SectionCardComponent } from '../../../shared/ui/section-card/section-card.component';
import { SelectComponent, SelectOption } from '../../../shared/ui/select/select.component';
import { ColorPickerComponent } from '../../../shared/ui/color-picker/color-picker.component';
export interface ThemeModeOption { export interface ThemeModeOption {
value: 'light' | 'dark' | 'system'; value: 'light' | 'dark' | 'system';
@@ -20,13 +24,14 @@ export interface SiteLayoutOption {
@Component({ @Component({
selector: 'app-project-editor-theme-section', selector: 'app-project-editor-theme-section',
standalone: true, standalone: true,
imports: [FormsModule, TranslatePipe, FormFieldComponent], imports: [FormsModule, TranslatePipe, FormFieldComponent, SectionCardComponent, SelectComponent, ColorPickerComponent],
templateUrl: './theme-section.component.html', templateUrl: './theme-section.component.html',
styleUrls: ['./section.shared.scss'], styleUrls: ['./section.shared.scss'],
changeDetection: ChangeDetectionStrategy.OnPush changeDetection: ChangeDetectionStrategy.OnPush
}) })
export class ProjectEditorThemeSectionComponent { export class ProjectEditorThemeSectionComponent {
private readonly facade = inject(ProjectEditorFacade); private readonly facade = inject(ProjectEditorFacade);
private readonly translate = inject(TranslateService);
readonly bootstrap = this.facade.bootstrap; readonly bootstrap = this.facade.bootstrap;
readonly themeModeOptions: ThemeModeOption[] = [ readonly themeModeOptions: ThemeModeOption[] = [
@@ -42,6 +47,22 @@ export class ProjectEditorThemeSectionComponent {
{ value: 'minimal', labelKey: 'builder.siteLayoutMinimal', descKey: 'builder.siteLayoutMinimalDesc' }, { value: 'minimal', labelKey: 'builder.siteLayoutMinimal', descKey: 'builder.siteLayoutMinimalDesc' },
]; ];
readonly themeModeSelectOptions = computed<SelectOption[]>(() =>
this.themeModeOptions.map(option => ({
value: option.value,
label: this.translate.t(option.labelKey),
description: this.translate.t(option.descKey)
}))
);
readonly siteLayoutSelectOptions = computed<SelectOption[]>(() =>
this.siteLayoutOptions.map(option => ({
value: option.value,
label: this.translate.t(option.labelKey),
description: this.translate.t(option.descKey)
}))
);
updatePalette<K extends keyof ThemePaletteConfig>(key: K, value: string): void { updatePalette<K extends keyof ThemePaletteConfig>(key: K, value: string): void {
this.facade.updateBootstrap(current => ({ this.facade.updateBootstrap(current => ({
...current, ...current,
@@ -62,12 +83,4 @@ export class ProjectEditorThemeSectionComponent {
layout: { ...current.layout, type: type as PlatformLayoutType } layout: { ...current.layout, type: type as PlatformLayoutType }
})); }));
} }
themeModeDescKey(mode: string): string {
return this.themeModeOptions.find(option => option.value === mode)?.descKey ?? '';
}
siteLayoutDescKey(type: string): string {
return this.siteLayoutOptions.find(option => option.value === type)?.descKey ?? '';
}
} }