Skip to content

Commit b2e56ce

Browse files
authored
Merge pull request #79 from pawcoding/feat/import-color
Import colors from other palettes
2 parents 9df0fa5 + 66080cf commit b2e56ce

38 files changed

+978
-176
lines changed

src/app/editor/data-access/color-editor.service.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Injectable, inject, signal } from '@angular/core';
33
import { firstValueFrom, tap } from 'rxjs';
44
import { Color } from '../../shared/model';
55
import { sleep } from '../../shared/utils/sleep';
6+
import { EditorData } from '../editor.component';
67

78
@Injectable({
89
providedIn: 'root'
@@ -18,7 +19,7 @@ export class ColorEditorService {
1819
this._isModalOpen.set(true);
1920

2021
const editor = await import('../editor.component').then((c) => c.EditorComponent);
21-
const dialogRef = this._dialog.open<Color | undefined>(editor, {
22+
const dialogRef = this._dialog.open<Color | undefined, EditorData>(editor, {
2223
backdropClass: 'rp-modal-backdrop',
2324
data: {
2425
color,

src/app/editor/editor.component.html

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
<article
2-
#editor
32
class="mx-auto flex w-full max-w-md flex-col gap-4 rounded bg-neutral-100 p-4 shadow-md dark:border dark:border-neutral-600 dark:bg-neutral-700 dark:shadow-none"
43
>
54
<h2 class="font-semibold">{{ color().name }}</h2>
@@ -13,7 +12,7 @@ <h2 class="font-semibold">{{ color().name }}</h2>
1312
/>
1413

1514
<section class="flex flex-col gap-2">
16-
<rp-editor-range
15+
<rp-color-range-slider
1716
[label]="'common.hue' | translate"
1817
[tooltip]="'editor.properties.hue' | translate"
1918
[value]="shade().hsl.H"
@@ -24,7 +23,7 @@ <h2 class="font-semibold">{{ color().name }}</h2>
2423
min="0"
2524
/>
2625

27-
<rp-editor-range
26+
<rp-color-range-slider
2827
[label]="'common.saturation' | translate"
2928
[tooltip]="'editor.properties.saturation' | translate"
3029
[value]="shade().hsl.S"
@@ -33,7 +32,7 @@ <h2 class="font-semibold">{{ color().name }}</h2>
3332
key="saturation"
3433
/>
3534

36-
<rp-editor-range
35+
<rp-color-range-slider
3736
[label]="'common.lightness' | translate"
3837
[tooltip]="'editor.properties.lightness' | translate"
3938
[value]="shade().hsl.L"

src/app/editor/editor.component.ts

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,26 @@
11
import { DIALOG_DATA, DialogRef } from '@angular/cdk/dialog';
22
import { DecimalPipe } from '@angular/common';
3-
import { Component, ElementRef, computed, effect, inject, signal, viewChild } from '@angular/core';
3+
import { Component, computed, effect, inject, signal } from '@angular/core';
44
import { TranslateModule, TranslateService } from '@ngx-translate/core';
55
import { ColorService } from '../shared/data-access/color.service';
66
import { Color, Shade } from '../shared/model';
77
import { ColorInputComponent } from '../shared/ui/color-input/color-input.component';
8+
import { ColorRangeSliderComponent } from '../shared/ui/color-range-slider/color-range-slider.component';
89
import { textColor } from '../shared/utils/text-color';
9-
import { EditorRangeComponent } from './ui/editor-range/editor-range.component';
10+
11+
/**
12+
* Data for the editor dialog.
13+
*/
14+
export type EditorData = {
15+
/**
16+
* Color to edit.
17+
*/
18+
color: Color;
19+
/**
20+
* Shade to open the editor with.
21+
*/
22+
shadeIndex?: number;
23+
};
1024

1125
export enum UpdateType {
1226
HEX = 'hex',
@@ -18,20 +32,25 @@ export enum UpdateType {
1832
@Component({
1933
selector: 'rp-editor',
2034
standalone: true,
21-
imports: [ColorInputComponent, TranslateModule, DecimalPipe, EditorRangeComponent],
22-
templateUrl: './editor.component.html'
35+
imports: [ColorInputComponent, TranslateModule, DecimalPipe, ColorRangeSliderComponent],
36+
templateUrl: './editor.component.html',
37+
host: {
38+
'[style.--editor-saturation]': 'shade().hsl.S + "%"',
39+
'[style.--editor-lightness]': 'shade().hsl.L + "%"',
40+
'[style.--editor-hue]': 'shade().hsl.H'
41+
}
2342
})
2443
export class EditorComponent {
2544
protected readonly UpdateType = UpdateType;
2645
protected readonly textColor = textColor;
2746

28-
private readonly _data = inject<{ color: Color; shadeIndex?: number }>(DIALOG_DATA);
29-
private readonly _dialogRef = inject(DialogRef);
30-
private readonly _colorService = inject(ColorService);
31-
private readonly _translateService = inject(TranslateService);
47+
readonly #data = inject<EditorData>(DIALOG_DATA);
48+
readonly #dialogRef = inject(DialogRef);
49+
readonly #colorService = inject(ColorService);
50+
readonly #translateService = inject(TranslateService);
3251

33-
protected readonly color = signal(this._data.color.copy());
34-
protected readonly shadeIndex = signal(this._data.shadeIndex ?? 0);
52+
protected readonly color = signal(this.#data.color.copy());
53+
protected readonly shadeIndex = signal(this.#data.shadeIndex ?? 0);
3554

3655
protected readonly shade = computed<Shade>(() => {
3756
const selectedShade = this.color().shades.find((shade) => shade.index === this.shadeIndex());
@@ -48,20 +67,12 @@ export class EditorComponent {
4867
});
4968

5069
protected readonly hasUnsavedChanges = computed<boolean>(
51-
() => this._data.color.toString() !== this.color().toString()
70+
() => this.#data.color.toString() !== this.color().toString()
5271
);
5372

54-
private readonly _editor = viewChild.required<ElementRef<HTMLElement>>('editor');
55-
5673
public constructor() {
5774
effect(() => {
58-
this._editor().nativeElement.style.setProperty('--editor-hue', `${this.shade().hsl.H}`);
59-
this._editor().nativeElement.style.setProperty('--editor-saturation', `${this.shade().hsl.S}%`);
60-
this._editor().nativeElement.style.setProperty('--editor-lightness', `${this.shade().hsl.L}%`);
61-
});
62-
63-
effect(() => {
64-
this._dialogRef.disableClose = this.hasUnsavedChanges();
75+
this.#dialogRef.disableClose = this.hasUnsavedChanges();
6576
});
6677
}
6778

@@ -86,7 +97,7 @@ export class EditorComponent {
8697
}
8798

8899
shade.fixed = false;
89-
this._updateColor();
100+
this.updateColor();
90101
}
91102

92103
public update(type: UpdateType, value: string | number): void {
@@ -108,36 +119,36 @@ export class EditorComponent {
108119
break;
109120
}
110121

111-
this._updateColor();
122+
this.updateColor();
112123

113124
const editedShade = this.color().shades.find((s) => s.hex === shade.hex);
114125
this.shadeIndex.set(editedShade?.index ?? -1);
115126
}
116127

117128
protected cancel(): void {
118-
this._dialogRef.close(undefined);
119-
this.color.set(this._data.color.copy());
129+
this.#dialogRef.close(undefined);
130+
this.color.set(this.#data.color.copy());
120131
}
121132

122133
protected save(): void {
123-
this._dialogRef.close(this.color());
134+
this.#dialogRef.close(this.color());
124135
}
125136

126-
private _updateColor(): void {
137+
private updateColor(): void {
127138
const updatedColor = this.color().copy();
128-
this._colorService.regenerateShades(updatedColor);
139+
this.#colorService.regenerateShades(updatedColor);
129140
this.color.set(updatedColor);
130141
}
131142

132143
protected getTooltip(shade: Shade, selected: boolean): string {
133144
const tooltips: Array<string> = [];
134145

135146
if (!selected) {
136-
tooltips.push(this._translateService.instant('editor.shades'));
147+
tooltips.push(this.#translateService.instant('editor.shades'));
137148
}
138149

139150
if (shade.fixed) {
140-
tooltips.push(this._translateService.instant('editor.unfix'));
151+
tooltips.push(this.#translateService.instant('editor.unfix'));
141152
}
142153

143154
return tooltips.join('\n');

src/app/editor/ui/editor-range/editor-range.component.css

Lines changed: 0 additions & 39 deletions
This file was deleted.

src/app/editor/ui/editor-range/editor-range.component.html

Lines changed: 0 additions & 26 deletions
This file was deleted.

src/app/export/data-access/export-modal.service.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Dialog } from '@angular/cdk/dialog';
22
import { Injectable, inject, signal } from '@angular/core';
33
import { firstValueFrom, tap } from 'rxjs';
44
import { Palette } from '../../shared/model';
5+
import { ExportModalData } from '../export-modal.component';
56

67
@Injectable({
78
providedIn: 'root'
@@ -18,7 +19,7 @@ export class ExportModalService {
1819
this._isModalOpen.set(true);
1920

2021
const exportModal = await import('../export-modal.component').then((c) => c.ExportModalComponent);
21-
const dialogRef = this._dialog.open<void>(exportModal, {
22+
const dialogRef = this._dialog.open<void, ExportModalData>(exportModal, {
2223
backdropClass: 'rp-modal-backdrop',
2324
data: {
2425
palette

src/app/export/export-modal.component.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ import { ExportFormatComponent } from './ui/export-format/export-format.componen
1616
import { ExportSuccessComponent } from './ui/export-success/export-success.component';
1717
import { RequestFormatComponent } from './ui/request-format/request-format.component';
1818

19+
/**
20+
* Data for the export modal.
21+
*/
22+
export type ExportModalData = {
23+
/**
24+
* Palette to export.
25+
*/
26+
palette: Palette;
27+
};
28+
1929
enum ExportModalState {
2030
FORMAT = 'format',
2131
DOWNLOAD = 'download',
@@ -39,7 +49,7 @@ export class ExportModalComponent {
3949
protected readonly ExportModalState = ExportModalState;
4050
protected readonly ExportFormat = ExportFormat;
4151

42-
private readonly _data = inject<{ palette: Palette }>(DIALOG_DATA);
52+
private readonly _data = inject<ExportModalData>(DIALOG_DATA);
4353
private readonly _dialogRef = inject(DialogRef);
4454
private readonly _toastService = inject(ToastService);
4555
private readonly _exportService = inject(ExportService);

src/app/home/home.component.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
22
import { Router } from '@angular/router';
33
import { TranslateModule } from '@ngx-translate/core';
44
import { AnalyticsService, AnalyticsServiceMock } from '../shared/data-access/analytics.service';
5-
import { PaletteService, PaletteServiceMock } from '../shared/data-access/palette.service';
5+
import { PaletteService } from '../shared/data-access/palette.service';
6+
import { PaletteServiceMock } from '../shared/data-access/palette.service-mock';
67
import { HomeService, HomeServiceMock } from './data-access/home.service';
78
import HomeComponent from './home.component';
89

src/app/list/list.component.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import { ActivatedRoute } from '@angular/router';
33
import { TranslateModule } from '@ngx-translate/core';
44
import { DialogService, DialogServiceMock } from '../shared/data-access/dialog.service';
55
import { ListService, ListServiceMock } from '../shared/data-access/list.service';
6-
import { PaletteService, PaletteServiceMock } from '../shared/data-access/palette.service';
6+
import { PaletteService } from '../shared/data-access/palette.service';
7+
import { PaletteServiceMock } from '../shared/data-access/palette.service-mock';
78
import ListComponent from './list.component';
89

910
describe('ListComponent', () => {

src/app/shared/constants/tailwind-colors.ts

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -331,24 +331,28 @@ export const rose = new Color(
331331
'Rose'
332332
);
333333

334-
export const TailwindRainbow = new Palette('Tailwind Rainbow', [
335-
red,
336-
orange,
337-
amber,
338-
yellow,
339-
lime,
340-
green,
341-
emerald,
342-
teal,
343-
cyan,
344-
sky,
345-
blue,
346-
indigo,
347-
violet,
348-
purple,
349-
fuchsia,
350-
pink,
351-
rose
352-
]);
353-
export const TailwindGrays = new Palette('Tailwind Grays', [slate, gray, zinc, neutral, stone]);
354-
export const Tailwind = new Palette('Tailwind', [...TailwindRainbow.colors, ...TailwindGrays.colors]);
334+
export const TailwindRainbow = new Palette(
335+
'Tailwind Rainbow',
336+
[
337+
red,
338+
orange,
339+
amber,
340+
yellow,
341+
lime,
342+
green,
343+
emerald,
344+
teal,
345+
cyan,
346+
sky,
347+
blue,
348+
indigo,
349+
violet,
350+
purple,
351+
fuchsia,
352+
pink,
353+
rose
354+
],
355+
'tailwind-rainbow'
356+
);
357+
export const TailwindGrays = new Palette('Tailwind Grays', [slate, gray, zinc, neutral, stone], 'tailwind-grays');
358+
export const Tailwind = new Palette('Tailwind', [...TailwindRainbow.colors, ...TailwindGrays.colors], 'tailwind');

0 commit comments

Comments
 (0)