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) {
<section class="editor-section-card">
<h2>{{ 'builder.theme' | translate }}</h2>
<app-section-card [title]="'builder.theme' | translate">
<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.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.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.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.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.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.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.dangerColor' | translate" [hint]="'builder.dangerColorDesc' | translate"><input type="color" [ngModel]="bootstrap.theme.palette.danger" (ngModelChange)="updatePalette('danger', $event)" /></app-form-field>
<label>
<span>{{ 'builder.themeModeLabel' | translate }}</span>
<small class="field-desc">{{ 'builder.themeModeDesc' | translate }}</small>
<select [ngModel]="bootstrap.theme.mode" (ngModelChange)="updateThemeMode($event)">
@for (option of themeModeOptions; track option.value) {
<option [value]="option.value">{{ option.labelKey | translate }}</option>
}
</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>
<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"><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"><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"><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"><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"><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"><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"><app-color-picker [ngModel]="bootstrap.theme.palette.danger" (ngModelChange)="updatePalette('danger', $event)" /></app-form-field>
<app-form-field [label]="'builder.themeModeLabel' | translate" [hint]="'builder.themeModeDesc' | translate">
<app-select [options]="themeModeSelectOptions()" [ngModel]="bootstrap.theme.mode" (ngModelChange)="updateThemeMode($event)" />
</app-form-field>
<app-form-field [label]="'builder.siteLayoutLabel' | translate" [hint]="'builder.siteLayoutDesc' | translate">
<app-select [options]="siteLayoutSelectOptions()" [ngModel]="bootstrap.layout?.type || 'default'" (ngModelChange)="updateSiteLayout($event)" />
</app-form-field>
</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 { ProjectEditorFacade } from '../facade/project-editor.facade';
import { TranslatePipe } from '../../../i18n/translate.pipe';
import { TranslateService } from '../../../i18n/translate.service';
import { PlatformLayoutType, ThemePaletteConfig } from '../../../shared/models/config';
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 {
value: 'light' | 'dark' | 'system';
@@ -20,13 +24,14 @@ export interface SiteLayoutOption {
@Component({
selector: 'app-project-editor-theme-section',
standalone: true,
imports: [FormsModule, TranslatePipe, FormFieldComponent],
imports: [FormsModule, TranslatePipe, FormFieldComponent, SectionCardComponent, SelectComponent, ColorPickerComponent],
templateUrl: './theme-section.component.html',
styleUrls: ['./section.shared.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ProjectEditorThemeSectionComponent {
private readonly facade = inject(ProjectEditorFacade);
private readonly translate = inject(TranslateService);
readonly bootstrap = this.facade.bootstrap;
readonly themeModeOptions: ThemeModeOption[] = [
@@ -42,6 +47,22 @@ export class ProjectEditorThemeSectionComponent {
{ 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 {
this.facade.updateBootstrap(current => ({
...current,
@@ -62,12 +83,4 @@ export class ProjectEditorThemeSectionComponent {
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 ?? '';
}
}